diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 2b4a5fccdaf..1fe08dc38cc 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ # Code of Conduct -Please read the [Go Community Code of Conduct](https://golang.org/conduct). +Please read the [Go Community Code of Conduct](https://github.com/cloudflare/go/wiki/Code-of-Conduct). diff --git a/.github/ISSUE_TEMPLATE/00-bug.yml b/.github/ISSUE_TEMPLATE/00-bug.yml deleted file mode 100644 index 5b0fda4950e..00000000000 --- a/.github/ISSUE_TEMPLATE/00-bug.yml +++ /dev/null @@ -1,94 +0,0 @@ -# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms -# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema -name: Bugs -description: The go command, standard library, or anything else -title: "import/path: issue title" - -body: - - type: markdown - attributes: - value: | - Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem. - - - type: input - id: go-version - attributes: - label: Go version - description: | - What version of Go are you using (`go version`)? - - Note: we only [support](https://go.dev/doc/devel/release#policy) the two most recent major releases. - placeholder: ex. go version go1.20.7 darwin/arm64 - validations: - required: true - - - type: textarea - id: go-env - attributes: - label: "Output of `go env` in your module/workspace:" - placeholder: | - GO111MODULE="" - GOARCH="arm64" - GOBIN="/Users/gopher/go/bin" - GOCACHE="/Users/gopher/go/cache" - GOENV="/Users/gopher/Library/Application Support/go/env" - GOEXE="" - GOEXPERIMENT="" - GOFLAGS="" - GOHOSTARCH="arm64" - GOHOSTOS="darwin" - GOINSECURE="" - GOMODCACHE="/Users/gopher/go/pkg/mod" - GONOPROXY="" - GONOSUMDB="" - GOOS="darwin" - GOPATH="/Users/gopher/go" - GOPRIVATE="" - GOPROXY="https://proxy.golang.org,direct" - GOROOT="/usr/local/go" - GOSUMDB="sum.golang.org" - GOTMPDIR="" - GOTOOLDIR="/usr/local/go/pkg/tool/darwin_arm64" - GOVCS="" - GOVERSION="go1.20.7" - GCCGO="gccgo" - AR="ar" - CC="clang" - CXX="clang++" - CGO_ENABLED="1" - GOMOD="/dev/null" - GOWORK="" - CGO_CFLAGS="-O2 -g" - CGO_CPPFLAGS="" - CGO_CXXFLAGS="-O2 -g" - CGO_FFLAGS="-O2 -g" - CGO_LDFLAGS="-O2 -g" - PKG_CONFIG="pkg-config" - GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/44/nbbyll_10jd0z8rj_qxm43740000gn/T/go-build2331607515=/tmp/go-build -gno-record-gcc-switches -fno-common" - render: shell - validations: - required: true - - - type: textarea - id: what-did-you-do - attributes: - label: "What did you do?" - description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best." - validations: - required: true - - - type: textarea - id: actual-behavior - attributes: - label: "What did you see happen?" - description: Command invocations and their associated output, functions with their arguments and return results, full stacktraces for panics (upload a file if it is very long), etc. Prefer copying text output over using screenshots. - validations: - required: true - - - type: textarea - id: expected-behavior - attributes: - label: "What did you expect to see?" - description: Why is the current output incorrect, and any additional context we may need to understand the issue. - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/01-pkgsite.yml b/.github/ISSUE_TEMPLATE/01-pkgsite.yml deleted file mode 100644 index aaf39b2928b..00000000000 --- a/.github/ISSUE_TEMPLATE/01-pkgsite.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Pkg.go.dev bugs or feature requests -description: Issues or feature requests for the documentation site -title: "x/pkgsite: issue title" -labels: ["pkgsite"] -body: - - type: markdown - attributes: - value: "Please answer these questions before submitting your issue. Thanks!" - - type: input - id: url - attributes: - label: "What is the URL of the page with the issue?" - validations: - required: true - - type: input - id: user-agent - attributes: - label: "What is your user agent?" - description: "You can find your user agent here: https://www.google.com/search?q=what+is+my+user+agent" - validations: - required: true - - type: textarea - id: screenshot - attributes: - label: "Screenshot" - description: "Please paste a screenshot of the page." - validations: - required: false - - type: textarea - id: what-did-you-do - attributes: - label: "What did you do?" - description: "If possible, provide a recipe for reproducing the error. Starting with a Private/Incognito tab/window may help rule out problematic browser extensions." - validations: - required: true - - type: textarea - id: actual-behavior - attributes: - label: "What did you see happen?" - validations: - required: true - - type: textarea - id: expected-behavior - attributes: - label: "What did you expect to see?" - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/02-pkgsite-removal.yml b/.github/ISSUE_TEMPLATE/02-pkgsite-removal.yml deleted file mode 100644 index 693f4999dcd..00000000000 --- a/.github/ISSUE_TEMPLATE/02-pkgsite-removal.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Pkg.go.dev package removal request -description: Request a package be removed from the documentation site (pkg.go.dev) -title: "x/pkgsite: package removal request for [type path here]" -labels: ["pkgsite/package-removal"] -body: - - type: markdown - attributes: - value: "Please answer these questions before submitting your issue. Thanks!" - - type: input - id: package-path - attributes: - label: "What is the path of the package that you would like to have removed?" - description: | - We can remove packages with a shared path prefix. - For example, a request for 'github.com/author' would remove all pkg.go.dev pages with that package path prefix. - validations: - required: true - - type: textarea - id: package-owner - attributes: - label: "Are you the owner of this package?" - description: | - Only the package owners can request to have their packages removed from pkg.go.dev. - If the package path doesn't include your github username, please provide some other form of proof of ownership. - validations: - required: true - - type: textarea - id: retraction-reason - attributes: - label: "What is the reason that you could not retract this package instead?" - description: | - Requesting we remove a module here only hides the generated documentation on pkg.go.dev. - It does not affect the behaviour of proxy.golang.org or the go command. - Instead we recommend using the retract directive which will be processed by all 3 of the above. - - If you have deleted your repo, please recreate it and publish a retraction. - - Retracting a module version involves adding a retract directive to your go.mod file and publishing a new version. - For example: https://github.com/jba/retract-demo/blob/main/go.mod#L5-L8. - See https://pkg.go.dev/about#removing-a-package for additional tips on retractions. - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/03-gopls.yml b/.github/ISSUE_TEMPLATE/03-gopls.yml deleted file mode 100644 index 5db1315f27e..00000000000 --- a/.github/ISSUE_TEMPLATE/03-gopls.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Gopls bugs or feature requests -description: Issues or feature requests for the Go language server (gopls) -title: "x/tools/gopls: issue title" -labels: ["gopls", "Tools"] -body: - - type: markdown - attributes: - value: "Please answer these questions before submitting your issue. Thanks!" - - type: input - id: gopls-version - attributes: - label: "gopls version" - description: "Output of `gopls -v version` on the command line" - validations: - required: true - - type: textarea - id: go-env - attributes: - label: "go env" - description: "Output of `go env` on the command line in your workspace directory" - render: shell - validations: - required: true - - type: textarea - id: what-did-you-do - attributes: - label: "What did you do?" - description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is better. A failing unit test is the best." - validations: - required: true - - type: textarea - id: actual-behavior - attributes: - label: "What did you see happen?" - validations: - required: true - - type: textarea - id: expected-behavior - attributes: - label: "What did you expect to see?" - validations: - required: true - - type: textarea - id: editor-and-settings - attributes: - label: "Editor and settings" - description: "Your editor and any settings you have configured (for example, your VSCode settings.json file)" - validations: - required: false - - type: textarea - id: logs - attributes: - label: "Logs" - description: "If possible please include gopls logs. Instructions for capturing them can be found here: https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md#capture-logs" - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/04-vuln.yml b/.github/ISSUE_TEMPLATE/04-vuln.yml deleted file mode 100644 index dd40af99c69..00000000000 --- a/.github/ISSUE_TEMPLATE/04-vuln.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Go vulnerability management - bugs and feature requests -description: Issues or feature requests about Go vulnerability management -title: "x/vuln: issue title" -labels: ["vulncheck or vulndb"] -body: - - type: markdown - attributes: - value: "Please answer these questions before submitting your issue. Thanks! To add a new vulnerability to the Go vulnerability database (https://vuln.go.dev), see https://go.dev/s/vulndb-report-new. To report an issue about a report, see https://go.dev/s/vulndb-report-feedback." - - type: textarea - id: govulncheck-version - attributes: - label: govulncheck version - description: What version of govulncheck are you using (`govulncheck -version`)? - placeholder: | - Go: devel go1.22-0262ea1ff9 Thu Oct 26 18:46:50 2023 +0000 - Scanner: govulncheck@v1.0.2-0.20231108200754-fcf7dff7b242 - DB: https://vuln.go.dev - DB updated: 2023-11-21 15:39:17 +0000 UTC - validations: - required: true - - type: textarea - id: reproduce-latest-version - attributes: - label: "Does this issue reproduce at the latest version of golang.org/x/vuln?" - validations: - required: true - - type: textarea - id: go-env - attributes: - label: "Output of `go env` in your module/workspace:" - render: shell - validations: - required: true - - type: textarea - id: what-did-you-do - attributes: - label: "What did you do?" - description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best." - validations: - required: true - - type: textarea - id: actual-behavior - attributes: - label: "What did you see happen?" - validations: - required: true - - type: textarea - id: expected-behavior - attributes: - label: "What did you expect to see?" - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/10-proposal.yml b/.github/ISSUE_TEMPLATE/10-proposal.yml deleted file mode 100644 index d2a256c5aeb..00000000000 --- a/.github/ISSUE_TEMPLATE/10-proposal.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Proposals -description: New external API or other notable changes -title: "proposal: import/path: proposal title" -labels: ["Proposal"] -body: - - type: markdown - attributes: - value: "Our proposal process is documented here: https://go.dev/s/proposal-process" - - type: textarea - id: proposal-details - attributes: - label: "Proposal Details" - description: "Please provide the details of your proposal here." - validations: - required: true diff --git a/.github/ISSUE_TEMPLATE/11-language-change.yml b/.github/ISSUE_TEMPLATE/11-language-change.yml deleted file mode 100644 index 37ba2d7e408..00000000000 --- a/.github/ISSUE_TEMPLATE/11-language-change.yml +++ /dev/null @@ -1,165 +0,0 @@ -name: Language Change Proposals -description: Changes to the language -labels: ["Proposal", "v2", "LanguageChange"] -title: "proposal: Go 2: proposal title" - - -body: - - type: markdown - attributes: - value: | - ## Our process for evaluating language changes can be found [here](https://go.googlesource.com/proposal/+/refs/heads/master#language-changes) - - - type: dropdown - id: author-go-experience - attributes: - label: "Go Programming Experience" - description: "Would you consider yourself a novice, intermediate, or experienced Go programmer?" - options: - - "Novice" - - "Intermediate" - - "Experienced" - default: 1 - - - type: input - id: author-other-languages-experience - attributes: - label: "Other Languages Experience" - description: "What other languages do you have experience with?" - placeholder: "Go, Python, JS, Rust" - validations: - required: false - - - type: checkboxes - id: related-idea - attributes: - label: "Related Idea" - options: - - label: "Has this idea, or one like it, been proposed before?" - - label: "Does this affect error handling?" - - label: "Is this about generics?" - - label: "Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit" - - - type: textarea - id: related-proposals - attributes: - label: Has this idea, or one like it, been proposed before? - description: If so, how does this proposal differ? - placeholder: | - Yes or No - - If yes, - 1. Mention the related proposals - 2. then describe how this proposal differs - validations: - required: true - - - type: textarea - id: error-handling-proposal - attributes: - label: Does this affect error handling? - description: If so, how does this differ from previous error handling proposals? - placeholder: | - Yes or No - - If yes, - 1.how does this differ from previous error handling proposals? - - validations: - required: true - - - type: textarea - id: generics-proposal - attributes: - label: Is this about generics? - description: If so, how does this relate to the accepted design and other generics proposals? - placeholder: | - Yes or No - - If yes, - 1. how does this relate to the accepted design and other generics proposals? - - validations: - required: true - - - type: textarea - id: proposal - attributes: - label: "Proposal" - description: "What is the proposed change? Who does this proposal help, and why? Please describe as precisely as possible the change to the language." - validations: - required: true - - - type: textarea - id: language-spec-changes - attributes: - label: "Language Spec Changes" - description: "What would change in the language spec?" - validations: - required: false - - - type: textarea - id: informal-change - attributes: - label: "Informal Change" - description: "Please also describe the change informally, as in a class teaching Go." - validations: - required: false - - - type: textarea - id: go-backwards-compatiblity - attributes: - label: Is this change backward compatible? - description: Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit. - placeholder: | - Yes or No - - If yes, - 1. Show example code before and after the change. - - validations: - required: true - - - type: textarea - id: orthogonality - attributes: - label: "Orthogonality: How does this change interact or overlap with existing features?" - description: "Is the goal of this change a performance improvement? If so, what quantifiable improvement should we expect? How would we measure it?" - validations: - required: false - - - type: textarea - id: learning-curve - attributes: - label: "Would this change make Go easier or harder to learn, and why?" - - - type: textarea - id: cost-description - attributes: - label: "Cost Description" - description: "What is the cost of this proposal? (Every language change has a cost)" - - - type: input - id: go-toolchain - attributes: - label: Changes to Go ToolChain - description: "How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected? " - validations: - required: false - - - type: input - id: perf-costs - attributes: - label: Performance Costs - description: "What is the compile time cost? What is the run time cost? " - validations: - required: false - - - type: textarea - id: prototype - attributes: - label: "Prototype" - description: "Can you describe a possible implementation?" - validations: - required: false - diff --git a/.github/ISSUE_TEMPLATE/12-telemetry.yml b/.github/ISSUE_TEMPLATE/12-telemetry.yml deleted file mode 100644 index 4215abfa990..00000000000 --- a/.github/ISSUE_TEMPLATE/12-telemetry.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Go Telemetry Proposals -description: New telemetry counter or update on an existing one -title: "x/telemetry/config: proposal title" -labels: ["Telemetry-Proposal"] -projects: ["golang/29"] -body: -- type: textarea - attributes: - label: Counter names - description: Names of counters to add or update. - validations: - required: true -- type: textarea - attributes: - label: Description - description: What do these counters measure? - validations: - required: true -- type: textarea - attributes: - label: Rationale - description: | - Why is the counter important? - For example, what new insights will it provide, and how will that information be used? - If this is about updating existing counters, why is the change necessary? - validations: - required: true -- type: textarea - attributes: - label: Do the counters carry sensitive user information? - validations: - required: true -- type: textarea - attributes: - label: How? - description: | - How do we plan to compute the info? - If available, include the code location or cl that uses the golang.org/x/telemetry/counter API. - validations: - required: true -- type: textarea - attributes: - label: Proposed Graph Config - description: | - Approved telemetry counters are maintained as [Go Telemetry Graph Config](https://golang.org/x/telemetry/internal/graphconfig) records. - Please draft the record entry for your proposal here. - If multiple records need to be included, separate them with `---` lines. - You can check the list of the approved counters and their current configuration in [config.txt](https://go.googlesource.com/telemetry/+/master/internal/configgen/config.txt). - render: Text - value: | - counter: gopls/bug - title: Gopls bug reports - description: Stacks of bugs encountered on the gopls server. - type: partition, histogram, stack # choose only one. - program: golang.org/x/tools/gopls - counter: gopls/bug - depth: 16 # only if type is stack. - version: v0.13.0 # the first binary version containing this counter. - validations: - required: true -- type: dropdown - attributes: - label: New or Update - description: Is this a new counter? See [config.txt](https://go.googlesource.com/telemetry/+/master/internal/configgen/config.txt) for the list of approved counters. - options: - - New - - Update - default: 0 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index d6257daf2fa..00000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,5 +0,0 @@ -blank_issues_enabled: true -contact_links: - - name: Questions - about: Please use one of the forums for questions or general discussions - url: https://go.dev/wiki/Questions diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 2e978b61380..ab808776bbd 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -1,25 +1 @@ -This PR will be imported into Gerrit with the title and first -comment (this text) used to generate the subject and body of -the Gerrit change. - -**Please ensure you adhere to every item in this list.** - -More info can be found at https://github.com/golang/go/wiki/CommitMessage - -+ The PR title is formatted as follows: `net/http: frob the quux before blarfing` - + The package name goes before the colon - + The part after the colon uses the verb tense + phrase that completes the blank in, - "This change modifies Go to ___________" - + Lowercase verb after the colon - + No trailing period - + Keep the title as short as possible. ideally under 76 characters or shorter -+ No Markdown -+ The first PR comment (this one) is wrapped at 76 characters, unless it's - really needed (ASCII art, table, or long link) -+ If there is a corresponding issue, add either `Fixes #1234` or `Updates #1234` - (the latter if this is not a complete fix) to this comment -+ If referring to a repo other than `golang/go` you can use the - `owner/repo#issue_number` syntax: `Fixes golang/tools#1234` -+ We do not use Signed-off-by lines in Go. Please don't add them. - Our Gerrit server & GitHub bots enforce CLA compliance instead. -+ Delete these instructions once you have read and applied them +Most PRs should be linked to an issue. See https://github.com/cloudflare/go/wiki/Contributing for guidance on when and how to open a PR. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000000..5313f10ae83 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,15 @@ +name: Go Toolchain Tests +on: + pull_request: + push: + branches: + - cf + - '*/cf-**' +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run tests + run: ./all.bash + working-directory: src diff --git a/README.md b/README.md index 98f968218e5..893f111a4f8 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,25 @@ -# The Go Programming Language +🚨 This fork is offered as-is, and without guarantees. It is expected that +changes in the code, repository, and API occur in the future. We recommend to take +caution before using this library in production. -Go is an open source programming language that makes it easy to build simple, -reliable, and efficient software. +# cfgo -![Gopher image](https://golang.org/doc/gopher/fiveyears.jpg) -*Gopher image by [Renee French][rf], licensed under [Creative Commons 4.0 Attributions license][cc4-by].* +This is an experimental fork of Go, that patches the TLS stack, to support: -Our canonical Git repository is located at https://go.googlesource.com/go. -There is a mirror of the repository at https://github.com/golang/go. +1. [Encrypted ClientHello (ECH)](https://blog.cloudflare.com/encrypted-client-hello/) +2. [Post-quantum key agreement](https://blog.cloudflare.com/post-quantum-for-all/) +3. [Delegated Credentials](https://blog.cloudflare.com/keyless-delegation/) +4. Post-quantum certificates. +5. Configuraton of keyshares sent in ClientHello with `tls.Config.ClientCurveGuess`. -Unless otherwise noted, the Go source files are distributed under the -BSD-style license found in the LICENSE file. +To use upstream Go and this fork with the same codebase, this fork sets the `cfgo` build tag. -### Download and Install +## Build -#### Binary Distributions +``` +$ git clone https://github.com/cloudflare/go +$ cd go/src +$ ./make.bash +``` -Official binary distributions are available at https://go.dev/dl/. - -After downloading a binary release, visit https://go.dev/doc/install -for installation instructions. - -#### Install From Source - -If a binary distribution is not available for your combination of -operating system and architecture, visit -https://go.dev/doc/install/source -for source installation instructions. - -### Contributing - -Go is the work of thousands of contributors. We appreciate your help! - -To contribute, please read the contribution guidelines at https://go.dev/doc/contribute. - -Note that the Go project uses the issue tracker for bug reports and -proposals only. See https://go.dev/wiki/Questions for a list of -places to ask questions about the Go language. - -[rf]: https://reneefrench.blogspot.com/ -[cc4-by]: https://creativecommons.org/licenses/by/4.0/ + You can now use `../bin/go` as you would regular `go`. diff --git a/VERSION b/VERSION index 33dc5adf643..7f3b0d2dc6c 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -go1.22.5 +go1.22.5-devel-cf time 2024-06-27T20:11:12Z diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000000..c183cf75d41 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,16 @@ +version: "3.8" +services: + # build + build: + image: &image ${GO_DOCKER_IMAGE:-golang} + command: ./make.bash + working_dir: /work/repo/src + volumes: + - .:/work/repo + # build and run the full test suite + test: + image: *image + command: ./all.bash + working_dir: /work/repo/src + volumes: + - .:/work/repo diff --git a/go.env b/go.env index 6ff2b921d46..e87f6e7b6d8 100644 --- a/go.env +++ b/go.env @@ -9,4 +9,4 @@ GOSUMDB=sum.golang.org # Automatically download newer toolchains as directed by go.mod files. # See https://go.dev/doc/toolchain for details. -GOTOOLCHAIN=auto +GOTOOLCHAIN=local diff --git a/src/cmd/api/api_test.go b/src/cmd/api/api_test.go index ba358d364d5..5c4d59e10ed 100644 --- a/src/cmd/api/api_test.go +++ b/src/cmd/api/api_test.go @@ -166,7 +166,7 @@ func TestCompareAPI(t *testing.T) { } for _, tt := range tests { buf := new(strings.Builder) - gotOK := compareAPI(buf, tt.features, tt.required, tt.exception) + gotOK := compareAPI(buf, tt.features, tt.required, tt.exception, false) if gotOK != tt.ok { t.Errorf("%s: ok = %v; want %v", tt.name, gotOK, tt.ok) } diff --git a/src/cmd/api/main_test.go b/src/cmd/api/main_test.go index 7985055b5c0..fd7624ccf71 100644 --- a/src/cmd/api/main_test.go +++ b/src/cmd/api/main_test.go @@ -180,7 +180,12 @@ func Check(t *testing.T) { if exitCode == 1 { t.Errorf("API database problems found") } - if !compareAPI(bw, features, required, exception) { + // The CF Go fork adds new APIs to crypto/x509 and crypto/tls, make sure + // that these do not fail the "API check" test. API additions could be + // tracked in files such as api/go1.000.txt, but since there are no API + // stability commitments, the extra work to maintain it is not worth it. + allowNew := strings.Contains(runtime.Version(), "-cf") + if !compareAPI(bw, features, required, exception, allowNew) { t.Errorf("API differences found") } } @@ -226,7 +231,7 @@ func portRemoved(feature string) bool { strings.Contains(feature, "(darwin-386-cgo)") } -func compareAPI(w io.Writer, features, required, exception []string) (ok bool) { +func compareAPI(w io.Writer, features, required, exception []string, allowNew bool) (ok bool) { ok = true featureSet := set(features) @@ -262,8 +267,10 @@ func compareAPI(w io.Writer, features, required, exception []string) (ok bool) { } case len(required) == 0 || (len(features) > 0 && required[0] > features[0]): newFeature := take(&features) - fmt.Fprintf(w, "+%s\n", newFeature) - ok = false // feature not in api/next/* + if !allowNew { + fmt.Fprintf(w, "+%s\n", newFeature) + ok = false // feature not in api/next/* + } default: take(&required) take(&features) diff --git a/src/crypto/internal/bigmod/_asm/go.mod b/src/crypto/internal/bigmod/_asm/go.mod index 7600a4abbe1..0159d00e4e1 100644 --- a/src/crypto/internal/bigmod/_asm/go.mod +++ b/src/crypto/internal/bigmod/_asm/go.mod @@ -6,7 +6,7 @@ require github.com/mmcloughlin/avo v0.4.0 require ( golang.org/x/mod v0.4.2 // indirect - golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 // indirect + golang.org/x/sys v0.1.0 // indirect golang.org/x/tools v0.1.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/crypto/internal/bigmod/_asm/go.sum b/src/crypto/internal/bigmod/_asm/go.sum index b4b59140f0d..87455949c44 100644 --- a/src/crypto/internal/bigmod/_asm/go.sum +++ b/src/crypto/internal/bigmod/_asm/go.sum @@ -16,8 +16,9 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 h1:giLT+HuUP/gXYrG2Plg9WTjj4qhfgaW424ZIFog3rlk= golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/src/crypto/tls/alert.go b/src/crypto/tls/alert.go index 33022cd2b4b..aba46055368 100644 --- a/src/crypto/tls/alert.go +++ b/src/crypto/tls/alert.go @@ -58,6 +58,7 @@ const ( alertUnknownPSKIdentity alert = 115 alertCertificateRequired alert = 116 alertNoApplicationProtocol alert = 120 + alertECHRequired alert = 121 ) var alertText = map[alert]string{ @@ -94,6 +95,7 @@ var alertText = map[alert]string{ alertUnknownPSKIdentity: "unknown PSK identity", alertCertificateRequired: "certificate required", alertNoApplicationProtocol: "no application protocol", + alertECHRequired: "ECH required", } func (e alert) String() string { diff --git a/src/crypto/tls/auth.go b/src/crypto/tls/auth.go index 7c5675c6d93..604e4315409 100644 --- a/src/crypto/tls/auth.go +++ b/src/crypto/tls/auth.go @@ -15,6 +15,9 @@ import ( "fmt" "hash" "io" + + circlPki "github.com/cloudflare/circl/pki" + circlSign "github.com/cloudflare/circl/sign" ) // verifyHandshakeSignature verifies a signature against pre-hashed @@ -55,7 +58,17 @@ func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc c return err } default: - return errors.New("internal error: unknown signature type") + scheme := circlSchemeBySigType(sigType) + if scheme == nil { + return errors.New("internal error: unknown signature type") + } + pubKey, ok := pubkey.(circlSign.PublicKey) + if !ok { + return fmt.Errorf("expected a %s public key, got %T", scheme.Name(), pubkey) + } + if !scheme.Verify(pubKey, signed, sig, nil) { + return fmt.Errorf("%s verification failure", scheme.Name()) + } } return nil } @@ -106,7 +119,15 @@ func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType case Ed25519: sigType = signatureEd25519 default: - return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) + scheme := circlPki.SchemeByTLSID(uint(signatureAlgorithm)) + if scheme == nil { + return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) + } + sigType = sigTypeByCirclScheme(scheme) + if sigType == 0 { + return 0, 0, fmt.Errorf("circl scheme %s not supported", + scheme.Name()) + } } switch signatureAlgorithm { case PKCS1WithSHA1, ECDSAWithSHA1: @@ -120,7 +141,11 @@ func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType case Ed25519: hash = directSigning default: - return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) + scheme := circlPki.SchemeByTLSID(uint(signatureAlgorithm)) + if scheme == nil { + return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) + } + hash = directSigning } return sigType, hash, nil } @@ -140,6 +165,8 @@ func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash c // full signature, and not even OpenSSL bothers with the // complexity, so we can't even test it properly. return 0, 0, fmt.Errorf("tls: Ed25519 public keys are not supported before TLS 1.2") + case circlSign.PublicKey: + return 0, 0, fmt.Errorf("tls: circl public keys are not supported before TLS 1.2") default: return 0, 0, fmt.Errorf("tls: unsupported public key: %T", pub) } @@ -210,6 +237,13 @@ func signatureSchemesForCertificate(version uint16, cert *Certificate) []Signatu } case ed25519.PublicKey: sigAlgs = []SignatureScheme{Ed25519} + case circlSign.PublicKey: + scheme := pub.Scheme() + tlsScheme, ok := scheme.(circlPki.TLSScheme) + if !ok { + return nil + } + sigAlgs = []SignatureScheme{SignatureScheme(tlsScheme.TLSIdentifier())} default: return nil } @@ -226,6 +260,28 @@ func signatureSchemesForCertificate(version uint16, cert *Certificate) []Signatu return sigAlgs } +// selectSignatureSchemeDC picks a SignatureScheme from the peer's preference list +// that works with the selected delegated credential. It's only called for protocol +// versions that support delegated credential, so TLS 1.3. +func selectSignatureSchemeDC(vers uint16, dc *DelegatedCredential, peerAlgs []SignatureScheme, peerAlgsDC []SignatureScheme) (SignatureScheme, error) { + if vers != VersionTLS13 { + return 0, errors.New("unsupported TLS version for dc") + } + + if !isSupportedSignatureAlgorithm(dc.algorithm, peerAlgs) { + return undefinedSignatureScheme, errors.New("tls: peer doesn't support the delegated credential's signature") + } + + // Pick signature scheme in the peer's preference order, as our + // preference order is not configurable. + for _, preferredAlg := range peerAlgsDC { + if preferredAlg == dc.cred.expCertVerfAlgo { + return preferredAlg, nil + } + } + return 0, errors.New("tls: peer doesn't support the delegated credential's signature algorithm") +} + // selectSignatureScheme picks a SignatureScheme from the peer's preference list // that works with the selected certificate. It's only called for protocol // versions that support signature algorithms, so TLS 1.2 and 1.3. diff --git a/src/crypto/tls/auth_test.go b/src/crypto/tls/auth_test.go index c23d93f3c08..f4fd4f0b92c 100644 --- a/src/crypto/tls/auth_test.go +++ b/src/crypto/tls/auth_test.go @@ -7,6 +7,8 @@ package tls import ( "crypto" "testing" + + circlPki "github.com/cloudflare/circl/pki" ) func TestSignatureSelection(t *testing.T) { @@ -161,7 +163,7 @@ func TestSupportedSignatureAlgorithms(t *testing.T) { if sigType == 0 { t.Errorf("%v: missing signature type", sigAlg) } - if hash == 0 && sigAlg != Ed25519 { + if hash == 0 && sigAlg != Ed25519 && circlPki.SchemeByTLSID(uint(sigAlg)) == nil { t.Errorf("%v: missing hash", sigAlg) } } diff --git a/src/crypto/tls/cfevent.go b/src/crypto/tls/cfevent.go new file mode 100644 index 00000000000..bc092b811d6 --- /dev/null +++ b/src/crypto/tls/cfevent.go @@ -0,0 +1,184 @@ +// Copyright 2023 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import "time" + +// CFEvent is a value emitted at various points in the handshake that is +// handled by the callback Config.CFEventHandler. +type CFEvent interface { + Name() string +} + +// CFEventTLS13ClientHandshakeTimingInfo carries intra-stack time durations for +// TLS 1.3 client-state machine changes. It can be used for tracking metrics +// during a connection. Some durations may be sensitive, such as the amount of +// time to process a particular handshake message, so this event should only be +// used for experimental purposes. +type CFEventTLS13ClientHandshakeTimingInfo struct { + timer func() time.Time + start time.Time + WriteClientHello time.Duration + ProcessServerHello time.Duration + ReadEncryptedExtensions time.Duration + ReadCertificate time.Duration + ReadCertificateVerify time.Duration + ReadServerFinished time.Duration + WriteCertificate time.Duration + WriteCertificateVerify time.Duration + WriteClientFinished time.Duration +} + +// Name is required by the CFEvent interface. +func (e CFEventTLS13ClientHandshakeTimingInfo) Name() string { + return "TLS13ClientHandshakeTimingInfo" +} + +func (e CFEventTLS13ClientHandshakeTimingInfo) elapsedTime() time.Duration { + if e.timer == nil { + return 0 + } + return e.timer().Sub(e.start) +} + +func createTLS13ClientHandshakeTimingInfo(timerFunc func() time.Time) CFEventTLS13ClientHandshakeTimingInfo { + timer := time.Now + if timerFunc != nil { + timer = timerFunc + } + + return CFEventTLS13ClientHandshakeTimingInfo{ + timer: timer, + start: timer(), + } +} + +// CFEventTLS13ServerHandshakeTimingInfo carries intra-stack time durations +// for TLS 1.3 state machine changes. It can be used for tracking metrics during a +// connection. Some durations may be sensitive, such as the amount of time to +// process a particular handshake message, so this event should only be used +// for experimental purposes. +type CFEventTLS13ServerHandshakeTimingInfo struct { + timer func() time.Time + start time.Time + ProcessClientHello time.Duration + WriteServerHello time.Duration + WriteEncryptedExtensions time.Duration + WriteCertificate time.Duration + WriteCertificateVerify time.Duration + WriteServerFinished time.Duration + ReadCertificate time.Duration + ReadCertificateVerify time.Duration + ReadClientFinished time.Duration +} + +// Name is required by the CFEvent interface. +func (e CFEventTLS13ServerHandshakeTimingInfo) Name() string { + return "TLS13ServerHandshakeTimingInfo" +} + +func (e CFEventTLS13ServerHandshakeTimingInfo) elapsedTime() time.Duration { + if e.timer == nil { + return 0 + } + return e.timer().Sub(e.start) +} + +func createTLS13ServerHandshakeTimingInfo(timerFunc func() time.Time) CFEventTLS13ServerHandshakeTimingInfo { + timer := time.Now + if timerFunc != nil { + timer = timerFunc + } + + return CFEventTLS13ServerHandshakeTimingInfo{ + timer: timer, + start: timer(), + } +} + +const ( + // Constants for ECH status events. + echStatusBypassed = 1 + iota + echStatusInner + echStatusOuter +) + +// CFEventECHClientStatus is emitted once it is known whether the client +// bypassed, offered, or greased ECH. +type CFEventECHClientStatus int + +// Bypassed returns true if the client bypassed ECH. +func (e CFEventECHClientStatus) Bypassed() bool { + return e == echStatusBypassed +} + +// Offered returns true if the client offered ECH. +func (e CFEventECHClientStatus) Offered() bool { + return e == echStatusInner +} + +// Greased returns true if the client greased ECH. +func (e CFEventECHClientStatus) Greased() bool { + return e == echStatusOuter +} + +// Name is required by the CFEvent interface. +func (e CFEventECHClientStatus) Name() string { + return "ech client status" +} + +// CFEventECHServerStatus is emitted once it is known whether the client +// bypassed, offered, or greased ECH. +type CFEventECHServerStatus int + +// Bypassed returns true if the client bypassed ECH. +func (e CFEventECHServerStatus) Bypassed() bool { + return e == echStatusBypassed +} + +// Accepted returns true if the client offered ECH. +func (e CFEventECHServerStatus) Accepted() bool { + return e == echStatusInner +} + +// Rejected returns true if the client greased ECH. +func (e CFEventECHServerStatus) Rejected() bool { + return e == echStatusOuter +} + +// Name is required by the CFEvent interface. +func (e CFEventECHServerStatus) Name() string { + return "ech server status" +} + +// CFEventECHPublicNameMismatch is emitted if the outer SNI does not match +// match the public name of the ECH configuration. Note that we do not record +// the outer SNI in order to avoid collecting this potentially sensitive data. +type CFEventECHPublicNameMismatch struct{} + +// Name is required by the CFEvent interface. +func (e CFEventECHPublicNameMismatch) Name() string { + return "ech public name does not match outer sni" +} + +// For backwards compatibility. +type CFEventTLS13NegotiatedKEX = CFEventTLSNegotiatedNamedKEX + +// CFEventTLSNegotiatedNamedKEX is emitted when a key agreement mechanism has been +// established that uses a named group. This includes all key agreements +// in TLSv1.3, but excludes RSA and DH in TLS 1.2 and earlier. +type CFEventTLSNegotiatedNamedKEX struct { + KEX CurveID +} + +func (e CFEventTLSNegotiatedNamedKEX) Name() string { + return "CFEventTLSNegotiatedNamedKEX" +} + +// CFEventTLS13HRR is emitted when a HRR is sent or received +type CFEventTLS13HRR struct{} + +func (e CFEventTLS13HRR) Name() string { + return "CFEventTLS13HRR" +} diff --git a/src/crypto/tls/cfgo_test.go b/src/crypto/tls/cfgo_test.go new file mode 100644 index 00000000000..bbc70d2ad54 --- /dev/null +++ b/src/crypto/tls/cfgo_test.go @@ -0,0 +1,9 @@ +//go:build !cfgo + +package tls + +import "testing" + +func TestCfgoBuildTag(t *testing.T) { + t.Error("Build tag cfgo is expected to be set for this toolchain") +} diff --git a/src/crypto/tls/cfkem.go b/src/crypto/tls/cfkem.go new file mode 100644 index 00000000000..7f1bb6cd5bf --- /dev/null +++ b/src/crypto/tls/cfkem.go @@ -0,0 +1,101 @@ +// Copyright 2022 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. +// +// Glue to add Circl's (post-quantum) hybrid KEMs. +// +// To enable set CurvePreferences with the desired scheme as the first element: +// +// import ( +// "crypto/tls" +// +// [...] +// +// config.CurvePreferences = []tls.CurveID{ +// tls.X25519Kyber768Draft00, +// tls.X25519, +// tls.P256, +// } + +package tls + +import ( + "fmt" + "io" + + "github.com/cloudflare/circl/hpke" + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/kem/hybrid" +) + +// Either *ecdh.PrivateKey or *kemPrivateKey +type singleClientKeySharePrivate interface{} + +type clientKeySharePrivate map[CurveID]singleClientKeySharePrivate + +type kemPrivateKey struct { + secretKey kem.PrivateKey + curveID CurveID +} + +var ( + X25519Kyber512Draft00 = CurveID(0xfe30) + X25519Kyber768Draft00 = CurveID(0x6399) + X25519Kyber768Draft00Old = CurveID(0xfe31) + P256Kyber768Draft00 = CurveID(0xfe32) + X25519MLKEM768 = CurveID(0x11ec) + invalidCurveID = CurveID(0) + + // A key agreeement similar in size but purposefully incompatible with + // X25519. The goal is to have a key agreement that servers will not + // support, so we can test HelloRetryRquest. + DummyKex = CurveID(0xfe33) +) + +func singleClientKeySharePrivateFor(ks clientKeySharePrivate, group CurveID) singleClientKeySharePrivate { + ret, _ := ks[group] + return ret +} + +// Returns scheme by CurveID if supported by Circl +func curveIdToCirclScheme(id CurveID) kem.Scheme { + switch id { + case X25519Kyber512Draft00: + return hybrid.Kyber512X25519() + case X25519Kyber768Draft00, X25519Kyber768Draft00Old: + return hybrid.Kyber768X25519() + case P256Kyber768Draft00: + return hybrid.P256Kyber768Draft00() + case X25519MLKEM768: + return hybrid.X25519MLKEM768() + case DummyKex: + return hpke.KEM_X25519_HKDF_SHA256.Scheme() + } + return nil +} + +// Generate a new shared secret and encapsulates it for the packed +// public key in ppk using randomness from rnd. +func encapsulateForKem(scheme kem.Scheme, rnd io.Reader, ppk []byte) ( + ct, ss []byte, alert alert, err error) { + pk, err := scheme.UnmarshalBinaryPublicKey(ppk) + if err != nil { + return nil, nil, alertIllegalParameter, fmt.Errorf("unpack pk: %w", err) + } + seed := make([]byte, scheme.EncapsulationSeedSize()) + if _, err := io.ReadFull(rnd, seed); err != nil { + return nil, nil, alertInternalError, fmt.Errorf("random: %w", err) + } + ct, ss, err = scheme.EncapsulateDeterministically(pk, seed) + return ct, ss, alertIllegalParameter, err +} + +// Generate a new keypair using randomness from rnd. +func generateKemKeyPair(scheme kem.Scheme, curveID CurveID, rnd io.Reader) ( + kem.PublicKey, *kemPrivateKey, error) { + seed := make([]byte, scheme.SeedSize()) + if _, err := io.ReadFull(rnd, seed); err != nil { + return nil, nil, err + } + pk, sk := scheme.DeriveKeyPair(seed) + return pk, &kemPrivateKey{sk, curveID}, nil +} diff --git a/src/crypto/tls/cfkem_test.go b/src/crypto/tls/cfkem_test.go new file mode 100644 index 00000000000..cf59ac5f3af --- /dev/null +++ b/src/crypto/tls/cfkem_test.go @@ -0,0 +1,153 @@ +// Copyright 2022 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "context" + "fmt" + "testing" +) + +func testHybridKEX(t *testing.T, curveID CurveID, clientPQ, serverPQ, + clientTLS12, serverTLS12 bool) { + var clientSelectedKEX *CurveID + var retry bool + + clientConfig := testConfig.Clone() + if clientPQ { + clientConfig.CurvePreferences = []CurveID{curveID, X25519} + } + clientCFEventHandler := func(ev CFEvent) { + switch e := ev.(type) { + case CFEventTLSNegotiatedNamedKEX: + clientSelectedKEX = &e.KEX + case CFEventTLS13HRR: + retry = true + } + } + if clientTLS12 { + clientConfig.MaxVersion = VersionTLS12 + } + + serverConfig := testConfig.Clone() + if serverPQ { + serverConfig.CurvePreferences = []CurveID{curveID, X25519} + } else { + serverConfig.CurvePreferences = []CurveID{X25519} + } + if serverTLS12 { + serverConfig.MaxVersion = VersionTLS12 + } + + c, s := localPipe(t) + done := make(chan error) + defer c.Close() + + go func() { + defer s.Close() + done <- Server(s, serverConfig).Handshake() + }() + + cli := Client(c, clientConfig) + cCtx := context.WithValue(context.Background(), CFEventHandlerContextKey{}, clientCFEventHandler) + clientErr := cli.HandshakeContext(cCtx) + serverErr := <-done + if clientErr != nil { + t.Errorf("client error: %s", clientErr) + } + if serverErr != nil { + t.Errorf("server error: %s", serverErr) + } + + var expectedKEX CurveID + var expectedRetry bool + + if clientPQ && serverPQ && !clientTLS12 && !serverTLS12 { + expectedKEX = curveID + } else { + expectedKEX = X25519 + } + if !clientTLS12 && clientPQ && !serverPQ { + expectedRetry = true + } + + if expectedRetry != retry { + t.Errorf("Expected retry=%v, got retry=%v", expectedRetry, retry) + } + if clientSelectedKEX == nil { + t.Error("No KEX happened?") + } else if *clientSelectedKEX != expectedKEX { + t.Errorf("failed to negotiate: expected %d, got %d", + expectedKEX, *clientSelectedKEX) + } +} + +func TestHybridKEX(t *testing.T) { + run := func(curveID CurveID, clientPQ, serverPQ, clientTLS12, serverTLS12 bool) { + t.Run(fmt.Sprintf("%#04x serverPQ:%v clientPQ:%v serverTLS12:%v clientTLS12:%v", uint16(curveID), + serverPQ, clientPQ, serverTLS12, clientTLS12), func(t *testing.T) { + testHybridKEX(t, curveID, clientPQ, serverPQ, clientTLS12, serverTLS12) + }) + } + for _, curveID := range []CurveID{ + X25519Kyber512Draft00, + X25519Kyber768Draft00, + X25519Kyber768Draft00Old, + P256Kyber768Draft00, + X25519MLKEM768, + DummyKex, + } { + run(curveID, true, true, false, false) + run(curveID, true, false, false, false) + run(curveID, false, true, false, false) + run(curveID, true, true, true, false) + run(curveID, true, true, false, true) + run(curveID, true, true, true, true) + } +} + +func TestClientCurveGuess(t *testing.T) { + run := func(guess, clientPrefs, serverPrefs []CurveID) { + t.Run( + fmt.Sprintf("guess=%v clientPrefs=%v serverPrefs=%v", + guess, clientPrefs, serverPrefs), + func(t *testing.T) { + testClientCurveGuess(t, guess, clientPrefs, serverPrefs) + }) + } + both := []CurveID{X25519Kyber768Draft00, X25519} + run([]CurveID{}, []CurveID{X25519}, both) + run([]CurveID{X25519}, []CurveID{X25519}, both) + run([]CurveID{X25519Kyber768Draft00}, both, []CurveID{X25519}) + run(both, both, both) + run(both, both, []CurveID{X25519}) + run(both, both, []CurveID{X25519Kyber768Draft00}) +} + +func testClientCurveGuess(t *testing.T, guess, clientPrefs, serverPrefs []CurveID) { + clientConfig := testConfig.Clone() + serverConfig := testConfig.Clone() + serverConfig.CurvePreferences = serverPrefs + clientConfig.CurvePreferences = clientPrefs + clientConfig.ClientCurveGuess = guess + + c, s := localPipe(t) + done := make(chan error) + defer c.Close() + + go func() { + defer s.Close() + done <- Server(s, serverConfig).Handshake() + }() + + cli := Client(c, clientConfig) + clientErr := cli.HandshakeContext(context.Background()) + serverErr := <-done + if clientErr != nil { + t.Errorf("client error: %v", clientErr) + } + if serverErr != nil { + t.Errorf("server error: %v", serverErr) + } +} diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 849e8b0a209..60c3b2d0883 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -112,6 +112,7 @@ const ( extensionALPN uint16 = 16 extensionSCT uint16 = 18 extensionExtendedMasterSecret uint16 = 23 + extensionDelegatedCredentials uint16 = 34 extensionSessionTicket uint16 = 35 extensionPreSharedKey uint16 = 41 extensionEarlyData uint16 = 42 @@ -123,6 +124,8 @@ const ( extensionKeyShare uint16 = 51 extensionQUICTransportParameters uint16 = 57 extensionRenegotiationInfo uint16 = 0xff01 + extensionECH uint16 = 0xfe0d // draft-ietf-tls-esni-13 + extensionECHOuterExtensions uint16 = 0xfd00 // draft-ietf-tls-esni-13 ) // TLS signaling cipher suite values @@ -187,6 +190,8 @@ const ( signatureRSAPSS signatureECDSA signatureEd25519 + signatureEdDilithium2 + signatureEdDilithium3 ) // directSigning is a standard Hash value that signals that no pre-hashing @@ -213,6 +218,16 @@ var defaultSupportedSignatureAlgorithms = []SignatureScheme{ ECDSAWithSHA1, } +// supportedSignatureAlgorithmsDC contains the signature and hash algorithms that +// the code advertises as supported in a TLS 1.3 ClientHello and in a TLS 1.3 +// CertificateRequest. This excludes 'rsa_pss_rsae_' algorithms. +var supportedSignatureAlgorithmsDC = []SignatureScheme{ + ECDSAWithP256AndSHA256, + Ed25519, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512, +} + // helloRetryRequestRandom is set as the Random value of a ServerHello // to signal that the message is actually a HelloRetryRequest. var helloRetryRequestRandom = []byte{ // See RFC 8446, Section 4.1.3. @@ -234,6 +249,45 @@ const ( // include downgrade canaries even if it's using its highers supported version. var testingOnlyForceDowngradeCanary bool +// testingTriggerHRR causes the server to intentionally trigger a +// HelloRetryRequest (HRR). This is useful for testing new TLS features that +// change the HRR codepath. +var testingTriggerHRR bool + +// testingECHTriggerBypassAfterHRR causes the client to bypass ECH after HRR. +// If available, the client will offer ECH in the first CH only. +var testingECHTriggerBypassAfterHRR bool + +// testingECHTriggerBypassBeforeHRR causes the client to bypass ECH before HRR. +// The client will offer ECH in the second CH only. +var testingECHTriggerBypassBeforeHRR bool + +// testingECHIllegalHandleAfterHRR causes the client to illegally change the ECH +// extension after HRR. +var testingECHIllegalHandleAfterHRR bool + +// testingECHTriggerPayloadDecryptError causes the client to to send an +// inauthentic payload. +var testingECHTriggerPayloadDecryptError bool + +// testingECHOuterExtMany causes a client to incorporate a sequence of +// outer extensions into the ClientHelloInner when it offers the ECH extension. +// The "key_share" extension is the only incorporated extension by default. +var testingECHOuterExtMany bool + +// testingECHOuterExtNone causes a client to not use the "outer_extension" +// mechanism for ECH. The "key_shares" extension is incorporated by default. +var testingECHOuterExtNone bool + +// testingECHOuterExtIncorrectOrder causes the client to send the +// "outer_extension" extension in the wrong order when offering the ECH +// extension. +var testingECHOuterExtIncorrectOrder bool + +// testingECHOuterExtIllegal causes the client to send in its +// "outer_extension" extension the codepoint for the ECH extension. +var testingECHOuterExtIllegal bool + // ConnectionState records basic TLS details about the connection. type ConnectionState struct { // Version is the TLS version used by the connection (e.g. VersionTLS12). @@ -284,6 +338,11 @@ type ConnectionState struct { // VerifiedChains and its contents should not be modified. VerifiedChains [][]*x509.Certificate + // VerifiedDC indicates that the Delegated Credential sent by the peer (if advertised + // and correctly processed), which has been verified against the leaf certificate, + // has been used. + VerifiedDC bool + // SignedCertificateTimestamps is a list of SCTs provided by the peer // through the TLS handshake for the leaf certificate, if any. SignedCertificateTimestamps [][]byte @@ -297,6 +356,14 @@ type ConnectionState struct { // resumed connections that don't support Extended Master Secret (RFC 7627). TLSUnique []byte + // ECHAccepted is set if the ECH extension was offered by the client and + // accepted by the server. + ECHAccepted bool + + // ECHOffered is set if the ECH extension is present in the ClientHello. + // This means the client has offered ECH or sent GREASE ECH. + ECHOffered bool + // ekm is a closure exposed via ExportKeyingMaterial. ekm func(label string, context []byte, length int) ([]byte, error) } @@ -429,6 +496,13 @@ type ClientHelloInfo struct { // Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1). SignatureSchemes []SignatureScheme + // SignatureSchemesDC lists the signature schemes that the client + // is willing to verify when using Delegated Credentials. + // This is and can be different from SignatureSchemes. SignatureSchemesDC + // is set only if the DelegatedCredentials Extension is being used. + // If Delegated Credentials are supported, this list should not be nil. + SignatureSchemesDC []SignatureScheme + // SupportedProtos lists the application protocols supported by the client. // SupportedProtos is set only if the Application-Layer Protocol // Negotiation Extension is being used (see RFC 7301, Section 3.1). @@ -443,6 +517,10 @@ type ClientHelloInfo struct { // might be rejected if used. SupportedVersions []uint16 + // SupportDelegatedCredential is true if the client indicated willingness + // to negotiate the Delegated Credential extension. + SupportsDelegatedCredential bool + // Conn is the underlying net.Conn for the connection. Do not read // from, or write to, this connection; that will cause the TLS // connection to fail. @@ -473,10 +551,21 @@ type CertificateRequestInfo struct { // empty slice indicates that the server has no preference. AcceptableCAs [][]byte + // SupportDelegatedCredential is true if the server indicated willingness + // to negotiate the Delegated Credential extension. + SupportsDelegatedCredential bool + // SignatureSchemes lists the signature schemes that the server is // willing to verify. SignatureSchemes []SignatureScheme + // SignatureSchemesDC lists the signature schemes that the server + // is willing to verify when using Delegated Credentials. + // This is and can be different from SignatureSchemes. SignatureSchemesDC + // is set only if the DelegatedCredentials Extension is being used. + // If Delegated Credentials are supported, this list should not be nil. + SignatureSchemesDC []SignatureScheme + // Version is the TLS version that was negotiated for this connection. Version uint16 @@ -689,7 +778,8 @@ type Config struct { // SessionTicketsDisabled may be set to true to disable session ticket and // PSK (resumption) support. Note that on clients, session ticket support is - // also disabled if ClientSessionCache is nil. + // also disabled if ClientSessionCache is nil. On clients or servers, + // support is disabled if the ECH extension is enabled. SessionTicketsDisabled bool // SessionTicketKey is used by TLS servers to provide session resumption. @@ -750,12 +840,29 @@ type Config struct { // which is currently TLS 1.3. MaxVersion uint16 + // ClientCurveGuess contains the "curves" for which the client will create + // a keyshare in the initial ClientHello for TLS 1.3. If the client + // guesses incorrectly, and the server does not support or does not + // prefer those keyshares, then the server will return a HelloRetryRequest + // incurring an extra roundtrip. + // + // If empty, no keyshares will be included in the ClientHello. + // + // If nil (default), will send the single most preferred keyshare + // as configurable via CurvePreferences. + ClientCurveGuess []CurveID + // CurvePreferences contains the elliptic curves that will be used in // an ECDHE handshake, in preference order. If empty, the default will // be used. The client will use the first preference as the type for // its key share in TLS 1.3. This may change in the future. CurvePreferences []CurveID + // PQSignatureSchemesEnabled controls whether additional post-quantum + // signature schemes are supported for peer certificates. For available + // signature schemes, see tls_cf.go. + PQSignatureSchemesEnabled bool + // DynamicRecordSizingDisabled disables adaptive sizing of TLS records. // When true, the largest possible TLS record size is always used. When // false, the size of TLS records may be adjusted in an attempt to @@ -774,6 +881,30 @@ type Config struct { // used for debugging. KeyLogWriter io.Writer + // ECHEnabled determines whether the ECH extension is enabled for this + // connection. + ECHEnabled bool + + // ClientECHConfigs are the parameters used by the client when it offers the + // ECH extension. If ECH is enabled, a suitable configuration is found, and + // the client supports TLS 1.3, then it will offer ECH in this handshake. + // Otherwise, if ECH is enabled, it will send a dummy ECH extension. + ClientECHConfigs []ECHConfig + + // ServerECHProvider is the ECH provider used by the client-facing server + // for the ECH extension. If the client offers ECH and TLS 1.3 is + // negotiated, then the provider is used to compute the HPKE context + // (draft-irtf-cfrg-hpke-07), which in turn is used to decrypt the extension + // payload. + ServerECHProvider ECHProvider + + // SupportDelegatedCredential is true if the client or server is willing + // to negotiate the delegated credential extension. + // This can only be used with TLS 1.3. + // + // See https://tools.ietf.org/html/draft-ietf-tls-subcerts. + SupportDelegatedCredential bool + // mutex protects sessionTicketKeys and autoSessionTicketKeys. mutex sync.RWMutex // sessionTicketKeys contains zero or more ticket keys. If set, it means @@ -858,9 +989,15 @@ func (c *Config) Clone() *Config { MinVersion: c.MinVersion, MaxVersion: c.MaxVersion, CurvePreferences: c.CurvePreferences, + ClientCurveGuess: c.ClientCurveGuess, + PQSignatureSchemesEnabled: c.PQSignatureSchemesEnabled, DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, Renegotiation: c.Renegotiation, KeyLogWriter: c.KeyLogWriter, + SupportDelegatedCredential: c.SupportDelegatedCredential, + ECHEnabled: c.ECHEnabled, + ClientECHConfigs: c.ClientECHConfigs, + ServerECHProvider: c.ServerECHProvider, sessionTicketKeys: c.sessionTicketKeys, autoSessionTicketKeys: c.autoSessionTicketKeys, } @@ -1059,6 +1196,17 @@ func (c *Config) supportedVersions(isClient bool) []uint16 { return versions } +func (c *Config) supportedVersionsFromMin(isClient bool, minVersion uint16) []uint16 { + versions := c.supportedVersions(isClient) + filteredVersions := versions[:0] + for _, v := range versions { + if v >= minVersion { + filteredVersions = append(filteredVersions, v) + } + } + return filteredVersions +} + func (c *Config) maxSupportedVersion(isClient bool) uint16 { supportedVersions := c.supportedVersions(isClient) if len(supportedVersions) == 0 { @@ -1408,6 +1556,16 @@ func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error { // and is only for debugging, so a global mutex saves space. var writerMutex sync.Mutex +// A DelegatedCredentialPair contains a Delegated Credential and its +// associated private key. +type DelegatedCredentialPair struct { + // DC is the delegated credential. + DC *DelegatedCredential + // PrivateKey is the private key used to derive the public key of + // contained in DC. PrivateKey must implement crypto.Signer. + PrivateKey crypto.PrivateKey +} + // A Certificate is a chain of one or more certificates, leaf first. type Certificate struct { Certificate [][]byte @@ -1425,6 +1583,16 @@ type Certificate struct { // SignedCertificateTimestamps contains an optional list of Signed // Certificate Timestamps which will be served to clients that request it. SignedCertificateTimestamps [][]byte + // DelegatedCredentials are a list of Delegated Credentials with their + // corresponding private keys, signed by the leaf certificate. + // If there are no delegated credentials, this field is nil. + DelegatedCredentials []DelegatedCredentialPair + // DelegatedCredential is the delegated credential to be used in the + // handshake. + // If there are no delegated credentials, this field is nil. + // NOTE: Do not fill this field, as it will be filled depending on + // the provided list of delegated credentials. + DelegatedCredential []byte // Leaf is the parsed form of the leaf certificate, which may be initialized // using x509.ParseCertificate to reduce per-handshake processing. If nil, // the leaf certificate will be parsed as needed. diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 0e4669866e5..5b04b0e2e2e 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -21,6 +21,8 @@ import ( "sync" "sync/atomic" "time" + + "github.com/cloudflare/circl/hpke" ) // A Conn represents a secured connection. @@ -58,6 +60,9 @@ type Conn struct { // verifiedChains contains the certificate chains that we built, as // opposed to the ones presented by the server. verifiedChains [][]*x509.Certificate + // verifiedDC contains the Delegated Credential sent by the peer (if advertised + // and correctly processed), which has been verified against the leaf certificate. + verifiedDC *DelegatedCredential // serverName contains the server name indicated by the client, if any. serverName string // secureRenegotiation is true if the server echoed the secure @@ -120,6 +125,24 @@ type Conn struct { activeCall atomic.Int32 tmp [16]byte + + // cfEventHandler is called at several points during the handshake if + // set. See also CFEventHandlerContextKey. + cfEventHandler func(event CFEvent) + + // State used for the ECH extension. + ech struct { + sealer hpke.Sealer // The client's HPKE context + opener hpke.Opener // The server's HPKE context + + // The state shared by the client and server. + offered bool // Client offered ECH + greased bool // Client greased ECH + accepted bool // Server accepted ECH + retryConfigs []byte // The retry configurations + configId uint8 // The ECH config id + maxNameLen int // maximum_name_len indicated by the ECH config + } } // Access to net.Conn methods. @@ -721,6 +744,12 @@ func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error { return c.in.setErrorLocked(io.EOF) } if c.vers == VersionTLS13 { + if !c.isClient && c.ech.greased && alert(data[1]) == alertECHRequired { + // This condition indicates that the client intended to offer + // ECH, but did not use a known ECH config. + c.ech.offered = true + c.ech.greased = false + } return c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) } switch data[0] { @@ -1429,6 +1458,29 @@ func (c *Conn) Close() error { if err := c.conn.Close(); err != nil { return err } + + // Resolve ECH status. + if !c.isClient && c.config.MaxVersion < VersionTLS13 { + c.handleCFEvent(CFEventECHServerStatus(echStatusBypassed)) + } else if !c.ech.offered { + if !c.ech.greased { + c.handleCFEvent(CFEventECHClientStatus(echStatusBypassed)) + } else { + c.handleCFEvent(CFEventECHClientStatus(echStatusOuter)) + } + } else { + c.handleCFEvent(CFEventECHClientStatus(echStatusInner)) + if !c.ech.accepted { + if len(c.ech.retryConfigs) > 0 { + c.handleCFEvent(CFEventECHServerStatus(echStatusOuter)) + } else { + c.handleCFEvent(CFEventECHServerStatus(echStatusBypassed)) + } + } else { + c.handleCFEvent(CFEventECHServerStatus(echStatusInner)) + } + } + return alertErr } @@ -1547,6 +1599,10 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) { return nil } + if handler, ok := handshakeCtx.Value(CFEventHandlerContextKey{}).(func(event CFEvent)); ok { + c.cfEventHandler = handler + } + c.in.Lock() defer c.in.Unlock() @@ -1613,8 +1669,13 @@ func (c *Conn) connectionStateLocked() ConnectionState { state.CipherSuite = c.cipherSuite state.PeerCertificates = c.peerCertificates state.VerifiedChains = c.verifiedChains + if c.verifiedDC != nil { + state.VerifiedDC = true + } state.SignedCertificateTimestamps = c.scts state.OCSPResponse = c.ocspResponse + state.ECHAccepted = c.ech.accepted + state.ECHOffered = c.ech.offered || c.ech.greased if (!c.didResume || c.extMasterSecret) && c.vers != VersionTLS13 { if c.clientFinishedIsFirst { state.TLSUnique = c.clientFinished[:] @@ -1664,3 +1725,21 @@ func (c *Conn) VerifyHostname(host string) error { } return c.peerCertificates[0].VerifyHostname(host) } + +// CFEventHandlerContextKey is a context key. It can be set on a TLS client or +// server before the handshake has started. The associated value must be of type +// func(event tls.CFEvent). This function will be called at various points +// during the handshake for collecting metrics. +// +// NOTE: it can also be called at the end of the connection for certain ECH +// metrics. This might be removed in the future. +// +// NOTE: This feature is used to implement Cloudflare-internal features. +// This feature is unstable and applications MUST NOT depend on it. +type CFEventHandlerContextKey struct{} + +func (c *Conn) handleCFEvent(event CFEvent) { + if c.cfEventHandler != nil { + c.cfEventHandler(event) + } +} diff --git a/src/crypto/tls/delegated_credentials.go b/src/crypto/tls/delegated_credentials.go new file mode 100644 index 00000000000..2bf5bfd2a2d --- /dev/null +++ b/src/crypto/tls/delegated_credentials.go @@ -0,0 +1,548 @@ +// Copyright 2020-2021 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +// Delegated Credentials for TLS +// (https://tools.ietf.org/html/draft-ietf-tls-subcerts) is an IETF Internet +// draft and proposed TLS extension. If the client or server supports this +// extension, then the server or client may use a "delegated credential" as the +// signing key in the handshake. A delegated credential is a short lived +// public/secret key pair delegated to the peer by an entity trusted by the +// corresponding peer. This allows a reverse proxy to terminate a TLS connection +// on behalf of the entity. Credentials can't be revoked; in order to +// mitigate risk in case the reverse proxy is compromised, the credential is only +// valid for a short time (days, hours, or even minutes). + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/binary" + "errors" + "fmt" + "io" + "time" + + "golang.org/x/crypto/cryptobyte" +) + +const ( + // In the absence of an application profile standard specifying otherwise, + // the maximum validity period is set to 7 days. + dcMaxTTLSeconds = 60 * 60 * 24 * 7 + dcMaxTTL = time.Duration(dcMaxTTLSeconds * time.Second) + dcMaxPubLen = (1 << 24) - 1 // Bytes + dcMaxSignatureLen = (1 << 16) - 1 // Bytes +) + +const ( + undefinedSignatureScheme SignatureScheme = 0x0000 +) + +var extensionDelegatedCredential = []int{1, 3, 6, 1, 4, 1, 44363, 44} + +// isValidForDelegation returns true if a certificate can be used for Delegated +// Credentials. +func isValidForDelegation(cert *x509.Certificate) bool { + // Check that the digitalSignature key usage is set. + // The certificate must contains the digitalSignature KeyUsage. + if (cert.KeyUsage & x509.KeyUsageDigitalSignature) == 0 { + return false + } + + // Check that the certificate has the DelegationUsage extension and that + // it's marked as non-critical (See Section 4.2 of RFC5280). + for _, extension := range cert.Extensions { + if extension.Id.Equal(extensionDelegatedCredential) { + if extension.Critical { + return false + } + return true + } + } + return false +} + +// isExpired returns true if the credential has expired. The end of the validity +// interval is defined as the delegator certificate's notBefore field ('start') +// plus dc.cred.validTime seconds. This function simply checks that the current time +// ('now') is before the end of the validity interval. +func (dc *DelegatedCredential) isExpired(start, now time.Time) bool { + end := start.Add(dc.cred.validTime) + return !now.Before(end) +} + +// invalidTTL returns true if the credential's validity period is longer than the +// maximum permitted. This is defined by the certificate's notBefore field +// ('start') plus the dc.validTime, minus the current time ('now'). +func (dc *DelegatedCredential) invalidTTL(start, now time.Time) bool { + return dc.cred.validTime > (now.Sub(start) + dcMaxTTL).Round(time.Second) +} + +// credential stores the public components of a Delegated Credential. +type credential struct { + // The amount of time for which the credential is valid. Specifically, the + // the credential expires 'validTime' seconds after the 'notBefore' of the + // delegation certificate. The delegator shall not issue Delegated + // Credentials that are valid for more than 7 days from the current time. + // + // When this data structure is serialized, this value is converted to a + // uint32 representing the duration in seconds. + validTime time.Duration + // The signature scheme associated with the credential public key. + // This is expected to be the same as the CertificateVerify.algorithm + // sent by the client or server. + expCertVerfAlgo SignatureScheme + // The credential's public key. + publicKey crypto.PublicKey +} + +// DelegatedCredential stores a Delegated Credential with the credential and its +// signature. +type DelegatedCredential struct { + // The serialized form of the Delegated Credential. + raw []byte + + // Cred stores the public components of a Delegated Credential. + cred *credential + + // The signature scheme used to sign the Delegated Credential. + algorithm SignatureScheme + + // The Credential's delegation: a signature that binds the credential to + // the end-entity certificate's public key. + signature []byte +} + +// marshalPublicKeyInfo returns a DER encoded PublicKeyInfo +// from a Delegated Credential (as defined in the X.509 standard). +// The following key types are currently supported: *ecdsa.PublicKey +// and ed25519.PublicKey. Unsupported key types result in an error. +// rsa.PublicKey is not supported as defined by the draft. +func (cred *credential) marshalPublicKeyInfo() ([]byte, error) { + switch cred.expCertVerfAlgo { + case ECDSAWithP256AndSHA256, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512, + Ed25519: + rawPub, err := x509.MarshalPKIXPublicKey(cred.publicKey) + if err != nil { + return nil, err + } + + return rawPub, nil + + default: + return nil, fmt.Errorf("tls: unsupported signature scheme: 0x%04x", cred.expCertVerfAlgo) + } +} + +// marshal encodes the credential struct of the Delegated Credential. +func (cred *credential) marshal() ([]byte, error) { + var b cryptobyte.Builder + + b.AddUint32(uint32(cred.validTime / time.Second)) + b.AddUint16(uint16(cred.expCertVerfAlgo)) + + // Encode the public key + rawPub, err := cred.marshalPublicKeyInfo() + if err != nil { + return nil, err + } + // Assert that the public key encoding is no longer than 2^24-1 bytes. + if len(rawPub) > dcMaxPubLen { + return nil, errors.New("tls: public key length exceeds 2^24-1 limit") + } + + b.AddUint24(uint32(len(rawPub))) + b.AddBytes(rawPub) + + raw := b.BytesOrPanic() + return raw, nil +} + +// unmarshalCredential decodes serialized bytes and returns a credential, if possible. +func unmarshalCredential(raw []byte) (*credential, error) { + if len(raw) < 10 { + return nil, errors.New("tls: Delegated Credential is not valid: invalid length") + } + + s := cryptobyte.String(raw) + var t uint32 + if !s.ReadUint32(&t) { + return nil, errors.New("tls: Delegated Credential is not valid") + } + validTime := time.Duration(t) * time.Second + + var pubAlgo uint16 + if !s.ReadUint16(&pubAlgo) { + return nil, errors.New("tls: Delegated Credential is not valid") + } + algo := SignatureScheme(pubAlgo) + + var pubLen uint32 + s.ReadUint24(&pubLen) + + pubKey, err := x509.ParsePKIXPublicKey(s) + if err != nil { + return nil, err + } + + return &credential{validTime, algo, pubKey}, nil +} + +// getCredentialLen returns the number of bytes comprising the serialized +// credential struct inside the Delegated Credential. +func getCredentialLen(raw []byte) (int, error) { + if len(raw) < 10 { + return 0, errors.New("tls: Delegated Credential is not valid") + } + + var read []byte + s := cryptobyte.String(raw) + s.ReadBytes(&read, 6) + + var pubLen uint32 + s.ReadUint24(&pubLen) + if !(pubLen > 0) { + return 0, errors.New("tls: Delegated Credential is not valid") + } + + raw = raw[6:] + if len(raw) < int(pubLen) { + return 0, errors.New("tls: Delegated Credential is not valid") + } + + return 9 + int(pubLen), nil +} + +// getHash maps the SignatureScheme to its corresponding hash function. +func getHash(scheme SignatureScheme) crypto.Hash { + switch scheme { + case ECDSAWithP256AndSHA256: + return crypto.SHA256 + case ECDSAWithP384AndSHA384: + return crypto.SHA384 + case ECDSAWithP521AndSHA512: + return crypto.SHA512 + case Ed25519: + return directSigning + case PKCS1WithSHA256, PSSWithSHA256: + return crypto.SHA256 + case PSSWithSHA384: + return crypto.SHA384 + case PSSWithSHA512: + return crypto.SHA512 + default: + return 0 //Unknown hash function + } +} + +// getECDSACurve maps the SignatureScheme to its corresponding ecdsa elliptic.Curve. +func getECDSACurve(scheme SignatureScheme) elliptic.Curve { + switch scheme { + case ECDSAWithP256AndSHA256: + return elliptic.P256() + case ECDSAWithP384AndSHA384: + return elliptic.P384() + case ECDSAWithP521AndSHA512: + return elliptic.P521() + default: + return nil + } +} + +// prepareDelegationSignatureInput returns the message that the delegator is going to sign. +func prepareDelegationSignatureInput(hash crypto.Hash, cred *credential, dCert []byte, algo SignatureScheme, isClient bool) ([]byte, error) { + header := make([]byte, 64) + for i := range header { + header[i] = 0x20 + } + + var context string + if !isClient { + context = "TLS, server delegated credentials\x00" + } else { + context = "TLS, client delegated credentials\x00" + } + + rawCred, err := cred.marshal() + if err != nil { + return nil, err + } + + var rawAlgo [2]byte + binary.BigEndian.PutUint16(rawAlgo[:], uint16(algo)) + + if hash == directSigning { + b := &bytes.Buffer{} + b.Write(header) + io.WriteString(b, context) + b.Write(dCert) + b.Write(rawCred) + b.Write(rawAlgo[:]) + return b.Bytes(), nil + } + + h := hash.New() + h.Write(header) + io.WriteString(h, context) + h.Write(dCert) + h.Write(rawCred) + h.Write(rawAlgo[:]) + return h.Sum(nil), nil +} + +// Extract the algorithm used to sign the Delegated Credential from the +// end-entity (leaf) certificate. +func getSignatureAlgorithm(cert *Certificate) (SignatureScheme, error) { + switch sk := cert.PrivateKey.(type) { + case *ecdsa.PrivateKey: + pk := sk.Public().(*ecdsa.PublicKey) + curveName := pk.Curve.Params().Name + certAlg := cert.Leaf.PublicKeyAlgorithm + if certAlg == x509.ECDSA && curveName == "P-256" { + return ECDSAWithP256AndSHA256, nil + } else if certAlg == x509.ECDSA && curveName == "P-384" { + return ECDSAWithP384AndSHA384, nil + } else if certAlg == x509.ECDSA && curveName == "P-521" { + return ECDSAWithP521AndSHA512, nil + } else { + return undefinedSignatureScheme, fmt.Errorf("using curve %s for %s is not supported", curveName, cert.Leaf.SignatureAlgorithm) + } + case ed25519.PrivateKey: + return Ed25519, nil + case *rsa.PrivateKey: + // If the certificate has the RSAEncryption OID there are a number of valid signature schemes that may sign the DC. + // In the absence of better information, we make a reasonable choice. + return PSSWithSHA256, nil + default: + return undefinedSignatureScheme, fmt.Errorf("tls: unsupported algorithm for signing Delegated Credential") + } +} + +// NewDelegatedCredential creates a new Delegated Credential using 'cert' for +// delegation, depending if the caller is the client or the server (defined by +// 'isClient'). It generates a public/private key pair for the provided signature +// algorithm ('pubAlgo') and it defines a validity interval (defined +// by 'cert.Leaf.notBefore' and 'validTime'). It signs the Delegated Credential +// using 'cert.PrivateKey'. +func NewDelegatedCredential(cert *Certificate, pubAlgo SignatureScheme, validTime time.Duration, isClient bool) (*DelegatedCredential, crypto.PrivateKey, error) { + // The granularity of DC validity is seconds. + validTime = validTime.Round(time.Second) + + // Parse the leaf certificate if needed. + var err error + if cert.Leaf == nil { + if len(cert.Certificate[0]) == 0 { + return nil, nil, errors.New("tls: missing leaf certificate for Delegated Credential") + } + cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + return nil, nil, err + } + } + + // Check that the leaf certificate can be used for delegation. + if !isValidForDelegation(cert.Leaf) { + return nil, nil, errors.New("tls: certificate not authorized for delegation") + } + + sigAlgo, err := getSignatureAlgorithm(cert) + if err != nil { + return nil, nil, err + } + + // Generate the Delegated Credential key pair based on the provided scheme + var privK crypto.PrivateKey + var pubK crypto.PublicKey + switch pubAlgo { + case ECDSAWithP256AndSHA256, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512: + privK, err = ecdsa.GenerateKey(getECDSACurve(pubAlgo), rand.Reader) + if err != nil { + return nil, nil, err + } + pubK = privK.(*ecdsa.PrivateKey).Public() + case Ed25519: + pubK, privK, err = ed25519.GenerateKey(rand.Reader) + if err != nil { + return nil, nil, err + } + default: + return nil, nil, fmt.Errorf("tls: unsupported algorithm for Delegated Credential: %s", pubAlgo) + } + + // Prepare the credential for signing + hash := getHash(sigAlgo) + credential := &credential{validTime, pubAlgo, pubK} + values, err := prepareDelegationSignatureInput(hash, credential, cert.Leaf.Raw, sigAlgo, isClient) + if err != nil { + return nil, nil, err + } + + var sig []byte + switch sk := cert.PrivateKey.(type) { + case *ecdsa.PrivateKey: + opts := crypto.SignerOpts(hash) + sig, err = sk.Sign(rand.Reader, values, opts) + if err != nil { + return nil, nil, err + } + case ed25519.PrivateKey: + opts := crypto.SignerOpts(hash) + sig, err = sk.Sign(rand.Reader, values, opts) + if err != nil { + return nil, nil, err + } + case *rsa.PrivateKey: + opts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: hash} + sig, err = rsa.SignPSS(rand.Reader, sk, hash, values, opts) + if err != nil { + return nil, nil, err + } + default: + return nil, nil, fmt.Errorf("tls: unsupported key type for Delegated Credential") + } + + if len(sig) > dcMaxSignatureLen { + return nil, nil, errors.New("tls: unable to create a Delegated Credential") + } + + return &DelegatedCredential{ + cred: credential, + algorithm: sigAlgo, + signature: sig, + }, privK, nil +} + +// Validate validates the Delegated Credential by checking that the signature is +// valid, that it hasn't expired, and that the TTL is valid. It also checks that +// certificate can be used for delegation. +func (dc *DelegatedCredential) Validate(cert *x509.Certificate, isClient bool, now time.Time, certVerifyMsg *certificateVerifyMsg) bool { + if dc.isExpired(cert.NotBefore, now) { + return false + } + + if dc.invalidTTL(cert.NotBefore, now) { + return false + } + + if dc.cred.expCertVerfAlgo != certVerifyMsg.signatureAlgorithm { + return false + } + + if !isValidForDelegation(cert) { + return false + } + + hash := getHash(dc.algorithm) + in, err := prepareDelegationSignatureInput(hash, dc.cred, cert.Raw, dc.algorithm, isClient) + if err != nil { + return false + } + + switch dc.algorithm { + case ECDSAWithP256AndSHA256, + ECDSAWithP384AndSHA384, + ECDSAWithP521AndSHA512: + pk, ok := cert.PublicKey.(*ecdsa.PublicKey) + if !ok { + return false + } + + return ecdsa.VerifyASN1(pk, in, dc.signature) + case Ed25519: + pk, ok := cert.PublicKey.(ed25519.PublicKey) + if !ok { + return false + } + + return ed25519.Verify(pk, in, dc.signature) + case PSSWithSHA256, + PSSWithSHA384, + PSSWithSHA512: + pk, ok := cert.PublicKey.(*rsa.PublicKey) + if !ok { + return false + } + hash := getHash(dc.algorithm) + return rsa.VerifyPSS(pk, hash, in, dc.signature, nil) == nil + default: + return false + } +} + +// Marshal encodes a DelegatedCredential structure. It also sets dc.Raw to that +// encoding. +func (dc *DelegatedCredential) Marshal() ([]byte, error) { + if len(dc.signature) > dcMaxSignatureLen { + return nil, errors.New("tls: delegated credential is not valid") + } + if len(dc.signature) == 0 { + return nil, errors.New("tls: delegated credential has no signature") + } + + raw, err := dc.cred.marshal() + if err != nil { + return nil, err + } + + var b cryptobyte.Builder + b.AddBytes(raw) + b.AddUint16(uint16(dc.algorithm)) + b.AddUint16(uint16(len(dc.signature))) + b.AddBytes(dc.signature) + + dc.raw = b.BytesOrPanic() + return dc.raw, nil +} + +// UnmarshalDelegatedCredential decodes a DelegatedCredential structure. +func UnmarshalDelegatedCredential(raw []byte) (*DelegatedCredential, error) { + rawCredentialLen, err := getCredentialLen(raw) + if err != nil { + return nil, err + } + + credential, err := unmarshalCredential(raw[:rawCredentialLen]) + if err != nil { + return nil, err + } + + raw = raw[rawCredentialLen:] + if len(raw) < 4 { + return nil, errors.New("tls: Delegated Credential is not valid") + } + + s := cryptobyte.String(raw) + + var algo uint16 + if !s.ReadUint16(&algo) { + return nil, errors.New("tls: Delegated Credential is not valid") + } + + var rawSignatureLen uint16 + if !s.ReadUint16(&rawSignatureLen) { + return nil, errors.New("tls: Delegated Credential is not valid") + } + + var sig []byte + if !s.ReadBytes(&sig, int(rawSignatureLen)) { + return nil, errors.New("tls: Delegated Credential is not valid") + } + + return &DelegatedCredential{ + cred: credential, + algorithm: SignatureScheme(algo), + signature: sig, + }, nil +} diff --git a/src/crypto/tls/delegated_credentials_test.go b/src/crypto/tls/delegated_credentials_test.go new file mode 100644 index 00000000000..9614824d38c --- /dev/null +++ b/src/crypto/tls/delegated_credentials_test.go @@ -0,0 +1,652 @@ +// Copyright 2020-2021 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/x509" + "errors" + "fmt" + "math/rand" + "testing" + "time" +) + +// These test keys were generated with the following program, available in the +// crypto/tls directory: +// +// go run generate_cert.go -ecdsa-curve P256 -host 127.0.0.1 -allowDC +var delegatorCertPEMP256 = `-----BEGIN CERTIFICATE----- +MIIBejCCAR+gAwIBAgIQKEg6iMq02QUu7QZSZJ/qjzAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTIxMDIyNzAwMTYwMVoXDTIyMDIyNzAwMTYwMVow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJTe +bU0Yny6aMvae3zlNj135l7XSzqPDZjYh1PqIqY/P2N5PPmD06fHQ2D7xZRUw/a5z +W7KMwRVXrvur+TVn4+GjVzBVMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMA8GCSsGAQQBgtpLLAQCBQAwDwYDVR0RBAgw +BocEfwAAATAKBggqhkjOPQQDAgNJADBGAiEAvkorBgZm6GidD0Z7tcAJWRq+2YOQ +GVclN1Z1CDljQIoCIQDUlTAqDyRpNJ9ntCHEdOQYe1LfAkJHasok5yCRHC1o8w== +-----END CERTIFICATE----- +` + +var delegatorKeyPEMP256 = testingKey(`-----BEGIN EC TESTING KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg4OgO7q8sUUZaYjEp +JuLzlXH0qmTZ1k3UHgPYbAmRFOWhRANCAASU3m1NGJ8umjL2nt85TY9d+Ze10s6j +w2Y2IdT6iKmPz9jeTz5g9Onx0Ng+8WUVMP2uc1uyjMEVV677q/k1Z+Ph +-----END EC TESTING KEY----- +`) + +// go run generate_cert.go -ecdsa-curve P384 -host 127.0.0.1 -allowDC + +var delegatorCertPEMP384 = `-----BEGIN CERTIFICATE----- +MIIBtzCCATygAwIBAgIQYhD6ucKVx53ZfdRCJkPy3DAKBggqhkjOPQQDAzASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTIxMDIyNzAwMTYzOFoXDTIyMDIyNzAwMTYzOFow +EjEQMA4GA1UEChMHQWNtZSBDbzB2MBAGByqGSM49AgEGBSuBBAAiA2IABHNmyki5 +Xxfmxxrk4QRoXfU7hk0o2gJWTkCUAyzlVNcSaUTHub64v2cwn9/LbbooFBlhwz4n +n706yHtzmSQHTkCKmcG2LwS75U+ZajzPXKoSqazGhapBLQb7R7A+uRQGvqNXMFUw +DgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQC +MAAwDwYJKwYBBAGC2kssBAIFADAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMD +A2kAMGYCMQDIOr2c+CckkU48HqcFiyzPkYWUUeytqmzOg3QDOu6U0jfmi1Xb9dda +pytx77nIUucCMQDD9uVr1UeKGC3Iv0VIHw+tjBzTUg9iToG+PPIlnP+duIBjFQcl +FkeNmqTC8510USo= +-----END CERTIFICATE----- +` + +var delegatorKeyPEMP384 = testingKey(`-----BEGIN EC TESTING KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDA1ouSiH174RBEvZBch +QQnl5iYWTpdCa+EHjexYzhQ9HHMcU7nKCk7OXRod3kAVcUahZANiAARzZspIuV8X +5sca5OEEaF31O4ZNKNoCVk5AlAMs5VTXEmlEx7m+uL9nMJ/fy226KBQZYcM+J5+9 +Osh7c5kkB05AipnBti8Eu+VPmWo8z1yqEqmsxoWqQS0G+0ewPrkUBr4= +-----END EC TESTING KEY----- +`) + +// go run generate_cert.go -ecdsa-curve P521 -host 127.0.0.1 -allowDC + +var delegatorCertPEMP521 = `-----BEGIN CERTIFICATE----- +MIICATCCAWKgAwIBAgIQJq2J2jQNbTUbhfjk0PT8/TAKBggqhkjOPQQDBDASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTIxMDIyNzAwMTcxN1oXDTIyMDIyNzAwMTcxN1ow +EjEQMA4GA1UEChMHQWNtZSBDbzCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAM3n +1xAxRLYhnDNRqc0onmNM9Ik0Jcja6e0bYa9mo0oV/y5DPeML3UJB1CNImFpAkx62 +wLiZmk/BhcPS0EstLAwXATBkb/q0fbKUZXFHd4gr5spRfAosXz5vg1VLeKHqpUku +tyJjgdFvuBZzmp2olqGKbBSKUElvDFkZWkZk5uGEnCsIo1cwVTAOBgNVHQ8BAf8E +BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAPBgkrBgEE +AYLaSywEAgUAMA8GA1UdEQQIMAaHBH8AAAEwCgYIKoZIzj0EAwQDgYwAMIGIAkIB +TVEJrlJkxqs0adMPKg5D1EQDGy4dUz4YSWc0VXFOV7TKFDhjo1Abs3SYNXPsgAgT +Ol8BhJ2gFUhgHBP8BiJqPUYCQgFWXEe6AfKPyAUcNH28pIavfhxeGc0DGE4Xux0w +/vWpDdT89YxJmQC1roSaXRwEW1GBXL41h5rMMklGqkkfnCW2SQ== +-----END CERTIFICATE----- +` + +var delegatorKeyPEMP521 = testingKey(`-----BEGIN EC TESTING KEY----- +MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIA4X72HzMvgBj//dX/ +SLkA2+oQ93l2eB2jXVRFST/mQj5NSSt8TNcIqW+TaxSejst7+jAQgnH2Zrith8zK +r2/Gy/6hgYkDgYYABADN59cQMUS2IZwzUanNKJ5jTPSJNCXI2untG2GvZqNKFf8u +Qz3jC91CQdQjSJhaQJMetsC4mZpPwYXD0tBLLSwMFwEwZG/6tH2ylGVxR3eIK+bK +UXwKLF8+b4NVS3ih6qVJLrciY4HRb7gWc5qdqJahimwUilBJbwxZGVpGZObhhJwr +CA== +-----END EC TESTING KEY----- +`) + +// go run generate_cert.go -ed25519 -host 127.0.0.1 -allowDC + +var delegatorCertPEMEd25519 = `-----BEGIN CERTIFICATE----- +MIIBOTCB7KADAgECAhEAzk3wRF7IPMF07CnnLbQEbDAFBgMrZXAwEjEQMA4GA1UE +ChMHQWNtZSBDbzAeFw0yMTAyMjcwMDE4MTVaFw0yMjAyMjcwMDE4MTVaMBIxEDAO +BgNVBAoTB0FjbWUgQ28wKjAFBgMrZXADIQD+aRKJTaCG+yEz/w3lLhglSTsxyPl4 +FepwdCUXDxj2oKNXMFUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF +BwMBMAwGA1UdEwEB/wQCMAAwDwYJKwYBBAGC2kssBAIFADAPBgNVHREECDAGhwR/ +AAABMAUGAytlcANBAO0XGRvpMAdkI8SVheJmr+Oe+BBR3VWyhU9PdIxiWu+v+pjp +UQDJpmto6r3AsriHVw2EIdvONnL1FeNzMX2HRAw= +-----END CERTIFICATE----- +` + +var delegatorKeyPEMEd25519 = testingKey(`-----BEGIN EC TESTING KEY----- +MC4CAQAwBQYDK2VwBCIEILsRn/g0To97rbKf+2zV+sr6ZmrqcEiLRK2/rD7r+xDZ +-----END EC TESTING KEY----- +`) + +var nonDelegatorCertPEM = `-----BEGIN CERTIFICATE----- +MIIBaDCCAQ6gAwIBAgIQcMnAGu3NQYTGYf2HK+JodTAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTIwMDgxODA1NDg1NloXDTIxMDgxODA1NDg1Nlow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPAi +QzOthHUdwLTPo9P7Vk1I2W5RHW5nIkq9zYqqMZ5mHQ6vmmrpklvTNHtY93PlokjN +pnlhzEsxK/QrBoAQ8fajRjBEMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMA8GA1UdEQQIMAaHBH8AAAEwCgYIKoZIzj0E +AwIDSAAwRQIgbOxx7/KWTD47UTWIBcFB95BPrFp2SaFBUyjhzMDXsQkCIQDnwtye +V1OlcMigjCsQuGRacYFP3f1ASpYVv58t/ZeVCw== +-----END CERTIFICATE----- +` + +var nonDelegatorKeyPEM = testingKey(`-----BEGIN EC TESTING KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgD9Q9131NamLDe4ud +dU9rg+gO0vv8lXYErf7P5GQlZD6hRANCAATwIkMzrYR1HcC0z6PT+1ZNSNluUR1u +ZyJKvc2KqjGeZh0Or5pq6ZJb0zR7WPdz5aJIzaZ5YcxLMSv0KwaAEPH2 +-----END EC TESTING KEY----- +`) + +var ( + dcTestConfig *Config + dcTestCerts map[string]*Certificate + serverDC []DelegatedCredentialPair + clientDC []DelegatedCredentialPair + dcNow time.Time + dcTestDCSignatureScheme = []SignatureScheme{ECDSAWithP256AndSHA256, Ed25519, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512} +) + +func init() { + dcTestConfig = &Config{ + Time: func() time.Time { + return dcNow + }, + Rand: zeroSource{}, + Certificates: nil, + MinVersion: VersionTLS10, + MaxVersion: VersionTLS13, + CipherSuites: allCipherSuites(), + } + +} + +func initDCTest() { + // Use a static time for testing at which time the test certificates are + // valid. + dcNow = time.Date(2021, time.March, 31, 11, 0, 0, 234234, time.UTC) + + // The certificates of the server. + dcTestCerts = make(map[string]*Certificate) + var err error + + // The delegation P256 certificate. + dcCertP256 := new(Certificate) + *dcCertP256, err = X509KeyPair([]byte(delegatorCertPEMP256), []byte(delegatorKeyPEMP256)) + if err != nil { + panic(err) + } + + dcCertP256.Leaf, err = x509.ParseCertificate(dcCertP256.Certificate[0]) + if err != nil { + panic(err) + } + dcTestCerts["dcP256"] = dcCertP256 + + // The delegation P384 certificate. + dcCertP384 := new(Certificate) + *dcCertP384, err = X509KeyPair([]byte(delegatorCertPEMP384), []byte(delegatorKeyPEMP384)) + if err != nil { + panic(err) + } + + dcCertP384.Leaf, err = x509.ParseCertificate(dcCertP384.Certificate[0]) + if err != nil { + panic(err) + } + dcTestCerts["dcP384"] = dcCertP384 + + // The delegation P521 certificate. + dcCertP521 := new(Certificate) + *dcCertP521, err = X509KeyPair([]byte(delegatorCertPEMP521), []byte(delegatorKeyPEMP521)) + if err != nil { + panic(err) + } + + dcCertP521.Leaf, err = x509.ParseCertificate(dcCertP521.Certificate[0]) + if err != nil { + panic(err) + } + dcTestCerts["dcP521"] = dcCertP521 + + // The delegation Ed25519 certificate. + dcCertEd25519 := new(Certificate) + *dcCertEd25519, err = X509KeyPair([]byte(delegatorCertPEMEd25519), []byte(delegatorKeyPEMEd25519)) + if err != nil { + panic(err) + } + + dcCertEd25519.Leaf, err = x509.ParseCertificate(dcCertEd25519.Certificate[0]) + if err != nil { + panic(err) + } + dcTestCerts["dcEd25519"] = dcCertEd25519 + + // The non-delegation certificate. + noDcCert := new(Certificate) + *noDcCert, err = X509KeyPair([]byte(nonDelegatorCertPEM), []byte(nonDelegatorKeyPEM)) + if err != nil { + panic(err) + } + noDcCert.Leaf, err = x509.ParseCertificate(noDcCert.Certificate[0]) + if err != nil { + panic(err) + } + dcTestCerts["no dc"] = noDcCert + + // The root certificates for the peer. + dcTestConfig.RootCAs = x509.NewCertPool() + + for _, c := range dcTestCerts { + dcRoot, err := x509.ParseCertificate(c.Certificate[len(c.Certificate)-1]) + if err != nil { + panic(err) + } + dcTestConfig.RootCAs.AddCert(dcRoot) + } + + for i := 0; i < len(dcTestDCSignatureScheme); i++ { + dc, priv, err := NewDelegatedCredential(dcCertP256, dcTestDCSignatureScheme[i], dcNow.Sub(dcCertP256.Leaf.NotBefore)+dcMaxTTL, false) + if err != nil { + panic(err) + } + serverDC = append(serverDC, DelegatedCredentialPair{dc, priv}) + + dc, priv, err = NewDelegatedCredential(dcCertP256, dcTestDCSignatureScheme[i], dcNow.Sub(dcCertP256.Leaf.NotBefore)+dcMaxTTL, true) + if err != nil { + panic(err) + } + clientDC = append(clientDC, DelegatedCredentialPair{dc, priv}) + } +} + +func publicKeysEqual(publicKey, publicKey2 crypto.PublicKey, algo SignatureScheme) error { + switch publicKey.(type) { + case *ecdsa.PublicKey: + curve := getECDSACurve(algo) + pk := publicKey.(*ecdsa.PublicKey) + pk2 := publicKey2.(*ecdsa.PublicKey) + + serPubKey := elliptic.Marshal(curve, pk.X, pk.Y) + serPubKey2 := elliptic.Marshal(curve, pk2.X, pk2.Y) + if !bytes.Equal(serPubKey2, serPubKey) { + return errors.New("ecdsa public Keys mismatch") + } + case ed25519.PublicKey: + pk := publicKey.(ed25519.PublicKey) + pk2 := publicKey2.(ed25519.PublicKey) + + if !bytes.Equal(pk, pk2) { + return errors.New("ed25519 Public Keys mismatch") + } + } + + return nil +} + +func delegagedCredentialsEqual(dc, dc2 *DelegatedCredential) error { + if dc2.cred.validTime != dc.cred.validTime { + return fmt.Errorf("ValidTime mismatch: got %d; want %d", dc2.cred.validTime, dc.cred.validTime) + } + + if dc2.cred.expCertVerfAlgo != dc.cred.expCertVerfAlgo { + return fmt.Errorf("scheme mismatch: got %04x; want %04x", dc2.cred.expCertVerfAlgo, dc.cred.expCertVerfAlgo) + } + + return publicKeysEqual(dc.cred.publicKey, dc2.cred.publicKey, dc.cred.expCertVerfAlgo) +} + +// Test delegation and validation of credentials. +func TestDelegateCredentialsValidate(t *testing.T) { + initDCTest() + cert := dcTestCerts["dcP384"] + validTime := dcNow.Sub(cert.Leaf.NotBefore) + dcMaxTTL + + delegatedCred, _, err := NewDelegatedCredential(cert, ECDSAWithP384AndSHA384, validTime, false) + if err != nil { + t.Fatal(err) + } else if delegatedCred == nil { + t.Fatal("unable to generate a Delegated Credential") + } + + rand := rand.New(rand.NewSource(time.Now().UnixNano())) + m := &certificateVerifyMsg{} + m.hasSignatureAlgorithm = true + m.signatureAlgorithm = ECDSAWithP384AndSHA384 + m.signature = randomBytes(rand.Intn(15)+1, rand) + + // Valid Delegated Credential + if !delegatedCred.Validate(cert.Leaf, false, dcNow, m) { + t.Error("generated valid Delegated Credential is rendered invalid") + } + + // Expired Delegated Credential + expired := dcNow.Add(dcMaxTTL).Add(time.Nanosecond) + if delegatedCred.Validate(cert.Leaf, false, expired, m) { + t.Error("expired delegated credential is valid; want invalid") + } + + // Test validation of Delegated Credential which TTL is too long + invalidDelegatedCred, _, err := NewDelegatedCredential(cert, ECDSAWithP384AndSHA384, validTime+time.Second, false) + if err != nil { + t.Fatal(err) + } + if invalidDelegatedCred.Validate(cert.Leaf, false, dcNow, m) { + t.Error("Delegated Credential validation with long TTL succeeded; want failure") + } + + shortValidTime := dcNow.Sub(cert.Leaf.NotBefore) + time.Second + + // Test validation of Delegated Credential which TTL is short + delegatedCred, _, err = NewDelegatedCredential(cert, ECDSAWithP384AndSHA384, shortValidTime, false) + if err != nil { + t.Fatal(err) + } + if !delegatedCred.Validate(cert.Leaf, false, dcNow, m) { + t.Error("valid Delegated Credential is invalid; want valid") + } + + delegatedCred.algorithm = ECDSAWithP521AndSHA512 + + // Test signature algorithm binding + if delegatedCred.Validate(cert.Leaf, false, dcNow, m) { + t.Error("Delegated Credential with wrong scheme is valid; want invalid") + } + + delegatedCred.algorithm = ECDSAWithP384AndSHA384 + + // Test delegation certificate binding + cert.Leaf.Raw[0] ^= byte(42) + if delegatedCred.Validate(cert.Leaf, false, dcNow, m) { + t.Error("Delegated Credential with wrong certificate is valid; want invalid") + } + + // Test validation of DC using a certificate that can't delegate. + if delegatedCred.Validate(dcTestCerts["no dc"].Leaf, false, dcNow, m) { + t.Error("Delegated Credential with non-delegation cert is valid; want invalid") + } + + // Test DC with another certificate + cert = dcTestCerts["dcP521"] + validTime = dcNow.Sub(cert.Leaf.NotBefore) + dcMaxTTL + delegatedCred, _, err = NewDelegatedCredential(cert, ECDSAWithP384AndSHA384, validTime, false) + if err != nil { + t.Fatal(err) + } else if delegatedCred == nil { + t.Fatal("unable to generate a Delegated Credential") + } + + // Valid Delegated Credential + if !delegatedCred.Validate(cert.Leaf, false, dcNow, m) { + t.Error("generated valid Delegated Credential is rendered invalid") + } +} + +// Test encoding/decoding of Delegated Credentials. +func TestDelegatedCredentialMarshal(t *testing.T) { + initDCTest() + cert := dcTestCerts["dcEd25519"] + time := dcNow.Sub(cert.Leaf.NotBefore) + dcMaxTTL + + for _, sig := range dcTestDCSignatureScheme { + delegatedCred, _, err := NewDelegatedCredential(cert, sig, time, false) + if err != nil { + t.Fatal(err) + } + + ser, err := delegatedCred.Marshal() + if err != nil { + t.Error(err) + } + + delegatedCred2, err := UnmarshalDelegatedCredential(ser) + if err != nil { + t.Error(err) + } + + err = delegagedCredentialsEqual(delegatedCred, delegatedCred2) + if err != nil { + t.Error(err) + } + + if delegatedCred.algorithm != delegatedCred2.algorithm { + t.Errorf("scheme mismatch: got %04x; want %04x", delegatedCred2.algorithm, delegatedCred.algorithm) + } + + if !bytes.Equal(delegatedCred2.signature, delegatedCred.signature) { + t.Error("Signature mismatch") + } + } +} + +var dcServerTests = []struct { + clientDCSupport bool + clientMaxVers uint16 + serverMaxVers uint16 + expectSuccess bool + expectDC bool + name string +}{ + {true, VersionTLS13, VersionTLS13, true, true, "tls13: DC client support"}, + {false, VersionTLS13, VersionTLS13, true, false, "DC not client support"}, + {true, VersionTLS12, VersionTLS13, true, false, "client using TLS 1.2. No DC is supported in that version."}, + {true, VersionTLS13, VersionTLS12, true, false, "server using TLS 1.2. No DC is supported in that version."}, + {true, VersionTLS11, VersionTLS13, true, false, "client using TLS 1.1. No DC is supported in that version."}, + {true, VersionTLS13, VersionTLS10, false, false, "server using TLS 1.0. No DC is supported in that version."}, +} + +var dcClientTests = []struct { + serverDCSupport bool + clientMaxVers uint16 + serverMaxVers uint16 + expectSuccess bool + expectDC bool + name string +}{ + {true, VersionTLS13, VersionTLS13, true, true, "tls13: DC server support"}, + {false, VersionTLS13, VersionTLS13, true, false, "DC not server support"}, + {true, VersionTLS12, VersionTLS13, true, false, "client using TLS 1.2. No DC is supported in that version."}, + {true, VersionTLS13, VersionTLS12, true, false, "server using TLS 1.2. No DC is supported in that version."}, + {true, VersionTLS11, VersionTLS13, true, false, "client using TLS 1.1. No DC is supported in that version."}, + {true, VersionTLS13, VersionTLS10, false, false, "server using TLS 1.0. No DC is supported in that version."}, +} + +// dcCount defines the delegated credential to be used as returned by the +// getCertificate or getClientCertificate callback. This allows to use +// delegated credentials with different algorithms at each run of the +// tests. +var dcCount int + +// Checks that the client suppports a version >= 1.3 and accepts Delegated +// Credentials. If so, it returns the delegation certificate; otherwise it +// returns a non-delegated certificate. +func testServerGetCertificate(ch *ClientHelloInfo) (*Certificate, error) { + versOk := false + for _, vers := range ch.SupportedVersions { + versOk = versOk || (vers >= uint16(VersionTLS13)) + } + + if versOk && ch.SupportsDelegatedCredential { + serverCert := dcTestCerts["dcP256"] + serverCert.DelegatedCredentials = serverDC[dcCount:] + return serverCert, nil + } + return dcTestCerts["no dc"], nil + +} + +// Used when the server doesn't support DCs. +// This function always returns a non-DC cert. +func testServerGetCertificateNoDC(ch *ClientHelloInfo) (*Certificate, error) { + return dcTestCerts["no dc"], nil +} + +// Checks that the client suppports a version >= 1.3 and accepts Delegated +// Credentials. If so, it returns the delegation certificate; otherwise it +// returns a non-Delegated certificate. +func testClientGetCertificate(cr *CertificateRequestInfo) (*Certificate, error) { + versOk := false + if cr.Version == VersionTLS13 { + versOk = true + } + + if versOk && cr.SupportsDelegatedCredential { + clientCert := dcTestCerts["dcP256"] + clientCert.DelegatedCredentials = clientDC[dcCount:] + return clientCert, nil + } + return dcTestCerts["no dc"], nil + +} + +// Tests the handshake and one round of application data. Returns true if the +// connection correctly used a Delegated Credential. +func testConnWithDC(t *testing.T, clientMsg, serverMsg string, clientConfig, serverConfig *Config, peer string) (bool, error) { + ln := newLocalListener(t) + defer ln.Close() + + serverCh := make(chan *Conn, 1) + var serverErr error + go func() { + serverConn, err := ln.Accept() + if err != nil { + serverErr = err + serverCh <- nil + return + } + server := Server(serverConn, serverConfig) + if err := server.Handshake(); err != nil { + serverErr = fmt.Errorf("handshake error: %v", err) + serverCh <- nil + return + } + serverCh <- server + }() + client, err := Dial("tcp", ln.Addr().String(), clientConfig) + + if err != nil { + return false, err + } + defer client.Close() + + server := <-serverCh + if server == nil { + return false, serverErr + } + + bufLen := len(clientMsg) + if len(serverMsg) > len(clientMsg) { + bufLen = len(serverMsg) + } + buf := make([]byte, bufLen) + + client.Write([]byte(clientMsg)) + n, err := server.Read(buf) + if err != nil || n != len(clientMsg) || string(buf[:n]) != clientMsg { + return false, fmt.Errorf("Server read = %d, buf= %q; want %d, %s", n, buf, len(clientMsg), clientMsg) + } + + server.Write([]byte(serverMsg)) + n, err = client.Read(buf) + if n != len(serverMsg) || err != nil || string(buf[:n]) != serverMsg { + return false, fmt.Errorf("Client read = %d, %v, data %q; want %d, nil, %s", n, err, buf, len(serverMsg), serverMsg) + } + + if peer == "server" { + return (server.verifiedDC != nil), nil + } else if peer == "client" { + return (client.verifiedDC != nil), nil + } else if peer == "both" { + return (client.verifiedDC != nil && server.verifiedDC != nil), nil + } + + return false, nil +} + +// Test the server authentication with the Delegated Credential extension. +func TestDCHandshakeServerAuth(t *testing.T) { + serverMsg := "hello, client" + clientMsg := "hello, server" + initDCTest() + clientConfig := dcTestConfig.Clone() + serverConfig := dcTestConfig.Clone() + + for i, test := range dcServerTests { + clientConfig.SupportDelegatedCredential = test.clientDCSupport + for dcCount = 0; dcCount < len(dcTestDCSignatureScheme); dcCount++ { + if test.serverMaxVers < VersionTLS13 { + t.Logf("Server doesn't support DCs, not offering. test %d", i) + serverConfig.GetCertificate = testServerGetCertificateNoDC + } else { + serverConfig.GetCertificate = testServerGetCertificate + } + + clientConfig.MaxVersion = test.clientMaxVers + serverConfig.MaxVersion = test.serverMaxVers + usedDC, err := testConnWithDC(t, clientMsg, serverMsg, clientConfig, serverConfig, "client") + + if err != nil && test.expectSuccess { + t.Errorf("test #%d (%s) with signature algorithm #%d fails: %s", i, test.name, dcCount, err.Error()) + } else if err == nil && !test.expectSuccess { + t.Errorf("test #%d (%s) with signature algorithm #%d succeeds; expected failure", i, test.name, dcCount) + } + + if usedDC != test.expectDC { + t.Errorf("test #%d (%s) with signature algorithm #%d usedDC = %v; expected %v", i, test.name, dcCount, usedDC, test.expectDC) + } + } + } +} + +// Test the client authentication with the Delegated Credential extension. +func TestDCHandshakeClientAuth(t *testing.T) { + clientMsg := "hello, server" + serverMsg := "hello, client" + + initDCTest() + serverConfig := dcTestConfig.Clone() + serverConfig.ClientAuth = RequestClientCert + serverConfig.GetCertificate = testServerGetCertificate + clientConfig := dcTestConfig.Clone() + clientConfig.GetClientCertificate = testClientGetCertificate + + for j, test := range dcClientTests { + serverConfig.SupportDelegatedCredential = test.serverDCSupport + + for dcCount = 0; dcCount < len(dcTestDCSignatureScheme); dcCount++ { + serverConfig.MaxVersion = test.serverMaxVers + clientConfig.MaxVersion = test.clientMaxVers + + usedDC, err := testConnWithDC(t, clientMsg, serverMsg, clientConfig, serverConfig, "server") + + if err != nil && test.expectSuccess { + t.Errorf("test #%d (%s) with signature algorithm #%d fails: %s", j, test.name, dcCount, err.Error()) + } else if err == nil && !test.expectSuccess { + t.Errorf("test #%d (%s) with signature algorithm #%d succeeds; expected failure", j, test.name, dcCount) + } + + if usedDC != test.expectDC { + t.Errorf("test #%d (%s) with signature algorithm #%d usedDC = %v; expected %v", j, test.name, dcCount, usedDC, test.expectDC) + } + } + } +} + +// Test server and client authentication with the Delegated Credential extension. +func TestDCHandshakeClientAndServerAuth(t *testing.T) { + clientMsg := "hello, server" + serverMsg := "hello, client" + + initDCTest() + serverConfig := dcTestConfig.Clone() + serverConfig.ClientAuth = RequestClientCert + serverConfig.GetCertificate = testServerGetCertificate + clientConfig := dcTestConfig.Clone() + clientConfig.GetClientCertificate = testClientGetCertificate + + serverConfig.SupportDelegatedCredential = true + clientConfig.SupportDelegatedCredential = true + + serverConfig.MaxVersion = VersionTLS13 + clientConfig.MaxVersion = VersionTLS13 + + usedDC, err := testConnWithDC(t, clientMsg, serverMsg, clientConfig, serverConfig, "both") + + if err != nil { + t.Errorf("test server and client auth fails: %s", err.Error()) + } + + if usedDC != true { + t.Errorf("test server and client auth does not succeed") + } +} diff --git a/src/crypto/tls/ech.go b/src/crypto/tls/ech.go new file mode 100644 index 00000000000..8e71a3a8b80 --- /dev/null +++ b/src/crypto/tls/ech.go @@ -0,0 +1,1094 @@ +// Copyright 2020 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "errors" + "fmt" + "io" + + "github.com/cloudflare/circl/hpke" + + "golang.org/x/crypto/cryptobyte" +) + +const ( + // Constants for TLS operations + echAcceptConfLabel = "ech accept confirmation" + echAcceptConfHRRLabel = "hrr ech accept confirmation" + + // Constants for HPKE operations + echHpkeInfoSetup = "tls ech" + + // When sent in the ClientHello, the first byte of the payload of the ECH + // extension indicates whether the message is the ClientHelloOuter or + // ClientHelloInner. + echClientHelloOuterVariant uint8 = 0 + echClientHelloInnerVariant uint8 = 1 +) + +var ( + zeros = [8]byte{} +) + +// echOfferOrGrease is called by the client after generating its ClientHello +// message to decide if it will offer or GREASE ECH. It does neither if ECH is +// disabled. Returns a pair of ClientHello messages, hello and helloInner. If +// offering ECH, these are the ClienthelloOuter and ClientHelloInner +// respectively. Otherwise, hello is the ClientHello and helloInner == nil. +// +// TODO(cjpatton): "[When offering ECH, the client] MUST NOT offer to resume any +// session for TLS 1.2 and below [in ClientHelloInner]." +func (c *Conn) echOfferOrGrease(helloBase *clientHelloMsg) (hello, helloInner *clientHelloMsg, err error) { + config := c.config + + if !config.ECHEnabled || testingECHTriggerBypassBeforeHRR { + // Bypass ECH. + return helloBase, nil, nil + } + + // Choose the ECHConfig to use for this connection. If none is available, or + // if we're not offering TLS 1.3 or above, then GREASE. + echConfig := config.echSelectConfig() + if echConfig == nil || config.maxSupportedVersion(roleClient) < VersionTLS13 { + var err error + + // Generate a dummy ClientECH. + helloBase.ech, err = echGenerateGreaseExt(config.rand()) + if err != nil { + return nil, nil, fmt.Errorf("tls: ech: failed to generate grease ECH: %s", err) + } + + // GREASE ECH. + c.ech.offered = false + c.ech.greased = true + helloBase.raw = nil + return helloBase, nil, nil + } + + // Store the ECH config parameters that are needed later. + c.ech.configId = echConfig.configId + c.ech.maxNameLen = int(echConfig.maxNameLen) + + // Generate the HPKE context. Store it in case of HRR. + var enc []byte + enc, c.ech.sealer, err = echConfig.setupSealer(config.rand()) + if err != nil { + return nil, nil, fmt.Errorf("tls: ech: %s", err) + } + + // ClientHelloInner is constructed from the base ClientHello. The payload of + // the "encrypted_client_hello" extension is a single 1 byte indicating that + // this is the ClientHelloInner. + helloInner = helloBase + helloInner.ech = []byte{echClientHelloInnerVariant} + + // Ensure that only TLS 1.3 and above are offered in the inner handshake. + if v := helloInner.supportedVersions; len(v) == 0 || v[len(v)-1] < VersionTLS13 { + return nil, nil, errors.New("tls: ech: only TLS 1.3 is allowed in ClientHelloInner") + } + + // ClientHelloOuter is constructed by generating a fresh ClientHello and + // copying "session_id" from ClientHelloInner, setting "server_name" to the + // client-facing server, and adding the "encrypted_client_hello" extension. + // + // In addition, we discard the "key_share" and instead use the one from + // ClientHelloInner. + hello, _, err = c.makeClientHello(config.MinVersion) + if err != nil { + return nil, nil, fmt.Errorf("tls: ech: %s", err) + } + hello.sessionId = helloBase.sessionId + hello.serverName = hostnameInSNI(string(echConfig.rawPublicName)) + if err := c.echUpdateClientHelloOuter(hello, helloInner, enc); err != nil { + return nil, nil, err + } + + // Offer ECH. + c.ech.offered = true + helloInner.raw = nil + hello.raw = nil + return hello, helloInner, nil +} + +// echUpdateClientHelloOuter is called by the client to construct the payload of +// the ECH extension in the outer handshake. +func (c *Conn) echUpdateClientHelloOuter(hello, helloInner *clientHelloMsg, enc []byte) error { + var ( + ech echClientOuter + err error + ) + + // Copy all compressed extensions from ClientHelloInner into + // ClientHelloOuter. + for _, ext := range echOuterExtensions() { + echCopyExtensionFromClientHelloInner(hello, helloInner, ext) + } + + // Always copy the "key_shares" extension from ClientHelloInner, regardless + // of whether it gets compressed. + hello.keyShares = helloInner.keyShares + + _, kdf, aead := c.ech.sealer.Suite().Params() + ech.handle.suite.kdfId = uint16(kdf) + ech.handle.suite.aeadId = uint16(aead) + ech.handle.configId = c.ech.configId + ech.handle.enc = enc + + // EncodedClientHelloInner + helloInner.raw = nil + helloInnerMarshalled, err := helloInner.marshal() + if err != nil { + return fmt.Errorf("tls: ech: failed to marshal helloInner: %w", err) + } + encodedHelloInner := echEncodeClientHelloInner( + helloInnerMarshalled, + len(helloInner.serverName), + c.ech.maxNameLen) + if encodedHelloInner == nil { + return errors.New("tls: ech: encoding of EncodedClientHelloInner failed") + } + + // ClientHelloOuterAAD + hello.raw = nil + hello.ech = ech.marshal() + helloMarshalled, err := hello.marshal() + if err != nil { + return fmt.Errorf("tls: ech: failed to marshal hello: %w", err) + } + helloOuterAad := echEncodeClientHelloOuterAAD(helloMarshalled, + aead.CipherLen(uint(len(encodedHelloInner)))) + if helloOuterAad == nil { + return errors.New("tls: ech: encoding of ClientHelloOuterAAD failed") + } + + ech.payload, err = c.ech.sealer.Seal(encodedHelloInner, helloOuterAad) + if err != nil { + return fmt.Errorf("tls: ech: seal failed: %s", err) + } + if testingECHTriggerPayloadDecryptError { + ech.payload[0] ^= 0xff // Inauthentic ciphertext + } + ech.raw = nil + hello.ech = ech.marshal() + + helloInner.raw = nil + hello.raw = nil + return nil +} + +// echAcceptOrReject is called by the client-facing server to determine whether +// ECH was offered by the client, and if so, whether to accept or reject. The +// return value is the ClientHello that will be used for the connection. +// +// This function is called prior to processing the ClientHello. In case of +// HelloRetryRequest, it is also called before processing the second +// ClientHello. This is indicated by the afterHRR flag. +func (c *Conn) echAcceptOrReject(hello *clientHelloMsg, afterHRR bool) (*clientHelloMsg, error) { + config := c.config + p := config.ServerECHProvider + + if !config.echCanAccept() { + // Bypass ECH. + return hello, nil + } + + if len(hello.ech) > 0 { // The ECH extension is present + switch hello.ech[0] { + case echClientHelloInnerVariant: // inner handshake + if len(hello.ech) > 1 { + c.sendAlert(alertIllegalParameter) + return nil, errors.New("ech: inner handshake has non-empty payload") + } + + // Continue as the backend server. + return hello, nil + case echClientHelloOuterVariant: // outer handshake + default: + c.sendAlert(alertIllegalParameter) + return nil, errors.New("ech: inner handshake has non-empty payload") + } + } else { + if c.ech.offered { + // This occurs if the server accepted prior to HRR, but the client + // failed to send the ECH extension in the second ClientHelloOuter. This + // would cause ClientHelloOuter to be used after ClientHelloInner, which + // is illegal. + c.sendAlert(alertMissingExtension) + return nil, errors.New("ech: hrr: bypass after offer") + } + + // Bypass ECH. + return hello, nil + } + + if afterHRR && !c.ech.offered && !c.ech.greased { + // The client bypassed ECH prior to HRR, but not after. This could + // cause ClientHelloInner to be used after ClientHelloOuter, which is + // illegal. + c.sendAlert(alertIllegalParameter) + return nil, errors.New("ech: hrr: offer or grease after bypass") + } + + // Parse ClientECH. + ech, err := echUnmarshalClientOuter(hello.ech) + if err != nil { + c.sendAlert(alertIllegalParameter) + return nil, fmt.Errorf("ech: failed to parse extension: %s", err) + } + + // Make sure that the HPKE suite and config id don't change across HRR and + // that the encapsulated key is not present after HRR. + if afterHRR && c.ech.offered { + _, kdf, aead := c.ech.opener.Suite().Params() + if ech.handle.suite.kdfId != uint16(kdf) || + ech.handle.suite.aeadId != uint16(aead) || + ech.handle.configId != c.ech.configId || + len(ech.handle.enc) > 0 { + c.sendAlert(alertIllegalParameter) + return nil, errors.New("ech: hrr: illegal handle in second hello") + } + } + + // Store the config id in case of HRR. + c.ech.configId = ech.handle.configId + + // Ask the ECH provider for the HPKE context. + if c.ech.opener == nil { + res := p.GetDecryptionContext(ech.handle.marshal(), extensionECH) + + // Compute retry configurations, skipping those indicating an + // unsupported version. + if len(res.RetryConfigs) > 0 { + configs, err := UnmarshalECHConfigs(res.RetryConfigs) // skips unrecognized versions + if err != nil { + c.sendAlert(alertInternalError) + return nil, fmt.Errorf("ech: %s", err) + } + + if len(configs) > 0 { + c.ech.retryConfigs, err = echMarshalConfigs(configs) + if err != nil { + c.sendAlert(alertInternalError) + return nil, fmt.Errorf("ech: %s", err) + } + } + + // Check if the outer SNI matches the public name of any ECH config + // advertised by the client-facing server. As of + // draft-ietf-tls-esni-10, the client is required to use the ECH + // config's public name as the outer SNI. Although there's no real + // reason for the server to enforce this, it's worth noting it when + // it happens. + pubNameMatches := false + for _, config := range configs { + if hello.serverName == string(config.rawPublicName) { + pubNameMatches = true + } + } + if !pubNameMatches { + c.handleCFEvent(CFEventECHPublicNameMismatch{}) + } + } + + switch res.Status { + case ECHProviderSuccess: + c.ech.opener, err = hpke.UnmarshalOpener(res.Context) + if err != nil { + c.sendAlert(alertInternalError) + return nil, fmt.Errorf("ech: %s", err) + } + case ECHProviderReject: + // Reject ECH. We do not know at this point whether the client + // intended to offer or grease ECH, so we presume grease until the + // client indicates rejection by sending an "ech_required" alert. + c.ech.greased = true + return hello, nil + case ECHProviderAbort: + c.sendAlert(alert(res.Alert)) + return nil, fmt.Errorf("ech: provider aborted: %s", res.Error) + default: + c.sendAlert(alertInternalError) + return nil, errors.New("ech: unexpected provider status") + } + } + + // ClientHelloOuterAAD + helloMarshalled, err := hello.marshal() + if err != nil { + return nil, fmt.Errorf("tls: ech: failed to marshal hello: %w", err) + } + rawHelloOuterAad := echEncodeClientHelloOuterAAD(helloMarshalled, uint(len(ech.payload))) + if rawHelloOuterAad == nil { + // This occurs if the ClientHelloOuter is malformed. This values was + // already parsed into `hello`, so this should not happen. + c.sendAlert(alertInternalError) + return nil, fmt.Errorf("ech: failed to encode ClientHelloOuterAAD") + } + + // EncodedClientHelloInner + rawEncodedHelloInner, err := c.ech.opener.Open(ech.payload, rawHelloOuterAad) + if err != nil { + if afterHRR && c.ech.accepted { + // Don't reject after accept, as this would result in processing the + // ClientHelloOuter after processing the ClientHelloInner. + c.sendAlert(alertDecryptError) + return nil, fmt.Errorf("ech: hrr: reject after accept: %s", err) + } + + // Reject ECH. We do not know at this point whether the client + // intended to offer or grease ECH, so we presume grease until the + // client indicates rejection by sending an "ech_required" alert. + c.ech.greased = true + return hello, nil + } + + // ClientHelloInner + rawHelloInner := echDecodeClientHelloInner(rawEncodedHelloInner, helloMarshalled, hello.sessionId) + if rawHelloInner == nil { + c.sendAlert(alertIllegalParameter) + return nil, fmt.Errorf("ech: failed to decode EncodedClientHelloInner") + } + helloInner := new(clientHelloMsg) + if !helloInner.unmarshal(rawHelloInner) { + c.sendAlert(alertIllegalParameter) + return nil, fmt.Errorf("ech: failed to parse ClientHelloInner") + } + + // Check for a well-formed ECH extension. + if len(helloInner.ech) != 1 || + helloInner.ech[0] != echClientHelloInnerVariant { + c.sendAlert(alertIllegalParameter) + return nil, fmt.Errorf("ech: ClientHelloInner does not have a well-formed ECH extension") + } + + // Check that the client did not offer TLS 1.2 or below in the inner + // handshake. + helloInnerSupportsTLS12OrBelow := len(helloInner.supportedVersions) == 0 + for _, v := range helloInner.supportedVersions { + if v < VersionTLS13 { + helloInnerSupportsTLS12OrBelow = true + } + } + if helloInnerSupportsTLS12OrBelow { + c.sendAlert(alertIllegalParameter) + return nil, errors.New("ech: ClientHelloInner offers TLS 1.2 or below") + } + + // Accept ECH. + c.ech.offered = true + c.ech.accepted = true + return helloInner, nil +} + +// echClientOuter represents a ClientECH structure, the payload of the client's +// "encrypted_client_hello" extension that appears in the outer handshake. +type echClientOuter struct { + raw []byte + + // Parsed from raw + handle echContextHandle + payload []byte +} + +// echUnmarshalClientOuter parses a ClientECH structure. The caller provides the +// ECH version indicated by the client. +func echUnmarshalClientOuter(raw []byte) (*echClientOuter, error) { + s := cryptobyte.String(raw) + ech := new(echClientOuter) + ech.raw = raw + + // Make sure this is the outer handshake. + var variant uint8 + if !s.ReadUint8(&variant) { + return nil, fmt.Errorf("error parsing ClientECH.type") + } + if variant != echClientHelloOuterVariant { + return nil, fmt.Errorf("unexpected ClientECH.type (want outer (0))") + } + + // Parse the context handle. + if !echReadContextHandle(&s, &ech.handle) { + return nil, fmt.Errorf("error parsing context handle") + } + endOfContextHandle := len(raw) - len(s) + ech.handle.raw = raw[1:endOfContextHandle] + + // Parse the payload. + var t cryptobyte.String + if !s.ReadUint16LengthPrefixed(&t) || + !t.ReadBytes(&ech.payload, len(t)) || !s.Empty() { + return nil, fmt.Errorf("error parsing payload") + } + + return ech, nil +} + +func (ech *echClientOuter) marshal() []byte { + if ech.raw != nil { + return ech.raw + } + var b cryptobyte.Builder + b.AddUint8(echClientHelloOuterVariant) + b.AddBytes(ech.handle.marshal()) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(ech.payload) + }) + return b.BytesOrPanic() +} + +// echContextHandle represents the prefix of a ClientECH structure used by +// the server to compute the HPKE context. +type echContextHandle struct { + raw []byte + + // Parsed from raw + suite hpkeSymmetricCipherSuite + configId uint8 + enc []byte +} + +func (handle *echContextHandle) marshal() []byte { + if handle.raw != nil { + return handle.raw + } + var b cryptobyte.Builder + b.AddUint16(handle.suite.kdfId) + b.AddUint16(handle.suite.aeadId) + b.AddUint8(handle.configId) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(handle.enc) + }) + return b.BytesOrPanic() +} + +func echReadContextHandle(s *cryptobyte.String, handle *echContextHandle) bool { + var t cryptobyte.String + if !s.ReadUint16(&handle.suite.kdfId) || // cipher_suite.kdf_id + !s.ReadUint16(&handle.suite.aeadId) || // cipher_suite.aead_id + !s.ReadUint8(&handle.configId) || // config_id + !s.ReadUint16LengthPrefixed(&t) || // enc + !t.ReadBytes(&handle.enc, len(t)) { + return false + } + return true +} + +// hpkeSymmetricCipherSuite represents an ECH ciphersuite, a KDF/AEAD algorithm pair. This +// is different from an HPKE ciphersuite, which represents a KEM/KDF/AEAD +// triple. +type hpkeSymmetricCipherSuite struct { + kdfId, aeadId uint16 +} + +// Generates a grease ECH extension using a hard-coded KEM public key. +func echGenerateGreaseExt(rand io.Reader) ([]byte, error) { + var err error + var dummyX25519PublicKey = []byte{ + 143, 38, 37, 36, 12, 6, 229, 30, 140, 27, 167, 73, 26, 100, 203, 107, 216, + 81, 163, 222, 52, 211, 54, 210, 46, 37, 78, 216, 157, 97, 241, 244, + } + dummyEncodedHelloInnerLen := 100 // TODO(cjpatton): Compute this correctly. + kem, kdf, aead := defaultHPKESuite.Params() + + pk, err := kem.Scheme().UnmarshalBinaryPublicKey(dummyX25519PublicKey) + if err != nil { + return nil, fmt.Errorf("tls: grease ech: failed to parse dummy public key: %s", err) + } + sender, err := defaultHPKESuite.NewSender(pk, nil) + if err != nil { + return nil, fmt.Errorf("tls: grease ech: failed to create sender: %s", err) + } + + var ech echClientOuter + ech.handle.suite.kdfId = uint16(kdf) + ech.handle.suite.aeadId = uint16(aead) + randomByte := make([]byte, 1) + _, err = io.ReadFull(rand, randomByte) + if err != nil { + return nil, fmt.Errorf("tls: grease ech: %s", err) + } + ech.handle.configId = randomByte[0] + ech.handle.enc, _, err = sender.Setup(rand) + if err != nil { + return nil, fmt.Errorf("tls: grease ech: %s", err) + } + ech.payload = make([]byte, + int(aead.CipherLen(uint(dummyEncodedHelloInnerLen)))) + if _, err = io.ReadFull(rand, ech.payload); err != nil { + return nil, fmt.Errorf("tls: grease ech: %s", err) + } + return ech.marshal(), nil +} + +// echEncodeClientHelloInner interprets innerData as a ClientHelloInner message +// and transforms it into an EncodedClientHelloInner. Returns nil if parsing +// innerData fails. +func echEncodeClientHelloInner(innerData []byte, serverNameLen, maxNameLen int) []byte { + var ( + errIllegalParameter = errors.New("illegal parameter") + outerExtensions = echOuterExtensions() + msgType uint8 + legacyVersion uint16 + random []byte + legacySessionId cryptobyte.String + cipherSuites cryptobyte.String + legacyCompressionMethods cryptobyte.String + extensions cryptobyte.String + s cryptobyte.String + b cryptobyte.Builder + ) + + u := cryptobyte.String(innerData) + if !u.ReadUint8(&msgType) || + !u.ReadUint24LengthPrefixed(&s) || !u.Empty() { + return nil + } + + if !s.ReadUint16(&legacyVersion) || + !s.ReadBytes(&random, 32) || + !s.ReadUint8LengthPrefixed(&legacySessionId) || + !s.ReadUint16LengthPrefixed(&cipherSuites) || + !s.ReadUint8LengthPrefixed(&legacyCompressionMethods) { + return nil + } + + if s.Empty() { + // Extensions field must be present in TLS 1.3. + return nil + } + + if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { + return nil + } + + b.AddUint16(legacyVersion) + b.AddBytes(random) + b.AddUint8(0) // 0-length legacy_session_id + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(cipherSuites) + }) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(legacyCompressionMethods) + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if testingECHOuterExtIncorrectOrder { + // Replace outer extensions with "outer_extension" extension, but in + // the incorrect order. + echAddOuterExtensions(b, outerExtensions) + } + + for !extensions.Empty() { + var ext uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&ext) || + !extensions.ReadUint16LengthPrefixed(&extData) { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + + if len(outerExtensions) > 0 && ext == outerExtensions[0] { + if !testingECHOuterExtIncorrectOrder { + // Replace outer extensions with "outer_extension" extension. + echAddOuterExtensions(b, outerExtensions) + } + + // Consume the remaining outer extensions. + for _, outerExt := range outerExtensions[1:] { + if !extensions.ReadUint16(&ext) || + !extensions.ReadUint16LengthPrefixed(&extData) { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + if ext != outerExt { + panic("internal error: malformed ClientHelloInner") + } + } + + } else { + b.AddUint16(ext) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(extData) + }) + } + } + }) + + encodedData, err := b.Bytes() + if err == errIllegalParameter { + return nil // Input malformed + } else if err != nil { + panic(err) // Host encountered internal error + } + + // Add padding. + paddingLen := 0 + if serverNameLen > 0 { + // draft-ietf-tls-esni-13, Section 6.1.3: + // + // If the ClientHelloInner contained a "server_name" extension with a + // name of length D, add max(0, L - D) bytes of padding. + if n := maxNameLen - serverNameLen; n > 0 { + paddingLen += n + } + } else { + // draft-ietf-tls-esni-13, Section 6.1.3: + // + // If the ClientHelloInner did not contain a "server_name" extension + // (e.g., if the client is connecting to an IP address), add L + 9 bytes + // of padding. This is the length of a "server_name" extension with an + // L-byte name. + const sniPaddingLen = 9 + paddingLen += sniPaddingLen + maxNameLen + } + paddingLen = 31 - ((len(encodedData) + paddingLen - 1) % 32) + for i := 0; i < paddingLen; i++ { + encodedData = append(encodedData, 0) + } + + return encodedData +} + +func echAddOuterExtensions(b *cryptobyte.Builder, outerExtensions []uint16) { + b.AddUint16(extensionECHOuterExtensions) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + for _, outerExt := range outerExtensions { + b.AddUint16(outerExt) + } + if testingECHOuterExtIllegal { + // This is not allowed. + b.AddUint16(extensionECH) + } + }) + }) +} + +// echDecodeClientHelloInner interprets encodedData as an EncodedClientHelloInner +// message and substitutes the "outer_extension" extension with extensions from +// outerData, interpreted as the ClientHelloOuter message. Returns nil if +// parsing encodedData fails. +func echDecodeClientHelloInner(encodedData, outerData, outerSessionId []byte) []byte { + var ( + errIllegalParameter = errors.New("illegal parameter") + legacyVersion uint16 + random []byte + legacySessionId cryptobyte.String + cipherSuites cryptobyte.String + legacyCompressionMethods cryptobyte.String + extensions cryptobyte.String + b cryptobyte.Builder + ) + + s := cryptobyte.String(encodedData) + if !s.ReadUint16(&legacyVersion) || + !s.ReadBytes(&random, 32) || + !s.ReadUint8LengthPrefixed(&legacySessionId) || + !s.ReadUint16LengthPrefixed(&cipherSuites) || + !s.ReadUint8LengthPrefixed(&legacyCompressionMethods) { + return nil + } + + if len(legacySessionId) > 0 { + return nil + } + + if s.Empty() { + // Extensions field must be present in TLS 1.3. + return nil + } + + if !s.ReadUint16LengthPrefixed(&extensions) { + return nil + } + + b.AddUint8(typeClientHello) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(legacyVersion) + b.AddBytes(random) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(outerSessionId) // ClientHelloOuter.legacy_session_id + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(cipherSuites) + }) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(legacyCompressionMethods) + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + var handledOuterExtensions bool + for !extensions.Empty() { + var ext uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&ext) || + !extensions.ReadUint16LengthPrefixed(&extData) { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + + if ext == extensionECHOuterExtensions { + if handledOuterExtensions { + // It is an error to send any extension more than once in a + // single message. + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + handledOuterExtensions = true + + // Read the referenced outer extensions. + referencedExts := make([]uint16, 0, 10) + var outerExtData cryptobyte.String + if !extData.ReadUint8LengthPrefixed(&outerExtData) || + len(outerExtData)%2 != 0 || + !extData.Empty() { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + for !outerExtData.Empty() { + if !outerExtData.ReadUint16(&ext) || + ext == extensionECH { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + referencedExts = append(referencedExts, ext) + } + + // Add the outer extensions from the ClientHelloOuter into the + // ClientHelloInner. + outerCt := 0 + r := processClientHelloExtensions(outerData, func(ext uint16, extData cryptobyte.String) bool { + if outerCt < len(referencedExts) && ext == referencedExts[outerCt] { + outerCt++ + b.AddUint16(ext) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(extData) + }) + } + return true + }) + + // Ensure that all outer extensions have been incorporated + // exactly once, and in the correct order. + if !r || outerCt != len(referencedExts) { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + } else { + b.AddUint16(ext) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(extData) + }) + } + } + }) + }) + + innerData, err := b.Bytes() + if err == errIllegalParameter { + return nil // Input malformed + } else if err != nil { + panic(err) // Host encountered internal error + } + + // Read the padding. + for !s.Empty() { + var zero uint8 + if !s.ReadUint8(&zero) || zero != 0 { + return nil + } + } + + return innerData +} + +// echEncodeClientHelloOuterAAD interprets outerData as ClientHelloOuter and +// constructs a ClientHelloOuterAAD. The output doesn't have the 4-byte prefix +// that indicates the handshake message type and its length. +func echEncodeClientHelloOuterAAD(outerData []byte, payloadLen uint) []byte { + var ( + errIllegalParameter = errors.New("illegal parameter") + msgType uint8 + legacyVersion uint16 + random []byte + legacySessionId cryptobyte.String + cipherSuites cryptobyte.String + legacyCompressionMethods cryptobyte.String + extensions cryptobyte.String + s cryptobyte.String + b cryptobyte.Builder + ) + + u := cryptobyte.String(outerData) + if !u.ReadUint8(&msgType) || + !u.ReadUint24LengthPrefixed(&s) || !u.Empty() { + return nil + } + + if !s.ReadUint16(&legacyVersion) || + !s.ReadBytes(&random, 32) || + !s.ReadUint8LengthPrefixed(&legacySessionId) || + !s.ReadUint16LengthPrefixed(&cipherSuites) || + !s.ReadUint8LengthPrefixed(&legacyCompressionMethods) { + return nil + } + + if s.Empty() { + // Extensions field must be present in TLS 1.3. + return nil + } + + if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { + return nil + } + + b.AddUint16(legacyVersion) + b.AddBytes(random) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(legacySessionId) + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(cipherSuites) + }) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(legacyCompressionMethods) + }) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for !extensions.Empty() { + var ext uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&ext) || + !extensions.ReadUint16LengthPrefixed(&extData) { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + + // If this is the ECH extension and the payload is the outer variant + // of ClientECH, then replace the payloadLen 0 bytes. + if ext == extensionECH { + ech, err := echUnmarshalClientOuter(extData) + if err != nil { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + ech.payload = make([]byte, payloadLen) + ech.raw = nil + extData = ech.marshal() + } + + b.AddUint16(ext) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(extData) + }) + } + }) + + outerAadData, err := b.Bytes() + if err == errIllegalParameter { + return nil // Input malformed + } else if err != nil { + panic(err) // Host encountered internal error + } + + return outerAadData +} + +// echEncodeAcceptConfHelloRetryRequest interprets data as a ServerHello message +// and replaces the payload of the ECH extension with 8 zero bytes. The output +// includes the 4-byte prefix that indicates the message type and its length. +func echEncodeAcceptConfHelloRetryRequest(data []byte) []byte { + var ( + errIllegalParameter = errors.New("illegal parameter") + vers uint16 + random []byte + sessionId []byte + cipherSuite uint16 + compressionMethod uint8 + s cryptobyte.String + b cryptobyte.Builder + ) + + s = cryptobyte.String(data) + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint16(&vers) || !s.ReadBytes(&random, 32) || + !readUint8LengthPrefixed(&s, &sessionId) || + !s.ReadUint16(&cipherSuite) || + !s.ReadUint8(&compressionMethod) { + return nil + } + + if s.Empty() { + // ServerHello is optionally followed by extension data + return nil + } + + var extensions cryptobyte.String + if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { + return nil + } + + b.AddUint8(typeServerHello) + b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16(vers) + b.AddBytes(random) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(sessionId) + }) + b.AddUint16(cipherSuite) + b.AddUint8(compressionMethod) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for !extensions.Empty() { + var extension uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&extension) || + !extensions.ReadUint16LengthPrefixed(&extData) { + panic(cryptobyte.BuildError{Err: errIllegalParameter}) + } + + b.AddUint16(extension) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + if extension == extensionECH { + b.AddBytes(zeros[:8]) + } else { + b.AddBytes(extData) + } + }) + } + }) + }) + + encodedData, err := b.Bytes() + if err == errIllegalParameter { + return nil // Input malformed + } else if err != nil { + panic(err) // Host encountered internal error + } + + return encodedData +} + +// processClientHelloExtensions interprets data as a ClientHello and applies a +// function proc to each extension. Returns a bool indicating whether parsing +// succeeded. +func processClientHelloExtensions(data []byte, proc func(ext uint16, extData cryptobyte.String) bool) bool { + _, extensionsData := splitClientHelloExtensions(data) + if extensionsData == nil { + return false + } + + s := cryptobyte.String(extensionsData) + if s.Empty() { + // Extensions field not present. + return true + } + + var extensions cryptobyte.String + if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() { + return false + } + + for !extensions.Empty() { + var ext uint16 + var extData cryptobyte.String + if !extensions.ReadUint16(&ext) || + !extensions.ReadUint16LengthPrefixed(&extData) { + return false + } + if ok := proc(ext, extData); !ok { + return false + } + } + return true +} + +// splitClientHelloExtensions interprets data as a ClientHello message and +// returns two strings: the first contains the start of the ClientHello up to +// the start of the extensions; and the second is the length-prefixed +// extensions. Returns (nil, nil) if parsing of data fails. +func splitClientHelloExtensions(data []byte) ([]byte, []byte) { + s := cryptobyte.String(data) + + var ignored uint16 + var t cryptobyte.String + if !s.Skip(4) || // message type and uint24 length field + !s.ReadUint16(&ignored) || !s.Skip(32) || // vers, random + !s.ReadUint8LengthPrefixed(&t) { // session_id + return nil, nil + } + + if !s.ReadUint16LengthPrefixed(&t) { // cipher_suites + return nil, nil + } + + if !s.ReadUint8LengthPrefixed(&t) { // compression_methods + return nil, nil + } + + return data[:len(data)-len(s)], s +} + +// TODO(cjpatton): Handle public name as described in draft-ietf-tls-esni-13, +// Section 4. +// +// TODO(cjpatton): Implement ECH config extensions as described in +// draft-ietf-tls-esni-13, Section 4.1. +func (c *Config) echSelectConfig() *ECHConfig { + for _, echConfig := range c.ClientECHConfigs { + if _, err := echConfig.selectSuite(); err == nil && + echConfig.version == extensionECH { + return &echConfig + } + } + return nil +} + +func (c *Config) echCanOffer() bool { + if c == nil { + return false + } + return c.ECHEnabled && + c.echSelectConfig() != nil && + c.maxSupportedVersion(roleClient) >= VersionTLS13 +} + +func (c *Config) echCanAccept() bool { + if c == nil { + return false + } + return c.ECHEnabled && + c.ServerECHProvider != nil && + c.maxSupportedVersion(roleServer) >= VersionTLS13 +} + +// echOuterExtensions returns the list of extensions of the ClientHelloOuter +// that will be incorporated into the CleintHelloInner. +func echOuterExtensions() []uint16 { + // NOTE(cjpatton): It would be nice to incorporate more extensions, but + // "key_share" is the last extension to appear in the ClientHello before + // "pre_shared_key". As a result, the only contiguous sequence of outer + // extensions that contains "key_share" is "key_share" itself. Note that + // we cannot change the order of extensions in the ClientHello, as the + // unit tests expect "key_share" to be the second to last extension. + outerExtensions := []uint16{extensionKeyShare} + if testingECHOuterExtMany { + // NOTE(cjpatton): Incorporating this particular sequence does not + // yield significant savings. However, it's useful to test that our + // server correctly handles a sequence of compressed extensions and + // not just one. + outerExtensions = []uint16{ + extensionStatusRequest, + extensionSupportedCurves, + extensionSupportedPoints, + } + } else if testingECHOuterExtNone { + outerExtensions = []uint16{} + } + + return outerExtensions +} + +func echCopyExtensionFromClientHelloInner(hello, helloInner *clientHelloMsg, ext uint16) { + switch ext { + case extensionStatusRequest: + hello.ocspStapling = helloInner.ocspStapling + case extensionSupportedCurves: + hello.supportedCurves = helloInner.supportedCurves + case extensionSupportedPoints: + hello.supportedPoints = helloInner.supportedPoints + case extensionKeyShare: + hello.keyShares = helloInner.keyShares + default: + panic(fmt.Errorf("tried to copy unrecognized extension: %04x", ext)) + } +} diff --git a/src/crypto/tls/ech_config.go b/src/crypto/tls/ech_config.go new file mode 100644 index 00000000000..62de3cec544 --- /dev/null +++ b/src/crypto/tls/ech_config.go @@ -0,0 +1,165 @@ +// Copyright 2020 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "errors" + "fmt" + "io" + + "github.com/cloudflare/circl/hpke" + "github.com/cloudflare/circl/kem" + + "golang.org/x/crypto/cryptobyte" +) + +// ECHConfig represents an ECH configuration. +type ECHConfig struct { + pk kem.PublicKey + raw []byte + + // Parsed from raw + version uint16 + configId uint8 + rawPublicName []byte + rawPublicKey []byte + kemId uint16 + suites []hpkeSymmetricCipherSuite + maxNameLen uint8 + ignoredExtensions []byte +} + +// UnmarshalECHConfigs parses a sequence of ECH configurations. +func UnmarshalECHConfigs(raw []byte) ([]ECHConfig, error) { + var ( + err error + config ECHConfig + t, contents cryptobyte.String + ) + configs := make([]ECHConfig, 0) + s := cryptobyte.String(raw) + if !s.ReadUint16LengthPrefixed(&t) || !s.Empty() { + return configs, errors.New("error parsing configs") + } + raw = raw[2:] +ConfigsLoop: + for !t.Empty() { + l := len(t) + if !t.ReadUint16(&config.version) || + !t.ReadUint16LengthPrefixed(&contents) { + return nil, errors.New("error parsing config") + } + n := l - len(t) + config.raw = raw[:n] + raw = raw[n:] + + if config.version != extensionECH { + continue ConfigsLoop + } + if !readConfigContents(&contents, &config) { + return nil, errors.New("error parsing config contents") + } + + kem := hpke.KEM(config.kemId) + if !kem.IsValid() { + continue ConfigsLoop + } + config.pk, err = kem.Scheme().UnmarshalBinaryPublicKey(config.rawPublicKey) + if err != nil { + return nil, fmt.Errorf("error parsing public key: %s", err) + } + configs = append(configs, config) + } + return configs, nil +} + +func echMarshalConfigs(configs []ECHConfig) ([]byte, error) { + var b cryptobyte.Builder + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, config := range configs { + if config.raw == nil { + panic("config.raw not set") + } + b.AddBytes(config.raw) + } + }) + return b.Bytes() +} + +func readConfigContents(contents *cryptobyte.String, config *ECHConfig) bool { + var t cryptobyte.String + if !contents.ReadUint8(&config.configId) || + !contents.ReadUint16(&config.kemId) || + !contents.ReadUint16LengthPrefixed(&t) || + !t.ReadBytes(&config.rawPublicKey, len(t)) || + !contents.ReadUint16LengthPrefixed(&t) || + len(t)%4 != 0 { + return false + } + + config.suites = nil + for !t.Empty() { + var kdfId, aeadId uint16 + if !t.ReadUint16(&kdfId) || !t.ReadUint16(&aeadId) { + // This indicates an internal bug. + panic("internal error while parsing contents.cipher_suites") + } + config.suites = append(config.suites, hpkeSymmetricCipherSuite{kdfId, aeadId}) + } + + if !contents.ReadUint8(&config.maxNameLen) || + !contents.ReadUint8LengthPrefixed(&t) || + !t.ReadBytes(&config.rawPublicName, len(t)) || + !contents.ReadUint16LengthPrefixed(&t) || + !t.ReadBytes(&config.ignoredExtensions, len(t)) || + !contents.Empty() { + return false + } + return true +} + +// setupSealer generates the client's HPKE context for use with the ECH +// extension. It returns the context and corresponding encapsulated key. +func (config *ECHConfig) setupSealer(rand io.Reader) (enc []byte, sealer hpke.Sealer, err error) { + if config.raw == nil { + panic("config.raw not set") + } + hpkeSuite, err := config.selectSuite() + if err != nil { + return nil, nil, err + } + info := append(append([]byte(echHpkeInfoSetup), 0), config.raw...) + sender, err := hpkeSuite.NewSender(config.pk, info) + if err != nil { + return nil, nil, err + } + return sender.Setup(rand) +} + +// isPeerCipherSuiteSupported returns true if this configuration indicates +// support for the given ciphersuite. +func (config *ECHConfig) isPeerCipherSuiteSupported(suite hpkeSymmetricCipherSuite) bool { + for _, configSuite := range config.suites { + if suite == configSuite { + return true + } + } + return false +} + +// selectSuite returns the first ciphersuite indicated by this +// configuration that is supported by the caller. +func (config *ECHConfig) selectSuite() (hpke.Suite, error) { + for _, suite := range config.suites { + hpkeSuite, err := hpkeAssembleSuite( + config.kemId, + suite.kdfId, + suite.aeadId, + ) + if err == nil { + return hpkeSuite, nil + } + } + return hpke.Suite{}, errors.New("could not negotiate a ciphersuite") +} diff --git a/src/crypto/tls/ech_provider.go b/src/crypto/tls/ech_provider.go new file mode 100644 index 00000000000..d114efb2766 --- /dev/null +++ b/src/crypto/tls/ech_provider.go @@ -0,0 +1,303 @@ +// Copyright 2020 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "errors" + "fmt" + + "github.com/cloudflare/circl/hpke" + "github.com/cloudflare/circl/kem" + + "golang.org/x/crypto/cryptobyte" +) + +// ECHProvider specifies the interface of an ECH service provider that decrypts +// the ECH payload on behalf of the client-facing server. It also defines the +// set of acceptable ECH configurations. +type ECHProvider interface { + // GetDecryptionContext attempts to construct the HPKE context used by the + // client-facing server for decryption. (See draft-irtf-cfrg-hpke-07, + // Section 5.2.) + // + // handle encodes the parameters of the client's "encrypted_client_hello" + // extension that are needed to construct the context. Since + // draft-ietf-tls-esni-10 these are the ECH cipher suite, the identity of + // the ECH configuration, and the encapsulated key. + // + // version is the version of ECH indicated by the client. + // + // res.Status == ECHProviderStatusSuccess indicates the call was successful + // and the caller may proceed. res.Context is set. + // + // res.Status == ECHProviderStatusReject indicates the caller must reject + // ECH. res.RetryConfigs may be set. + // + // res.Status == ECHProviderStatusAbort indicates the caller should abort + // the handshake. Note that, in some cases, it's appropriate to reject + // rather than abort. In particular, aborting with "illegal_parameter" might + // "stick out". res.Alert and res.Error are set. + GetDecryptionContext(handle []byte, version uint16) (res ECHProviderResult) +} + +// ECHProviderStatus is the status of the ECH provider's response. +type ECHProviderStatus uint + +const ( + ECHProviderSuccess ECHProviderStatus = 0 + ECHProviderReject = 1 + ECHProviderAbort = 2 + + errHPKEInvalidPublicKey = "hpke: invalid KEM public key" +) + +// ECHProviderResult represents the result of invoking the ECH provider. +type ECHProviderResult struct { + Status ECHProviderStatus + + // Alert is the TLS alert sent by the caller when aborting the handshake. + Alert uint8 + + // Error is the error propagated by the caller when aborting the handshake. + Error error + + // RetryConfigs is the sequence of ECH configs to offer to the client for + // retrying the handshake. This may be set in case of success or rejection. + RetryConfigs []byte + + // Context is the server's HPKE context. This is set if ECH is not rejected + // by the provider and no error was reported. The data has the following + // format (in TLS syntax): + // + // enum { sealer(0), opener(1) } HpkeRole; + // + // struct { + // HpkeRole role; + // HpkeKemId kem_id; // as defined in draft-irtf-cfrg-hpke-07 + // HpkeKdfId kdf_id; // as defined in draft-irtf-cfrg-hpke-07 + // HpkeAeadId aead_id; // as defined in draft-irtf-cfrg-hpke-07 + // opaque exporter_secret<0..255>; + // opaque key<0..255>; + // opaque base_nonce<0..255>; + // opaque seq<0..255>; + // } HpkeContext; + Context []byte +} + +// EXP_ECHKeySet implements the ECHProvider interface for a sequence of ECH keys. +// +// NOTE: This API is EXPERIMENTAL and subject to change. +type EXP_ECHKeySet struct { + // The serialized ECHConfigs, in order of the server's preference. + configs []byte + + // Maps a configuration identifier to its secret key. + sk map[uint8]EXP_ECHKey +} + +// EXP_NewECHKeySet constructs an EXP_ECHKeySet. +func EXP_NewECHKeySet(keys []EXP_ECHKey) (*EXP_ECHKeySet, error) { + if len(keys) > 255 { + return nil, fmt.Errorf("tls: ech provider: unable to support more than 255 ECH configurations at once") + } + + keySet := new(EXP_ECHKeySet) + keySet.sk = make(map[uint8]EXP_ECHKey) + configs := make([]byte, 0) + for _, key := range keys { + if _, ok := keySet.sk[key.config.configId]; ok { + return nil, fmt.Errorf("tls: ech provider: ECH config conflict for configId %d", key.config.configId) + } + + keySet.sk[key.config.configId] = key + configs = append(configs, key.config.raw...) + } + + var b cryptobyte.Builder + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(configs) + }) + keySet.configs = b.BytesOrPanic() + + return keySet, nil +} + +// GetDecryptionContext is required by the ECHProvider interface. +func (keySet *EXP_ECHKeySet) GetDecryptionContext(rawHandle []byte, version uint16) (res ECHProviderResult) { + // Propagate retry configurations regardless of the result. The caller sends + // these to the clients only if it rejects. + res.RetryConfigs = keySet.configs + + // Ensure we know how to proceed, i.e., the caller has indicated a supported + // version of ECH. Currently only draft-ietf-tls-esni-13 is supported. + if version != extensionECH { + res.Status = ECHProviderAbort + res.Alert = uint8(alertInternalError) + res.Error = errors.New("version not supported") + return // Abort + } + + // Parse the handle. + s := cryptobyte.String(rawHandle) + handle := new(echContextHandle) + if !echReadContextHandle(&s, handle) || !s.Empty() { + // This is the result of a client-side error. However, aborting with + // "illegal_parameter" would stick out, so we reject instead. + res.Status = ECHProviderReject + res.RetryConfigs = keySet.configs + return // Reject + } + handle.raw = rawHandle + + // Look up the secret key for the configuration indicated by the client. + key, ok := keySet.sk[handle.configId] + if !ok { + res.Status = ECHProviderReject + res.RetryConfigs = keySet.configs + return // Reject + } + + // Ensure that support for the selected ciphersuite is indicated by the + // configuration. + suite := handle.suite + if !key.config.isPeerCipherSuiteSupported(suite) { + // This is the result of a client-side error. However, aborting with + // "illegal_parameter" would stick out, so we reject instead. + res.Status = ECHProviderReject + res.RetryConfigs = keySet.configs + return // Reject + } + + // Ensure the version indicated by the client matches the version supported + // by the configuration. + if version != key.config.version { + // This is the result of a client-side error. However, aborting with + // "illegal_parameter" would stick out, so we reject instead. + res.Status = ECHProviderReject + res.RetryConfigs = keySet.configs + return // Reject + } + + // Compute the decryption context. + opener, err := key.setupOpener(handle.enc, suite) + if err != nil { + if err.Error() == errHPKEInvalidPublicKey { + // This occurs if the KEM algorithm used to generate handle.enc is + // not the same as the KEM algorithm of the key. One way this can + // happen is if the client sent a GREASE ECH extension with a + // config_id that happens to match a known config, but which uses a + // different KEM algorithm. + res.Status = ECHProviderReject + res.RetryConfigs = keySet.configs + return // Reject + } + + res.Status = ECHProviderAbort + res.Alert = uint8(alertInternalError) + res.Error = err + return // Abort + } + + // Serialize the decryption context. + res.Context, err = opener.MarshalBinary() + if err != nil { + res.Status = ECHProviderAbort + res.Alert = uint8(alertInternalError) + res.Error = err + return // Abort + } + + res.Status = ECHProviderSuccess + return // Success +} + +// EXP_ECHKey represents an ECH key and its corresponding configuration. The +// encoding of an ECH Key has the format defined below (in TLS syntax). Note +// that the ECH standard does not specify this format. +// +// struct { +// opaque sk<0..2^16-1>; +// ECHConfig config<0..2^16>; // draft-ietf-tls-esni-13 +// } ECHKey; +type EXP_ECHKey struct { + sk kem.PrivateKey + config ECHConfig +} + +// EXP_UnmarshalECHKeys parses a sequence of ECH keys. +func EXP_UnmarshalECHKeys(raw []byte) ([]EXP_ECHKey, error) { + var ( + err error + key EXP_ECHKey + sk, config, contents cryptobyte.String + ) + s := cryptobyte.String(raw) + keys := make([]EXP_ECHKey, 0) +KeysLoop: + for !s.Empty() { + if !s.ReadUint16LengthPrefixed(&sk) || + !s.ReadUint16LengthPrefixed(&config) { + return nil, errors.New("error parsing key") + } + + key.config.raw = config + if !config.ReadUint16(&key.config.version) || + !config.ReadUint16LengthPrefixed(&contents) || + !config.Empty() { + return nil, errors.New("error parsing config") + } + + if key.config.version != extensionECH { + continue KeysLoop + } + if !readConfigContents(&contents, &key.config) { + return nil, errors.New("error parsing config contents") + } + + for _, suite := range key.config.suites { + if !hpke.KDF(suite.kdfId).IsValid() || + !hpke.AEAD(suite.aeadId).IsValid() { + continue KeysLoop + } + } + + kem := hpke.KEM(key.config.kemId) + if !kem.IsValid() { + continue KeysLoop + } + key.config.pk, err = kem.Scheme().UnmarshalBinaryPublicKey(key.config.rawPublicKey) + if err != nil { + return nil, fmt.Errorf("error parsing public key: %s", err) + } + key.sk, err = kem.Scheme().UnmarshalBinaryPrivateKey(sk) + if err != nil { + return nil, fmt.Errorf("error parsing secret key: %s", err) + } + + keys = append(keys, key) + } + return keys, nil +} + +// setupOpener computes the HPKE context used by the server in the ECH +// extension.i +func (key *EXP_ECHKey) setupOpener(enc []byte, suite hpkeSymmetricCipherSuite) (hpke.Opener, error) { + if key.config.raw == nil { + panic("raw config not set") + } + hpkeSuite, err := hpkeAssembleSuite( + key.config.kemId, + suite.kdfId, + suite.aeadId, + ) + if err != nil { + return nil, err + } + info := append(append([]byte(echHpkeInfoSetup), 0), key.config.raw...) + receiver, err := hpkeSuite.NewReceiver(key.sk, info) + if err != nil { + return nil, err + } + return receiver.Setup(enc) +} diff --git a/src/crypto/tls/ech_test.go b/src/crypto/tls/ech_test.go new file mode 100644 index 00000000000..9c950234824 --- /dev/null +++ b/src/crypto/tls/ech_test.go @@ -0,0 +1,952 @@ +// Copyright 2020 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "bytes" + "context" + "crypto/rand" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "testing" + "time" +) + +const ( + echTestBackendServerName = "example.com" + echTestClientFacingServerName = "cloudflare-esni.com" +) + +// The client's root CA certificate. +const echTestCertRootPEM = ` +-----BEGIN CERTIFICATE----- +MIICQTCCAeigAwIBAgIUYGSqOFcpxSleCzSCaveKL8lV4N0wCgYIKoZIzj0EAwIw +fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh +biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK +BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjAwOTIyMTcwNjAw +WhcNMjUwOTIxMTcwNjAwWjB/MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv +cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEfMB0GA1UEChMWSW50ZXJuZXQg +V2lkZ2V0cywgSW5jLjEMMAoGA1UECxMDV1dXMRQwEgYDVQQDEwtleGFtcGxlLmNv +bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNcFaBtPRgekRBKTBvuKdTy3raqs +4IizMLFup434MfQ5oH71mYpKndfBzxcZDTMYeocKlt1pVYwvZ3ZdpRsW6yWjQjBA +MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ2GJIW ++4m3/qpkage5tEvMg3NwPTAKBggqhkjOPQQDAgNHADBEAiB6J8UqRvdhLOiaDYqH +KG+TuveHOqlfQqQgXo4/hNKMiAIgV79TTPHu+Ymn/tcCy9LVWZcpgnCEjrZi0ou5 +et8BX9s= +-----END CERTIFICATE-----` + +// Certificate of the client-facing server. The server name is +// "cloudflare-esni.com". +const echTestCertClientFacingPEM = ` +-----BEGIN CERTIFICATE----- +MIICIjCCAcigAwIBAgIUCXySp2MadlDlcvFrSm4BtLUY70owCgYIKoZIzj0EAwIw +fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh +biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK +BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjAwOTIyMTcxMDAw +WhcNMjEwOTIyMTcxMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7nP/ +Txinb0JPE/xdjv5d3zrWJqXo7qwP67oVaMKJp5ausJ+0IZfiMWz8pa6T7pyyLrC5 +xvQNkfVkpP9/FxmNFaOBoDCBnTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI +KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFNN7Afv+ +CgPAxRr4QdZn8JFvQ9nTMB8GA1UdIwQYMBaAFDYYkhb7ibf+qmRqB7m0S8yDc3A9 +MB4GA1UdEQQXMBWCE2Nsb3VkZmxhcmUtZXNuaS5jb20wCgYIKoZIzj0EAwIDSAAw +RQIgZ4VlBtjTRludP/JwfaNQyGKZFWFqRsECvGPbk+ZHLZwCIQCTjuMAFrnjf/j5 +3RNw67l7+QQPrmurSO86l1IlDWNtcA== +-----END CERTIFICATE-----` + +// Signing key of the client-facing server. +var echTestKeyClientFacingPEM = testingKey(` +-----BEGIN TESTING KEY----- +MHcCAQEEIPpCcU8mu+h4xHAm18NJvn73Ko9fjH9QxDCpRt7kCIq9oAoGCCqGSM49 +AwEHoUQDQgAE7nP/Txinb0JPE/xdjv5d3zrWJqXo7qwP67oVaMKJp5ausJ+0IZfi +MWz8pa6T7pyyLrC5xvQNkfVkpP9/FxmNFQ== +-----END TESTING KEY-----`) + +// Certificate of the backend server. The server name is "example.com". +const echTestCertBackendPEM = ` +-----BEGIN CERTIFICATE----- +MIICGTCCAcCgAwIBAgIUQJSSdOZs9wag1Toanlt9lol0uegwCgYIKoZIzj0EAwIw +fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh +biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK +BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjAwOTIyMTcwOTAw +WhcNMjEwOTIyMTcwOTAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElq+q +E01Z87KIPHWdEAk0cWssHkRnS4aQCDfstoxDIWQ4rMwHvrWGFy/vytRwyjhHuX9n +tc5ArCpwbAmY+oW/46OBmDCBlTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI +KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPz9Ct9U +EIjBEcUpv/yxHYccUDo1MB8GA1UdIwQYMBaAFDYYkhb7ibf+qmRqB7m0S8yDc3A9 +MBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMAoGCCqGSM49BAMCA0cAMEQCICDBEzzE +DF529x9Z4BkOKVxNDicfWSjxrcMohevjeCWDAiBaxXS5+6I2fcred0JGMsJgo7ts +S8GYhuKE99mQA0/mug== +-----END CERTIFICATE-----` + +// Signing key of the backend server. +var echTestKeyBackendPEM = testingKey(` +-----BEGIN TESTING KEY----- +MHcCAQEEIIJsLXmfzw6FDlqyRRLhY6lVB6ws5ewjUQjnS4DXsQ60oAoGCCqGSM49 +AwEHoUQDQgAElq+qE01Z87KIPHWdEAk0cWssHkRnS4aQCDfstoxDIWQ4rMwHvrWG +Fy/vytRwyjhHuX9ntc5ArCpwbAmY+oW/4w== +-----END TESTING KEY-----`) + +// The ECH keys used by the client-facing server. +const echTestKeys = `-----BEGIN ECH KEYS----- +ACBpvnEYyFK6Ey4Pajbm6VaEsQp4bgRxoPVOs2wOiMuD+QBG/g0AQsMAIAAgCfU+ +VOBXjOut9a9m7wLhrZhHfM0GqE5BQLQK03DJf10ABAABAAElE2Nsb3VkZmxhcmUt +ZXNuaS5jb20AAAAguffuF8tjWUORwFbQ3+cDDqkMQuuMV7py7p1EJfM9S3IAZ/4N +AGMDABAAQQRhm1JRi7hkaK1HhcJq4ByJpK4fbsaD65xSqUuW0L53OYK3zEtz78pk +NhWC9NlkItWc2SYOTrGGHc5WhmJxKCTbAAQAAQABKhNjbG91ZGZsYXJlLWVzbmku +Y29tAAA= +-----END ECH KEYS-----` + +// A sequence of ECH keys with unsupported versions. +const echTestInvalidVersionKeys = `-----BEGIN ECH KEYS----- +ACDhS0q2cTU1Qzi6hPM4BQ/HLnbEUZyWdY2GbmS0DVkumgBIAfUARAAAIAAgi1Tu +jWJ236k1VAMeRnysKbDigxLpDs/AGdEowK8KiBkABAABAAEAAAATY2xvdWRmbGFy +ZS1lc25pLmNvbQAAACBmNj/zQe6OT/MR/MM39G6kwMJCJEXpdvTAkbdHErlgXwBI +AfUARAEAIAAgZ1Ru1uyGX6N9HYs5/pAE3KwUXRDBHD0Bdna8oP4uVEwABAABAAEA +AAATY2xvdWRmbGFyZS1lc25pLmNvbQAA +-----END ECH KEYS-----` + +// The sequence of ECH configurations corresponding to echTestKeys. +const echTestConfigs = `-----BEGIN ECH CONFIGS----- +AK3+DQBCwwAgACAJ9T5U4FeM6631r2bvAuGtmEd8zQaoTkFAtArTcMl/XQAEAAEA +ASUTY2xvdWRmbGFyZS1lc25pLmNvbQAA/g0AYwMAEABBBGGbUlGLuGRorUeFwmrg +HImkrh9uxoPrnFKpS5bQvnc5grfMS3PvymQ2FYL02WQi1ZzZJg5OsYYdzlaGYnEo +JNsABAABAAEqE2Nsb3VkZmxhcmUtZXNuaS5jb20AAA== +-----END ECH CONFIGS-----` + +// An invalid sequence of ECH configurations. +const echTestStaleConfigs = `-----BEGIN ECH CONFIGS----- +AK3+DQBCfgAgACA02DWuCoykTn5CZ/t+h3dXN2JLS5r5RlJPaOzH1UdnRgAEAAEA +ASUTY2xvdWRmbGFyZS1lc25pLmNvbQAA/g0AY8YAEABBBIpQ8lWXbmjAgaFg6TDf +si7tgaTV7fUMbrOZzCyKyIfv/cO872MYb9dvEH1Izu6LtKdGAlmKmu2pxtdpbsSW +CX0ABAABAAEqE2Nsb3VkZmxhcmUtZXNuaS5jb20AAA== +-----END ECH CONFIGS-----` + +// echTestProviderAlwaysAbort mocks an ECHProvider that, in response to any +// request, sets an alert and returns an error. The client-facing server must +// abort the handshake. +type echTestProviderAlwaysAbort struct{} + +// Required by the ECHProvider interface. +func (p echTestProviderAlwaysAbort) GetDecryptionContext(_ []byte, _ uint16) (res ECHProviderResult) { + res.Status = ECHProviderAbort + res.Alert = uint8(alertInternalError) + res.Error = errors.New("provider failed") + return // Abort +} + +// echTestProviderAlwaysReject simulates fallover of the ECH provider. In +// response to any query, it rejects without sending retry configurations., in response to any +type echTestProviderAlwaysReject struct{} + +// Required by the ECHProvider interface. +func (p echTestProviderAlwaysReject) GetDecryptionContext(_ []byte, _ uint16) (res ECHProviderResult) { + res.Status = ECHProviderReject + return // Reject without retry configs +} + +func echTestLoadConfigs(pemData string) []ECHConfig { + block, rest := pem.Decode([]byte(pemData)) + if block == nil || block.Type != "ECH CONFIGS" || len(rest) > 0 { + panic("pem decoding fails") + } + + configs, err := UnmarshalECHConfigs(block.Bytes) + if err != nil { + panic(err) + } + + return configs +} + +func echTestLoadKeySet(pemData string) *EXP_ECHKeySet { + block, rest := pem.Decode([]byte(pemData)) + if block == nil || block.Type != "ECH KEYS" || len(rest) > 0 { + panic("pem decoding fails") + } + + keys, err := EXP_UnmarshalECHKeys(block.Bytes) + if err != nil { + panic(err) + } + + keySet, err := EXP_NewECHKeySet(keys) + if err != nil { + panic(err) + } + + return keySet +} + +type echTestCase struct { + name string + + // expected outcomes + expectClientAbort bool // client aborts + expectServerAbort bool // server aborts + expectOffered bool // server indicates that ECH was offered + expectClientBypassed bool // server bypasses ECH + expectServerBypassed bool // server indicates that ECH was bypassed by client + expectAccepted bool // server indicates ECH acceptance + expectRejected bool // server indicates ECH rejection + expectGrease bool // server indicates dummy ECH was detected + expectBackendServerName bool // client verified backend server name + + // client config + clientEnabled bool // client enables ECH + clientStaleConfigs bool // client offers ECH with invalid config + clientNoConfigs bool // client sends dummy ECH if ECH enabled + clientInvalidTLSVersion bool // client does not offer 1.3 + + // server config + serverEnabled bool // server enables ECH + serverProviderAlwaysAbort bool // ECH provider always aborts + serverProviderAlwaysReject bool // ECH provider always rejects + serverProviderInvalidVersion bool // ECH provider uses configs with unsupported version + serverInvalidTLSVersion bool // server does not offer 1.3 + + // code path triggers + triggerHRR bool // server triggers HRR + triggerECHBypassAfterHRR bool // client bypasses after HRR + triggerECHBypassBeforeHRR bool // client bypasses before HRR + triggerIllegalHandleAfterHRR bool // client sends illegal ECH extension after HRR + triggerOuterExtMany bool // client sends many (not just one) outer extensions + triggerOuterExtIncorrectOrder bool // client sends malformed outer extensions + triggerOuterExtIllegal bool // client sends malformed outer extensions + triggerOuterExtNone bool // client does not incorporate outer extensions + triggerOuterIsInner bool // client sends "ech_is_inner" in ClientHelloOuter + triggerPayloadDecryptError bool // client sends inauthentic ciphertext +} + +// TODO(cjpatton): Add test cases for PSK interactions: +// - ECH bypassed, backend server consumes early data (baseline test config) +// - ECH accepted, backend server consumes early data +// - ECH rejected, client-facing server ignores early data intended for backend +var echTestCases = []echTestCase{ + { + // The client offers ECH and it is accepted by the server + name: "success / accepted", + expectOffered: true, + expectAccepted: true, + expectBackendServerName: true, + clientEnabled: true, + serverEnabled: true, + }, + { + // The client bypasses ECH, i.e., it neither offers ECH nor sends a + // dummy ECH extension. + name: "success / bypassed: not offered", + expectClientBypassed: true, + expectBackendServerName: true, + serverEnabled: true, + }, + { + // The client sends dummy (i.e., "GREASEd") ECH. The server sends retry + // configs in case the client meant to offer ECH. The client does not + // signal rejection, so the server concludes ECH was not offered. + name: "success / bypassed: grease", + expectGrease: true, + expectBackendServerName: true, + clientEnabled: true, + clientNoConfigs: true, + serverEnabled: true, + }, + { + // The client sends dummy ECH because it has enabled ECH but not TLS + // 1.3. The server sends retry configs in case the client meant to offer + // ECH. The client does not signal rejection, so the server concludes + // ECH was not offered. + name: "success / bypassed: client invalid version", + expectGrease: true, + expectBackendServerName: true, + clientInvalidTLSVersion: true, + clientEnabled: true, + serverEnabled: true, + }, + { + // The client offers ECH with an invalid (e.g., stale) config. The + // server sends retry configs. The client signals rejection by sending + // an "ech_required" alert. + name: "success / rejected: invalid config", + expectOffered: true, + expectRejected: true, + expectClientAbort: true, + expectServerAbort: true, + clientStaleConfigs: true, + clientEnabled: true, + serverEnabled: true, + }, + { + // The client offers ECH, but the payload is mangled in transit. The + // server sends retry configurations. The client signals rejection by + // sending an "ech_required" alert. + name: "success / rejected: inauthentic ciphertext", + expectOffered: true, + expectRejected: true, + expectClientAbort: true, + expectServerAbort: true, + clientEnabled: true, + serverEnabled: true, + triggerPayloadDecryptError: true, + }, + { + // The client offered ECH, but client-facing server terminates the + // connection without sending retry configurations. The client aborts + // with "ech_required" and regards ECH as securely disabled by the + // server. + name: "success / rejected: not supported by client-facing server", + expectServerBypassed: true, + expectClientAbort: true, + expectServerAbort: true, + clientEnabled: true, + }, + { + // The client offers ECH. The server ECH rejects without sending retry + // configurations, simulating fallover of the ECH provider. The client + // signals rejection. + name: "success / rejected: provider falls over", + expectServerAbort: true, + expectOffered: true, + expectServerBypassed: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + serverProviderAlwaysReject: true, + }, + { + // The client offers ECH. The server ECH rejects without sending retry + // configurations because the ECH provider returns configurations with + // unsupported versions only. + name: "success / rejected: provider invalid version", + expectServerAbort: true, + expectOffered: true, + expectServerBypassed: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + serverProviderInvalidVersion: true, + }, + { + // The client offers ECH. The server does not support TLS 1.3, so it + // ignores the extension and continues as usual. The client does not + // signal rejection because TLS 1.2 has been negotiated. + name: "success / bypassed: client-facing invalid version", + expectServerBypassed: true, + clientEnabled: true, + serverEnabled: true, + serverInvalidTLSVersion: true, + }, + { + // The client offers ECH. The ECH provider encounters an unrecoverable + // error, causing the server to abort. + name: "server abort: provider hard fails", + expectServerAbort: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + serverProviderAlwaysAbort: true, + }, + { + // The client offers ECH and it is accepted by the server. The HRR code + // path is triggered. + name: "hrr / accepted", + expectOffered: true, + expectAccepted: true, + expectBackendServerName: true, + triggerHRR: true, + clientEnabled: true, + serverEnabled: true, + }, + { + // The client sends a dummy ECH extension. The server sends retry + // configs in case the client meant to offer ECH. The client does not + // signal rejection, so the server concludes ECH was not offered. The + // HRR code path is triggered. + name: "hrr / bypassed: grease", + expectGrease: true, + expectBackendServerName: true, + clientEnabled: true, + clientNoConfigs: true, + serverEnabled: true, + triggerHRR: true, + }, + { + // The client offers ECH with an invalid (e.g., stale) config. The + // server sends retry configs. The client signals rejection. The HRR + // code path is triggered. + name: "hrr / rejected: invalid config", + expectOffered: true, + expectRejected: true, + expectClientAbort: true, + expectServerAbort: true, + clientEnabled: true, + clientStaleConfigs: true, + serverEnabled: true, + triggerHRR: true, + }, + { + // The HRR code path is triggered. The client offered ECH in the second + // CH but not the first. + name: "hrr / server abort: offer after bypass", + expectServerAbort: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + triggerHRR: true, + triggerECHBypassBeforeHRR: true, + }, + { + // The HRR code path is triggered. The client offered ECH in the first + // CH but not the second. + name: "hrr / server abort: bypass after offer", + expectOffered: true, + expectAccepted: true, + expectServerAbort: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + triggerHRR: true, + triggerECHBypassAfterHRR: true, + }, + { + // The HRR code path is triggered. In the second CH, the value of the + // context handle changes illegally. Specifically, the client sends a + // non-empty "config_id" and "enc". + name: "hrr / server abort: illegal handle", + expectOffered: true, + expectAccepted: true, + expectServerAbort: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + triggerHRR: true, + triggerIllegalHandleAfterHRR: true, + }, + { + // The client offers ECH and it is accepted by the server. The client + // incorporates many outer extensions instead of just one (the default + // behavior). + name: "outer extensions, many / accepted", + expectBackendServerName: true, + expectOffered: true, + expectAccepted: true, + clientEnabled: true, + serverEnabled: true, + triggerOuterExtMany: true, + }, + { + // The client offers ECH and it is accepted by the server. The client + // incorporates no outer extensions. + name: "outer extensions, none / accepted", + expectBackendServerName: true, + expectOffered: true, + expectAccepted: true, + clientEnabled: true, + serverEnabled: true, + triggerOuterExtNone: true, + }, + { + // The client offers ECH but does not implement the "outer_extension" + // mechanism correctly. Specifically, it sends them in the wrong order, + // causing the client and server to compute different transcripts. + name: "outer extensions, incorrect order / server abort: incorrect transcript", + expectOffered: true, + expectAccepted: true, + expectServerAbort: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + triggerOuterExtIncorrectOrder: true, + }, + { + // The client offers ECH but does not implement the "outer_extension" + // mechanism correctly. Specifically, the "outer extensions" contains + // the codepoint for the ECH extension itself. + name: "outer extensions, illegal: illegal parameter", + expectServerAbort: true, + expectClientAbort: true, + clientEnabled: true, + serverEnabled: true, + triggerOuterExtIllegal: true, + }, +} + +// Returns the base configurations for the client and client-facing server, +func echSetupConnTest() (clientConfig, serverConfig *Config) { + echTestNow := time.Date(2020, time.September, 23, 0, 0, 0, 0, time.UTC) + echTestConfig := &Config{ + Time: func() time.Time { + return echTestNow + }, + Rand: rand.Reader, + CipherSuites: allCipherSuites(), + InsecureSkipVerify: false, + } + + clientFacingCert, err := X509KeyPair([]byte(echTestCertClientFacingPEM), []byte(echTestKeyClientFacingPEM)) + if err != nil { + panic(err) + } + + backendCert, err := X509KeyPair([]byte(echTestCertBackendPEM), []byte(echTestKeyBackendPEM)) + if err != nil { + panic(err) + } + + block, rest := pem.Decode([]byte(echTestCertRootPEM)) + if block == nil || block.Type != "CERTIFICATE" || len(rest) > 0 { + panic("pem decoding fails") + } + + rootCert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + panic(err) + } + + clientConfig = echTestConfig.Clone() + clientConfig.ServerName = echTestBackendServerName + clientConfig.RootCAs = x509.NewCertPool() + clientConfig.RootCAs.AddCert(rootCert) + + serverConfig = echTestConfig.Clone() + serverConfig.GetCertificate = func(info *ClientHelloInfo) (*Certificate, error) { + if info.ServerName == echTestBackendServerName { + return &backendCert, nil + } else if info.ServerName == echTestClientFacingServerName { + return &clientFacingCert, nil + } + return nil, nil + } + return +} + +// echTestResult represents the ECH status and error status of a connection. +type echTestResult struct { + // Operational parameters + clientDone, serverDone bool + // Results + clientStatus CFEventECHClientStatus + serverStatus CFEventECHServerStatus + connState ConnectionState + err error +} + +func (r *echTestResult) eventHandler(event CFEvent) { + switch e := event.(type) { + case CFEventECHClientStatus: + if r.clientDone { + panic("expected at most one client ECH status event") + } + r.clientStatus = e + r.clientDone = true + case CFEventECHServerStatus: + if r.serverDone { + panic("expected at most one server ECH status event") + } + r.serverStatus = e + r.clientDone = true + } +} + +// echTestConn runs the handshake and returns the ECH and error status of the +// client and server. It also returns the server name verified by the client. +func echTestConn(t *testing.T, clientConfig, serverConfig *Config) (clientRes, serverRes echTestResult) { + testMessage := []byte("hey bud") + buf := make([]byte, len(testMessage)) + ln := newLocalListener(t) + defer ln.Close() + + serverCh := make(chan echTestResult, 1) + go func() { + var res echTestResult + serverConn, err := ln.Accept() + if err != nil { + res.err = err + serverCh <- res + return + } + + server := Server(serverConn, serverConfig) + defer func() { + server.Close() + serverCh <- res + }() + + sCtx := context.WithValue(context.Background(), CFEventHandlerContextKey{}, res.eventHandler) + if err := server.HandshakeContext(sCtx); err != nil { + res.err = err + return + } + + if _, err = server.Read(buf); err != nil { + res.err = err + } + + res.connState = server.ConnectionState() + }() + + cCtx := context.WithValue(context.Background(), CFEventHandlerContextKey{}, clientRes.eventHandler) + clientDialer := &Dialer{Config: clientConfig} + clientConn, err := clientDialer.DialContext(cCtx, "tcp", ln.Addr().String()) + if err != nil { + serverRes = <-serverCh + clientRes.err = err + return + } + client := clientConn.(*Conn) + defer client.Close() + + _, err = client.Write(testMessage) + if err != nil { + serverRes = <-serverCh + clientRes.err = err + return + } + + clientRes.connState = client.ConnectionState() + serverRes = <-serverCh + return +} + +func TestECHHandshake(t *testing.T) { + defer func() { + // Reset testing triggers after the test completes. + testingTriggerHRR = false + testingECHTriggerBypassAfterHRR = false + testingECHTriggerBypassBeforeHRR = false + testingECHIllegalHandleAfterHRR = false + testingECHOuterExtMany = false + testingECHOuterExtNone = false + testingECHOuterExtIncorrectOrder = false + testingECHOuterExtIllegal = false + testingECHTriggerPayloadDecryptError = false + }() + + staleConfigs := echTestLoadConfigs(echTestStaleConfigs) + configs := echTestLoadConfigs(echTestConfigs) + keySet := echTestLoadKeySet(echTestKeys) + invalidVersionKeySet := echTestLoadKeySet(echTestInvalidVersionKeys) + + clientConfig, serverConfig := echSetupConnTest() + for i, test := range echTestCases { + t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) { + // Configure the client. + n := 0 + if test.clientNoConfigs { + clientConfig.ClientECHConfigs = nil + n++ + } + if test.clientStaleConfigs { + clientConfig.ClientECHConfigs = staleConfigs + n++ + } + if n == 0 { + clientConfig.ClientECHConfigs = configs + } else if n > 1 { + panic("invalid test configuration") + } + + if test.clientEnabled { + clientConfig.ECHEnabled = true + } else { + clientConfig.ECHEnabled = false + } + + if test.clientInvalidTLSVersion { + clientConfig.MinVersion = VersionTLS10 + clientConfig.MaxVersion = VersionTLS12 + } else { + clientConfig.MinVersion = VersionTLS10 + clientConfig.MaxVersion = VersionTLS13 + } + + // Configure the client-facing server. + if test.serverEnabled { + serverConfig.ECHEnabled = true + } else { + serverConfig.ECHEnabled = false + } + + n = 0 + if test.serverProviderAlwaysAbort { + serverConfig.ServerECHProvider = &echTestProviderAlwaysAbort{} + n++ + } + if test.serverProviderAlwaysReject { + serverConfig.ServerECHProvider = &echTestProviderAlwaysReject{} + n++ + } + if test.serverProviderInvalidVersion { + serverConfig.ServerECHProvider = invalidVersionKeySet + n++ + } + if n == 0 { + serverConfig.ServerECHProvider = keySet + } else if n > 1 { + panic("invalid test configuration") + } + + if test.serverInvalidTLSVersion { + serverConfig.MinVersion = VersionTLS10 + serverConfig.MaxVersion = VersionTLS12 + } else { + serverConfig.MinVersion = VersionTLS10 + serverConfig.MaxVersion = VersionTLS13 + } + + testingTriggerHRR = false + if test.triggerHRR { + testingTriggerHRR = true + } + + testingECHTriggerBypassAfterHRR = false + if test.triggerECHBypassAfterHRR { + testingECHTriggerBypassAfterHRR = true + } + + testingECHTriggerBypassBeforeHRR = false + if test.triggerECHBypassBeforeHRR { + testingECHTriggerBypassBeforeHRR = true + } + + testingECHTriggerPayloadDecryptError = false + if test.triggerPayloadDecryptError { + testingECHTriggerPayloadDecryptError = true + } + + n = 0 + testingECHOuterExtMany = false + if test.triggerOuterExtMany { + testingECHOuterExtMany = true + n++ + } + testingECHOuterExtNone = false + if test.triggerOuterExtNone { + testingECHOuterExtNone = true + n++ + } + testingECHOuterExtIncorrectOrder = false + if test.triggerOuterExtIncorrectOrder { + testingECHOuterExtIncorrectOrder = true + n++ + } + testingECHOuterExtIllegal = false + if test.triggerOuterExtIllegal { + testingECHOuterExtIllegal = true + n++ + } + testingECHIllegalHandleAfterHRR = false + if test.triggerIllegalHandleAfterHRR { + testingECHIllegalHandleAfterHRR = true + n++ + } + if n > 1 { + panic("invalid test configuration") + } + + t.Logf("%s", test.name) + + // Run the handshake. + client, server := echTestConn(t, clientConfig, serverConfig) + if !test.expectClientAbort && client.err != nil { + t.Error("client aborts; want success") + } + + if !test.expectServerAbort && server.err != nil { + t.Error("server aborts; want success") + } + + if test.expectClientAbort && client.err == nil { + t.Error("client succeeds; want abort") + } else if client.err != nil { + t.Logf("client err: %s", client.err) + } + + if test.expectServerAbort && server.err == nil { + t.Errorf("server succeeds; want abort") + } else if server.err != nil { + t.Logf("server err: %s", server.err) + } + + if got := server.clientStatus.Offered(); got != test.expectOffered { + t.Errorf("got offered=%v; want %v", got, test.expectOffered) + } + + if got := server.clientStatus.Greased(); got != test.expectGrease { + t.Errorf("got grease=%v; want %v", got, test.expectGrease) + } + + if got := server.clientStatus.Bypassed(); got != test.expectClientBypassed && server.err == nil { + t.Errorf("got clientBypassed=%v; want %v", got, test.expectClientBypassed) + } + + if got := server.serverStatus.Bypassed(); got != test.expectServerBypassed && server.err == nil { + t.Errorf("got serverBypassed=%v; want %v", got, test.expectServerBypassed) + } + + if got := server.serverStatus.Accepted(); got != test.expectAccepted { + t.Errorf("got accepted=%v; want %v", got, test.expectAccepted) + } + + if got := server.serverStatus.Rejected(); got != test.expectRejected { + t.Errorf("got rejected=%v; want %v", got, test.expectRejected) + } + + if client.err != nil { + return + } + + if name := client.connState.ServerName; test.expectBackendServerName != (name == echTestBackendServerName) { + t.Errorf("got backend server name=%v; want %v", name == echTestBackendServerName, test.expectBackendServerName) + } + + if client.clientStatus.Greased() != server.clientStatus.Greased() || + client.clientStatus.Bypassed() != server.clientStatus.Bypassed() || + client.serverStatus.Bypassed() != server.serverStatus.Bypassed() || + client.serverStatus.Accepted() != server.serverStatus.Accepted() || + client.serverStatus.Rejected() != server.serverStatus.Rejected() { + t.Error("client and server disagree on ech usage") + t.Errorf("client=%+v", client) + t.Errorf("server=%+v", server) + } + + if accepted := client.connState.ECHAccepted; accepted != client.serverStatus.Accepted() { + t.Errorf("client got ECHAccepted=%v; want %v", accepted, client.serverStatus.Accepted()) + } + + if accepted := server.connState.ECHAccepted; accepted != server.serverStatus.Accepted() { + t.Errorf("server got ECHAccepted=%v; want %v", accepted, server.serverStatus.Accepted()) + } + }) + } +} + +func TestUnmarshalConfigs(t *testing.T) { + block, rest := pem.Decode([]byte(echTestConfigs)) + if block == nil || block.Type != "ECH CONFIGS" || len(rest) > 0 { + t.Fatal("pem decoding fails") + } + + configs, err := UnmarshalECHConfigs(block.Bytes) + if err != nil { + t.Fatal(err) + } + + if len(configs) != 2 { + t.Errorf("wrong number of configs: got %d; want %d", len(configs), 2) + } + + for i, config := range configs { + if len(config.suites) != 1 { + t.Errorf("wrong number of cipher suites in config #%d: got %d; want %d", i, len(config.suites), 1) + } + } + + for _, config := range configs { + if len(config.raw) == 0 { + t.Error("raw config not set") + } + } +} + +func TestUnmarshalKeys(t *testing.T) { + block, rest := pem.Decode([]byte(echTestKeys)) + if block == nil || block.Type != "ECH KEYS" || len(rest) > 0 { + t.Fatal("pem decoding fails") + } + + keys, err := EXP_UnmarshalECHKeys(block.Bytes) + if err != nil { + t.Fatal(err) + } + + if len(keys) != 2 { + t.Errorf("wrong number of configs: got %d; want %d", len(keys), 2) + } + + for i, key := range keys { + if len(key.config.raw) == 0 { + t.Error("raw config not set") + } + + if len(key.config.suites) != 1 { + t.Errorf("wrong number of cipher suites in config #%d: got %d; want %d", i, len(key.config.suites), 1) + } + } +} + +func testECHProvider(t *testing.T, p ECHProvider, handle []byte, version uint16, want ECHProviderResult) { + got := p.GetDecryptionContext(handle, version) + if got.Status != want.Status { + t.Errorf("incorrect status: got %+v; want %+v", got.Status, want.Status) + } + if got.Alert != want.Alert { + t.Errorf("incorrect alert: got %+v; want %+v", got.Alert, want.Alert) + } + if got.Error != want.Error { + t.Errorf("incorrect error: got %+v; want %+v", got.Error, want.Error) + } + if !bytes.Equal(got.RetryConfigs, want.RetryConfigs) { + t.Errorf("incorrect retry configs: got %+v; want %+v", got.RetryConfigs, want.RetryConfigs) + } + if !bytes.Equal(got.Context, want.Context) { + t.Errorf("incorrect context: got %+v; want %+v", got.Context, want.Context) + } +} + +func TestECHProvider(t *testing.T) { + p := echTestLoadKeySet(echTestKeys) + t.Run("ok", func(t *testing.T) { + handle := []byte{ + 0, 1, 0, 1, 195, 0, 32, 49, 215, 32, 55, 8, 132, 98, 118, 166, 113, + 184, 40, 196, 151, 103, 20, 221, 148, 22, 72, 112, 152, 18, 20, 107, + 15, 109, 178, 15, 98, 104, 66, + } + context := []byte{ + 1, 0, 32, 0, 1, 0, 1, 32, 111, 237, 227, 138, 43, 202, 113, 109, + 127, 174, 36, 48, 232, 103, 97, 52, 76, 112, 136, 36, 220, 91, 12, + 21, 63, 194, 77, 110, 112, 25, 241, 135, 16, 214, 55, 95, 236, 101, + 6, 49, 56, 18, 215, 166, 137, 136, 225, 58, 54, 12, 229, 100, 254, + 43, 179, 2, 188, 179, 6, 166, 138, 138, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + } + testECHProvider(t, p, handle, extensionECH, ECHProviderResult{ + Status: ECHProviderSuccess, + RetryConfigs: p.configs, + Context: context, + }) + }) + t.Run("invalid config id", func(t *testing.T) { + handle := []byte{ + 0, 1, 0, 1, 255, 202, 62, 220, 1, 243, 58, 0, 32, 40, 52, 167, 167, + 21, 125, 151, 32, 250, 255, 1, 125, 206, 103, 62, 96, 189, 112, 126, + 48, 221, 41, 198, 146, 100, 149, 29, 133, 103, 87, 87, 78, + } + testECHProvider(t, p, handle, extensionECH, ECHProviderResult{ + Status: ECHProviderReject, + RetryConfigs: p.configs, + }) + }) + t.Run("invalid cipher suite", func(t *testing.T) { + handle := []byte{ + 99, 99, 0, 1, 8, 202, 62, 220, 1, 243, 58, 247, 102, 0, 32, 40, 52, + 167, 167, 21, 125, 151, 32, 250, 255, 1, 125, 206, 103, 62, 96, 189, + 112, 126, 48, 221, 41, 198, 146, 100, 149, 29, 133, 103, 87, 87, 78, + } + testECHProvider(t, p, handle, extensionECH, ECHProviderResult{ + Status: ECHProviderReject, + RetryConfigs: p.configs, + }) + }) + t.Run("malformed", func(t *testing.T) { + handle := []byte{ + 0, 1, 0, 1, 8, 202, 62, 220, 1, + } + testECHProvider(t, p, handle, extensionECH, ECHProviderResult{ + Status: ECHProviderReject, + RetryConfigs: p.configs, + }) + }) +} diff --git a/src/crypto/tls/generate_cert.go b/src/crypto/tls/generate_cert.go index cd4bfc513f0..360ce8fa80a 100644 --- a/src/crypto/tls/generate_cert.go +++ b/src/crypto/tls/generate_cert.go @@ -25,6 +25,9 @@ import ( "os" "strings" "time" + + circlSign "github.com/cloudflare/circl/sign" + circlSchemes "github.com/cloudflare/circl/sign/schemes" ) var ( @@ -32,9 +35,11 @@ var ( validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") + allowDC = flag.Bool("allowDC", false, "whether this cert can be used with Delegated Credentials") rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set") ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521") ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key") + circlKey = flag.String("circl", "", "Generate a key supported by Circl") ) func publicKey(priv any) any { @@ -45,6 +50,8 @@ func publicKey(priv any) any { return &k.PublicKey case ed25519.PrivateKey: return k.Public().(ed25519.PublicKey) + case circlSign.PrivateKey: + return k.Public() default: return nil } @@ -63,6 +70,12 @@ func main() { case "": if *ed25519Key { _, priv, err = ed25519.GenerateKey(rand.Reader) + } else if *circlKey != "" { + scheme := circlSchemes.ByName(*circlKey) + if scheme == nil { + log.Fatalf("No such Circl scheme: %s", *circlKey) + } + _, priv, err = scheme.GenerateKey() } else { priv, err = rsa.GenerateKey(rand.Reader, *rsaBits) } @@ -132,10 +145,19 @@ func main() { } if *isCA { + if *allowDC { + log.Fatal("Failed to create certificate: ca is not allowed with the dc flag") + } + template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } + if *allowDC { + template.AllowDC = true + template.KeyUsage |= x509.KeyUsageDigitalSignature + } + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) if err != nil { log.Fatalf("Failed to create certificate: %v", err) diff --git a/src/crypto/tls/generate_delegated_credential.go b/src/crypto/tls/generate_delegated_credential.go new file mode 100644 index 00000000000..1b72b414d53 --- /dev/null +++ b/src/crypto/tls/generate_delegated_credential.go @@ -0,0 +1,126 @@ +// Copyright 2022 Cloudflare, Inc. 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 ignore + +// Generate a delegated credential with the given signature scheme, signed with +// the given x.509 key pair. Outputs to 'dc.cred' and 'dckey.pem' and will +// overwrite existing files. + +// Example usage: +// generate_delegated_credential -cert-path cert.pem -key-path key.pem -signature-scheme Ed25519 -duration 24h + +package main + +import ( + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "encoding/pem" + "errors" + "flag" + "fmt" + "log" + "os" + "path/filepath" + "time" + + circlSign "github.com/cloudflare/circl/sign" +) + +var ( + validFor = flag.Duration("duration", 5*24*time.Hour, "Duration that credential is valid for") + signatureScheme = flag.String("signature-scheme", "", "The signature scheme used by the DC") + certPath = flag.String("cert-path", "./cert.pem", "Path to signing cert") + keyPath = flag.String("key-path", "./key.pem", "Path to signing key") + isClient = flag.Bool("client-dc", false, "Create a client Delegated Credential") + outPath = flag.String("out-path", "./", "Path to output directory") +) + +var SigStringMap = map[string]tls.SignatureScheme{ + // ECDSA algorithms. Only constrained to a specific curve in TLS 1.3. + "ECDSAWithP256AndSHA256": tls.ECDSAWithP256AndSHA256, + "ECDSAWithP384AndSHA384": tls.ECDSAWithP384AndSHA384, + "ECDSAWithP521AndSHA512": tls.ECDSAWithP521AndSHA512, + + // EdDSA algorithms. + "Ed25519": tls.Ed25519, +} + +func main() { + flag.Parse() + sa := SigStringMap[*signatureScheme] + + cert, err := tls.LoadX509KeyPair(*certPath, *keyPath) + if err != nil { + log.Fatalf("Failed to load certificate and key: %v", err) + } + cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + log.Fatalf("Failed to parse leaf certificate: %v", err) + } + + validTime := time.Since(cert.Leaf.NotBefore) + *validFor + dc, priv, err := tls.NewDelegatedCredential(&cert, sa, validTime, *isClient) + if err != nil { + log.Fatalf("Failed to create a DC: %v\n", err) + } + dcBytes, err := dc.Marshal() + if err != nil { + log.Fatalf("Failed to marshal DC: %v\n", err) + } + + DCOut, err := os.Create(filepath.Join(*outPath, "dc.cred")) + if err != nil { + log.Fatalf("Failed to open dc.cred for writing: %v", err) + } + + DCOut.Write(dcBytes) + if err := DCOut.Close(); err != nil { + log.Fatalf("Error closing dc.cred: %v", err) + } + log.Print("wrote dc.cred\n") + + derBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + log.Fatalf("Failed to marshal DC private key: %v\n", err) + } + + DCKeyOut, err := os.Create(filepath.Join(*outPath, "dckey.pem")) + if err != nil { + log.Fatalf("Failed to open dckey.pem for writing: %v", err) + } + + if err := pem.Encode(DCKeyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: derBytes}); err != nil { + log.Fatalf("Failed to write data to dckey.pem: %v\n", err) + } + if err := DCKeyOut.Close(); err != nil { + log.Fatalf("Error closing dckey.pem: %v\n", err) + } + log.Print("wrote dckey.pem\n") + + fmt.Println("Success") +} + +// Copied from tls.go, because it's private. +func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { + if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { + return key, nil + } + if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { + switch key := key.(type) { + case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey, circlSign.PrivateKey: + return key, nil + default: + return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping") + } + } + if key, err := x509.ParseECPrivateKey(der); err == nil { + return key, nil + } + + return nil, errors.New("tls: failed to parse private key") +} diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 08a2d47974c..6755ce04b4a 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -8,7 +8,6 @@ import ( "bytes" "context" "crypto" - "crypto/ecdh" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" @@ -23,6 +22,8 @@ import ( "strconv" "strings" "time" + + circlSign "github.com/cloudflare/circl/sign" ) type clientHandshakeState struct { @@ -39,7 +40,7 @@ type clientHandshakeState struct { var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme -func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { +func (c *Conn) makeClientHello(minVersion uint16) (*clientHelloMsg, clientKeySharePrivate, error) { config := c.config if len(config.ServerName) == 0 && !config.InsecureSkipVerify { return nil, nil, errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") @@ -57,7 +58,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { return nil, nil, errors.New("tls: NextProtos values too large") } - supportedVersions := config.supportedVersions(roleClient) + supportedVersions := config.supportedVersionsFromMin(roleClient, minVersion) if len(supportedVersions) == 0 { return nil, nil, errors.New("tls: no supported versions satisfy MinVersion and MaxVersion") } @@ -127,13 +128,13 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { } if hello.vers >= VersionTLS12 { - hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + hello.supportedSignatureAlgorithms = config.supportedSignatureAlgorithms() } if testingOnlyForceClientHelloSignatureAlgorithms != nil { hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms } - var key *ecdh.PrivateKey + secret := make(clientKeySharePrivate) if hello.supportedVersions[0] == VersionTLS13 { // Reset the list of ciphers when the client only supports TLS 1.3. if len(hello.supportedVersions) == 1 { @@ -145,15 +146,78 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) } - curveID := config.curvePreferences()[0] - if _, ok := curveForCurveID(curveID); !ok { - return nil, nil, errors.New("tls: CurvePreferences includes unsupported curve") + curveIDs := []CurveID{config.curvePreferences()[0]} + + if config.ClientCurveGuess != nil { + curveIDs = config.ClientCurveGuess } - key, err = generateECDHEKey(config.rand(), curveID) - if err != nil { - return nil, nil, err + + hello.keyShares = make([]keyShare, 0, len(curveIDs)) + + // Check whether ClientCurveGuess is a subsequence of CurvePreferences + // as is required by RFC8446 §4.2.8 + offset := 0 + curvePreferences := config.curvePreferences() + found := 0 + CurveGuessCheck: + for _, curveID := range curveIDs { + for { + if offset == len(curvePreferences) { + break CurveGuessCheck + } + + if curvePreferences[offset] == curveID { + found++ + break + } + + offset++ + } + } + if found != len(curveIDs) { + return nil, nil, errors.New("tls: ClientCurveGuess not a subsequence of CurvePreferences") + } + + for _, curveID := range curveIDs { + var ( + singleSecret interface{} + singleShare []byte + ) + + if _, ok := secret[curveID]; ok { + return nil, nil, errors.New("tls: ClientCurveGuess contains duplicate") + } + + if scheme := curveIdToCirclScheme(curveID); scheme != nil { + pk, sk, err := generateKemKeyPair(scheme, curveID, config.rand()) + if err != nil { + return nil, nil, fmt.Errorf("generateKemKeyPair %s: %w", + scheme.Name(), err) + } + packedPk, err := pk.MarshalBinary() + if err != nil { + return nil, nil, fmt.Errorf("pack circl public key %s: %w", + scheme.Name(), err) + } + singleShare = packedPk + singleSecret = sk + } else { + if _, ok := curveForCurveID(curveID); !ok { + return nil, nil, errors.New("tls: CurvePreferences includes unsupported curve") + } + key, err := generateECDHEKey(config.rand(), curveID) + if err != nil { + return nil, nil, err + } + singleShare = key.PublicKey().Bytes() + singleSecret = key + } + hello.keyShares = append(hello.keyShares, keyShare{group: curveID, data: singleShare}) + secret[curveID] = singleSecret } - hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} + + hello.delegatedCredentialSupported = config.SupportDelegatedCredential + hello.supportedSignatureAlgorithmsDC = supportedSignatureAlgorithmsDC } if c.quic != nil { @@ -167,7 +231,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { hello.quicTransportParameters = p } - return hello, key, nil + return hello, secret, nil } func (c *Conn) clientHandshake(ctx context.Context) (err error) { @@ -175,17 +239,36 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { c.config = defaultConfig() } + hsTimings := createTLS13ClientHandshakeTimingInfo(c.config.Time) + // This may be a renegotiation handshake, in which case some fields // need to be reset. c.didResume = false - hello, ecdheKey, err := c.makeClientHello() + // Determine the minimum required version for this handshake. + minVersion := c.config.MinVersion + if c.config.echCanOffer() { + // If the ECH extension will be offered in this handshake, then the + // ClientHelloInner must not offer TLS 1.2 or below. + minVersion = VersionTLS13 + } + + helloBase, ecdheKey, err := c.makeClientHello(minVersion) if err != nil { return err } - c.serverName = hello.serverName - session, earlySecret, binderKey, err := c.loadSession(hello) + hello, helloInner, err := c.echOfferOrGrease(helloBase) + if err != nil { + return err + } + + helloResumed := hello + if c.ech.offered { + helloResumed = helloInner + } + + session, earlySecret, binderKey, err := c.loadSession(helloResumed) if err != nil { return err } @@ -209,6 +292,8 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { return err } + hsTimings.WriteClientHello = hsTimings.elapsedTime() + if hello.earlyData { suite := cipherSuiteTLS13ByID(session.cipherSuite) transcript := suite.hash.New() @@ -249,20 +334,23 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { if c.vers == VersionTLS13 { hs := &clientHandshakeStateTLS13{ - c: c, - ctx: ctx, - serverHello: serverHello, - hello: hello, - ecdheKey: ecdheKey, - session: session, - earlySecret: earlySecret, - binderKey: binderKey, + c: c, + ctx: ctx, + serverHello: serverHello, + hello: hello, + helloInner: helloInner, + keySharePrivate: ecdheKey, + session: session, + earlySecret: earlySecret, + binderKey: binderKey, + hsTimings: hsTimings, } // In TLS 1.3, session tickets are delivered after the handshake. return hs.handshake() } + c.serverName = hello.serverName hs := &clientHandshakeState{ c: c, ctx: ctx, @@ -280,7 +368,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { func (c *Conn) loadSession(hello *clientHelloMsg) ( session *SessionState, earlySecret, binderKey []byte, err error) { - if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { + if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil || c.config.ECHEnabled { return nil, nil, nil, nil } @@ -603,6 +691,16 @@ func (hs *clientHandshakeState) doFullHandshake() error { return err } + if eccKex, ok := keyAgreement.(*ecdheKeyAgreement); ok { + curveId, ok := curveIDForCurve(eccKex.key.Curve()) + if !ok { + panic("internal error: unknown curve") + } + c.handleCFEvent(CFEventTLSNegotiatedNamedKEX{ + KEX: curveId, + }) + } + msg, err = c.readHandshake(&hs.finishedHash) if err != nil { return err @@ -983,10 +1081,14 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { } if !c.config.InsecureSkipVerify { + dnsName := c.config.ServerName + if c.ech.offered && !c.ech.accepted { + dnsName = c.serverName + } opts := x509.VerifyOptions{ Roots: c.config.RootCAs, CurrentTime: c.config.time(), - DNSName: c.config.ServerName, + DNSName: dnsName, Intermediates: x509.NewCertPool(), } @@ -1002,7 +1104,7 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { } switch certs[0].PublicKey.(type) { - case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey: + case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey, circlSign.PublicKey: break default: c.sendAlert(alertUnsupportedCertificate) @@ -1036,6 +1138,9 @@ func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *ce AcceptableCAs: certReq.certificateAuthorities, Version: vers, ctx: ctx, + + SupportsDelegatedCredential: false, // Not supported in TLS <= 1.2 + SignatureSchemesDC: nil, // Not supported in TLS <= 1.2 } var rsaAvail, ecAvail bool diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 2f59f6888c5..04a272c4a91 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -11,29 +11,79 @@ import ( "crypto/ecdh" "crypto/hmac" "crypto/rsa" + "crypto/subtle" "errors" + "fmt" "hash" "time" ) type clientHandshakeStateTLS13 struct { - c *Conn - ctx context.Context - serverHello *serverHelloMsg - hello *clientHelloMsg - ecdheKey *ecdh.PrivateKey - - session *SessionState - earlySecret []byte - binderKey []byte - - certReq *certificateRequestMsgTLS13 - usingPSK bool - sentDummyCCS bool - suite *cipherSuiteTLS13 - transcript hash.Hash - masterSecret []byte - trafficSecret []byte // client_application_traffic_secret_0 + c *Conn + ctx context.Context + serverHello *serverHelloMsg + hello *clientHelloMsg + helloInner *clientHelloMsg + keySharePrivate clientKeySharePrivate + + session *SessionState + earlySecret []byte + binderKey []byte + selectedGroup CurveID + + certReq *certificateRequestMsgTLS13 + usingPSK bool + sentDummyCCS bool + suite *cipherSuiteTLS13 + transcript hash.Hash + transcriptInner hash.Hash + masterSecret []byte + trafficSecret []byte // client_application_traffic_secret_0 + + hsTimings CFEventTLS13ClientHandshakeTimingInfo +} + +// processDelegatedCredentialFromServer unmarshals the DelegatedCredential +// offered by the server (if present) and validates it using the peer's +// certificate. +func (hs *clientHandshakeStateTLS13) processDelegatedCredentialFromServer(rawDC []byte, certVerifyMsg *certificateVerifyMsg) error { + c := hs.c + + var dc *DelegatedCredential + var err error + if rawDC != nil { + // Assert that support for the DC extension was indicated by the client. + if !hs.hello.delegatedCredentialSupported { + c.sendAlert(alertUnexpectedMessage) + return errors.New("tls: got Delegated Credential extension without indication") + } + + dc, err = UnmarshalDelegatedCredential(rawDC) + if err != nil { + c.sendAlert(alertDecodeError) + return fmt.Errorf("tls: Delegated Credential: %s", err) + } + + if !isSupportedSignatureAlgorithm(dc.cred.expCertVerfAlgo, supportedSignatureAlgorithmsDC) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: Delegated Credential used with invalid signature algorithm") + } + if !isSupportedSignatureAlgorithm(dc.algorithm, c.config.supportedSignatureAlgorithms()) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: Delegated Credential signed with unsupported signature algorithm") + } + } + + if dc != nil { + if !dc.Validate(c.peerCertificates[0], false, c.config.time(), certVerifyMsg) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: invalid Delegated Credential") + } + } + + c.verifiedDC = dc + + return nil } // handshake requires hs.c, hs.hello, hs.serverHello, hs.ecdheKey, and, @@ -53,7 +103,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error { } // Consistency check on the presence of a keyShare and its parameters. - if hs.ecdheKey == nil || len(hs.hello.keyShares) != 1 { + if hs.keySharePrivate == nil { return c.sendAlert(alertInternalError) } @@ -67,6 +117,18 @@ func (hs *clientHandshakeStateTLS13) handshake() error { return err } + // When offering ECH, we don't know whether ECH was accepted or rejected + // until we get the server's response. Compute the transcript of both the + // inner and outer handshake until we know. + if c.ech.offered { + hs.transcriptInner = hs.suite.hash.New() + helloInnerMarshalled, err := hs.helloInner.marshal() + if err != nil { + return fmt.Errorf("tls: ech: helloInner.marshal(): %w", err) + } + hs.transcriptInner.Write(helloInnerMarshalled) + } + if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { if err := hs.sendDummyChangeCipherSpec(); err != nil { return err @@ -76,10 +138,45 @@ func (hs *clientHandshakeStateTLS13) handshake() error { } } + // Check for ECH acceptance confirmation. + if c.ech.offered { + echAcceptConfTranscript := cloneHash(hs.transcriptInner, hs.suite.hash) + if echAcceptConfTranscript == nil { + c.sendAlert(alertInternalError) + return errors.New("tls: internal error: failed to clone hash") + } + + sh, err := hs.serverHello.marshal() + if err != nil { + return fmt.Errorf("tls: ech: hs.serverHello.marshal(): %w", err) + } + echAcceptConfTranscript.Write(sh[:30]) + echAcceptConfTranscript.Write(zeros[:8]) + echAcceptConfTranscript.Write(sh[38:]) + echAcceptConf := hs.suite.expandLabel( + hs.suite.extract(hs.helloInner.random, nil), + echAcceptConfLabel, + echAcceptConfTranscript.Sum(nil), + 8) + + if subtle.ConstantTimeCompare(hs.serverHello.random[24:], echAcceptConf) == 1 { + c.ech.accepted = true + hs.hello = hs.helloInner + hs.transcript = hs.transcriptInner + } + } + if err := transcriptMsg(hs.serverHello, hs.transcript); err != nil { return err } + // Resolve the server name now that ECH acceptance has been determined. + // + // NOTE(cjpatton): Currently the client sends the same ALPN extension in the + // ClientHelloInner and ClientHelloOuter. If that changes, then we'll need + // to resolve ALPN here as well. + c.serverName = hs.hello.serverName + c.buffering = true if err := hs.processServerHello(); err != nil { return err @@ -105,10 +202,14 @@ func (hs *clientHandshakeStateTLS13) handshake() error { if err := hs.sendClientFinished(); err != nil { return err } + if err := hs.abortIfRequired(); err != nil { + return err + } if _, err := c.flush(); err != nil { return err } + c.handleCFEvent(hs.hsTimings) c.isHandshakeComplete.Store(true) return nil @@ -189,6 +290,8 @@ func (hs *clientHandshakeStateTLS13) sendDummyChangeCipherSpec() error { func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { c := hs.c + c.handleCFEvent(CFEventTLS13HRR{}) + // The first ClientHello gets double-hashed into the transcript upon a // HelloRetryRequest. (The idea is that the server might offload transcript // storage to the client in the cookie.) See RFC 8446, Section 4.4.1. @@ -200,6 +303,50 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { return err } + // Determine which ClientHello message was consumed by the server. If ECH + // was offered, this may be the ClientHelloInner or ClientHelloOuter. + hello := hs.hello + isInner := false + if c.ech.offered { + chHash = hs.transcriptInner.Sum(nil) + hs.transcriptInner.Reset() + hs.transcriptInner.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) + hs.transcriptInner.Write(chHash) + + // Check for ECH acceptance confirmation. + serverHelloMarshalled, err := hs.serverHello.marshal() + if err != nil { + return fmt.Errorf("tls: serverHello.marshal(): %w", err) + } + if hs.serverHello.ech != nil { + if len(hs.serverHello.ech) != 8 { + c.sendAlert(alertDecodeError) + return errors.New("tls: ech: hrr: malformed acceptance signal") + } + + echAcceptConfHRRTranscript := cloneHash(hs.transcriptInner, hs.suite.hash) + if echAcceptConfHRRTranscript == nil { + c.sendAlert(alertInternalError) + return errors.New("tls: internal error: failed to clone hash") + } + + echAcceptConfHRR := echEncodeAcceptConfHelloRetryRequest(serverHelloMarshalled) + echAcceptConfHRRTranscript.Write(echAcceptConfHRR) + echAcceptConfHRRSignal := hs.suite.expandLabel( + hs.suite.extract(hs.helloInner.random, nil), + echAcceptConfHRRLabel, + echAcceptConfHRRTranscript.Sum(nil), + 8) + + if subtle.ConstantTimeCompare(hs.serverHello.ech, echAcceptConfHRRSignal) == 1 { + hello = hs.helloInner + isInner = true + } + } + + hs.transcriptInner.Write(serverHelloMarshalled) + } + // The only HelloRetryRequest extensions we support are key_share and // cookie, and clients must abort the handshake if the HRR would not result // in any change in the ClientHello. @@ -209,7 +356,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { } if hs.serverHello.cookie != nil { - hs.hello.cookie = hs.serverHello.cookie + hello.cookie = hs.serverHello.cookie } if hs.serverHello.serverShare.group != 0 { @@ -222,7 +369,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { // share for it this time. if curveID := hs.serverHello.selectedGroup; curveID != 0 { curveOK := false - for _, id := range hs.hello.supportedCurves { + for _, id := range hello.supportedCurves { if id == curveID { curveOK = true break @@ -232,25 +379,42 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: server selected unsupported group") } - if sentID, _ := curveIDForCurve(hs.ecdheKey.Curve()); sentID == curveID { + if singleClientKeySharePrivateFor(hs.keySharePrivate, curveID) != nil { c.sendAlert(alertIllegalParameter) return errors.New("tls: server sent an unnecessary HelloRetryRequest key_share") } - if _, ok := curveForCurveID(curveID); !ok { - c.sendAlert(alertInternalError) - return errors.New("tls: CurvePreferences includes unsupported curve") - } - key, err := generateECDHEKey(c.config.rand(), curveID) - if err != nil { - c.sendAlert(alertInternalError) - return err + if scheme := curveIdToCirclScheme(curveID); scheme != nil { + pk, sk, err := generateKemKeyPair(scheme, curveID, c.config.rand()) + if err != nil { + c.sendAlert(alertInternalError) + return fmt.Errorf("HRR generateKemKeyPair %s: %w", + scheme.Name(), err) + } + packedPk, err := pk.MarshalBinary() + if err != nil { + c.sendAlert(alertInternalError) + return fmt.Errorf("HRR pack circl public key %s: %w", + scheme.Name(), err) + } + hs.keySharePrivate = clientKeySharePrivate{curveID: sk} + hello.keyShares = []keyShare{{group: curveID, data: packedPk}} + } else { + if _, ok := curveForCurveID(curveID); !ok { + c.sendAlert(alertInternalError) + return errors.New("tls: CurvePreferences includes unsupported curve") + } + key, err := generateECDHEKey(c.config.rand(), curveID) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + hs.keySharePrivate = clientKeySharePrivate{curveID: key} + hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} } - hs.ecdheKey = key - hs.hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} } - hs.hello.raw = nil - if len(hs.hello.pskIdentities) > 0 { + hello.raw = nil + if len(hello.pskIdentities) > 0 { pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite) if pskSuite == nil { return c.sendAlert(alertInternalError) @@ -258,7 +422,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { if pskSuite.hash == hs.suite.hash { // Update binders and obfuscated_ticket_age. ticketAge := c.config.time().Sub(time.Unix(int64(hs.session.createdAt), 0)) - hs.hello.pskIdentities[0].obfuscatedTicketAge = uint32(ticketAge/time.Millisecond) + hs.session.ageAdd + hello.pskIdentities[0].obfuscatedTicketAge = uint32(ticketAge/time.Millisecond) + hs.session.ageAdd transcript := hs.suite.hash.New() transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) @@ -266,28 +430,80 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { if err := transcriptMsg(hs.serverHello, transcript); err != nil { return err } - helloBytes, err := hs.hello.marshalWithoutBinders() + helloBytes, err := hello.marshalWithoutBinders() if err != nil { return err } transcript.Write(helloBytes) pskBinders := [][]byte{hs.suite.finishedHash(hs.binderKey, transcript)} - if err := hs.hello.updateBinders(pskBinders); err != nil { + if err := hello.updateBinders(pskBinders); err != nil { return err } } else { // Server selected a cipher suite incompatible with the PSK. - hs.hello.pskIdentities = nil - hs.hello.pskBinders = nil + hello.pskIdentities = nil + hello.pskBinders = nil } } - if hs.hello.earlyData { - hs.hello.earlyData = false + if hello.earlyData { + hello.earlyData = false c.quicRejectedEarlyData() } - if _, err := hs.c.writeHandshakeRecord(hs.hello, hs.transcript); err != nil { + if isInner { + hs.helloInner = hello + helloInnerMarshalled, err := hs.helloInner.marshal() + if err != nil { + return fmt.Errorf("tls: ech: helloInner.marshal(): %w", err) + } + hs.transcriptInner.Write(helloInnerMarshalled) + if err := c.echUpdateClientHelloOuter(hs.hello, hs.helloInner, nil); err != nil { + return err + } + } else { + hs.hello = hello + } + + if c.ech.offered && testingECHIllegalHandleAfterHRR { + hs.hello.raw = nil + + // Change the cipher suite and config id and set an encapsulated key in + // the updated ClientHello. This will trigger a server abort because the + // cipher suite and config id are supposed to match the previous + // ClientHello and the encapsulated key is supposed to be empty. + var ech echClientOuter + _, kdf, aead := c.ech.sealer.Suite().Params() + ech.handle.suite.kdfId = uint16(kdf) ^ 0xff + ech.handle.suite.aeadId = uint16(aead) ^ 0xff + ech.handle.configId = c.ech.configId ^ 0xff + ech.handle.enc = []byte{1, 2, 3, 4, 5} + ech.payload = []byte{1, 2, 3, 4, 5} + hs.hello.ech = ech.marshal() + } + + if testingECHTriggerBypassAfterHRR { + hs.hello.raw = nil + + // Don't send the ECH extension in the updated ClientHello. This will + // trigger a server abort, since this is illegal. + hs.hello.ech = nil + } + + if testingECHTriggerBypassBeforeHRR { + hs.hello.raw = nil + + // Send a dummy ECH extension in the updated ClientHello. This will + // trigger a server abort, since no ECH extension was sent in the + // previous ClientHello. + var err error + hs.hello.ech, err = echGenerateGreaseExt(c.config.rand()) + if err != nil { + return fmt.Errorf("tls: ech: failed to generate grease ECH: %s", err) + } + } + + if _, err := c.writeHandshakeRecord(hs.hello, nil); err != nil { return err } @@ -308,12 +524,21 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { return err } + helloMarshalled, err := hs.hello.marshal() + if err != nil { + return fmt.Errorf("tls: hello.marshal(): %w", err) + } + hs.transcript.Write(helloMarshalled) return nil } func (hs *clientHandshakeStateTLS13) processServerHello() error { c := hs.c + defer func() { + hs.hsTimings.ProcessServerHello = hs.hsTimings.elapsedTime() + }() + if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { c.sendAlert(alertUnexpectedMessage) return errors.New("tls: server sent two HelloRetryRequest messages") @@ -333,15 +558,29 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: server did not send a key share") } - if sentID, _ := curveIDForCurve(hs.ecdheKey.Curve()); hs.serverHello.serverShare.group != sentID { + if singleClientKeySharePrivateFor(hs.keySharePrivate, hs.serverHello.serverShare.group) == nil { c.sendAlert(alertIllegalParameter) return errors.New("tls: server selected unsupported group") } + c.handleCFEvent(CFEventTLSNegotiatedNamedKEX{ + KEX: hs.serverHello.serverShare.group, + }) + if !hs.serverHello.selectedIdentityPresent { return nil } + // Per the rules of draft-ietf-tls-esni-13, Section 6.1, the server is not + // permitted to resume a connection connection in the outer handshake. If + // ECH is rejected and the client-facing server replies with a + // "pre_shared_key" extension in its ServerHello, then the client MUST abort + // the handshake with an "illegal_parameter" alert. + if c.ech.offered && !c.ech.accepted { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: ech: client-facing server offered PSK after ECH rejection") + } + if int(hs.serverHello.selectedIdentity) >= len(hs.hello.pskIdentities) { c.sendAlert(alertIllegalParameter) return errors.New("tls: server selected an invalid PSK") @@ -372,15 +611,29 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error { func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { c := hs.c - peerKey, err := hs.ecdheKey.Curve().NewPublicKey(hs.serverHello.serverShare.data) - if err != nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid server key share") + var sharedKey []byte + var err error + + // We already checked that ks isn't nil in processServerHello() + ks := singleClientKeySharePrivateFor(hs.keySharePrivate, hs.serverHello.serverShare.group) + + if key, ok := ks.(*ecdh.PrivateKey); ok { + peerKey, err := key.Curve().NewPublicKey(hs.serverHello.serverShare.data) + if err == nil { + sharedKey, _ = key.ECDH(peerKey) + } + } else if key, ok := ks.(*kemPrivateKey); ok { + sk := key.secretKey + sharedKey, err = sk.Scheme().Decapsulate(sk, hs.serverHello.serverShare.data) + if err != nil { + c.sendAlert(alertIllegalParameter) + return fmt.Errorf("%s decaps: %w", sk.Scheme().Name(), err) + } } - sharedKey, err := hs.ecdheKey.ECDH(peerKey) - if err != nil { + + if sharedKey == nil { c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid server key share") + return fmt.Errorf("tls: invalid server key share") } earlySecret := hs.earlySecret @@ -478,6 +731,24 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error { return errors.New("tls: server accepted 0-RTT with the wrong ALPN") } } + if c.ech.offered && len(encryptedExtensions.ech) > 0 { + if !c.ech.accepted { + // If the server rejects ECH, then it may send retry configurations. + // If present, we must check them for syntactic correctness and + // abort if they are not correct. + c.ech.retryConfigs = encryptedExtensions.ech + if _, err = UnmarshalECHConfigs(c.ech.retryConfigs); err != nil { + c.sendAlert(alertDecodeError) + return fmt.Errorf("tls: ech: failed to parse retry configs: %s", err) + } + } else { + // Retry configs must not be sent in the inner handshake. + c.sendAlert(alertUnsupportedExtension) + return errors.New("tls: ech: got retry configs after ECH acceptance") + } + } + + hs.hsTimings.ReadEncryptedExtensions = hs.hsTimings.elapsedTime() return nil } @@ -525,6 +796,8 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { return errors.New("tls: received empty certificates message") } + hs.hsTimings.ReadCertificate = hs.hsTimings.elapsedTime() + c.scts = certMsg.certificate.SignedCertificateTimestamps c.ocspResponse = certMsg.certificate.OCSPStaple @@ -547,10 +820,11 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { } // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, c.config.supportedSignatureAlgorithms()) { c.sendAlert(alertIllegalParameter) return errors.New("tls: certificate used with invalid signature algorithm") } + sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm) if err != nil { return c.sendAlert(alertInternalError) @@ -559,8 +833,19 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: certificate used with invalid signature algorithm") } + if certMsg.delegatedCredential { + if err := hs.processDelegatedCredentialFromServer(certMsg.certificate.DelegatedCredential, certVerify); err != nil { + return err // alert sent + } + } + + pk := c.peerCertificates[0].PublicKey + if c.verifiedDC != nil { + pk = c.verifiedDC.cred.publicKey + } + signed := signedMessage(sigHash, serverSignatureContext, hs.transcript) - if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, + if err := verifyHandshakeSignature(sigType, pk, sigHash, signed, certVerify.signature); err != nil { c.sendAlert(alertDecryptError) return errors.New("tls: invalid signature by the server certificate: " + err.Error()) @@ -570,6 +855,8 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { return err } + hs.hsTimings.ReadCertificateVerify = hs.hsTimings.elapsedTime() + return nil } @@ -590,6 +877,8 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() error { return unexpectedMessageError(finished, msg) } + hs.hsTimings.ReadServerFinished = hs.hsTimings.elapsedTime() + expectedMAC := hs.suite.finishedHash(c.in.trafficSecret, hs.transcript) if !hmac.Equal(expectedMAC, finished.verifyData) { c.sendAlert(alertDecryptError) @@ -624,6 +913,44 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() error { return nil } +func certificateRequestInfo(certReq *certificateRequestMsgTLS13, vers uint16, ctx context.Context) *CertificateRequestInfo { + cri := &CertificateRequestInfo{ + SupportsDelegatedCredential: certReq.supportDelegatedCredential, + SignatureSchemes: certReq.supportedSignatureAlgorithms, + SignatureSchemesDC: certReq.supportedSignatureAlgorithmsDC, + AcceptableCAs: certReq.certificateAuthorities, + Version: vers, + ctx: ctx, + } + + return cri +} + +// getClientDelegatedCredential will return a Delegated Credential pair (a +// Delegated Credential and its private key) for the given CertificateRequestInfo, +// defaulting to the first element of cert.DelegatedCredentialPair. +// The returned Delegated Credential could be invalid for usage in the handshake. +// Returns an error if there are no delegated credentials or if the one found +// cannot be used for the current connection. +func getClientDelegatedCredential(cri *CertificateRequestInfo, cert *Certificate) (*DelegatedCredentialPair, error) { + if len(cert.DelegatedCredentials) == 0 { + return nil, errors.New("no Delegated Credential found") + } + + for _, dcPair := range cert.DelegatedCredentials { + // If the client sent the signature_algorithms in the DC extension, ensure it supports + // schemes we can use with this delegated credential. + if len(cri.SignatureSchemesDC) > 0 { + if _, err := selectSignatureSchemeDC(VersionTLS13, dcPair.DC, cri.SignatureSchemes, cri.SignatureSchemesDC); err == nil { + return &dcPair, nil + } + } + } + + // No delegated credential can be returned. + return nil, errors.New("no valid Delegated Credential found") +} + func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { c := hs.c @@ -631,26 +958,41 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { return nil } - cert, err := c.getClientCertificate(&CertificateRequestInfo{ - AcceptableCAs: hs.certReq.certificateAuthorities, - SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, - Version: c.vers, - ctx: hs.ctx, - }) + cri := certificateRequestInfo(hs.certReq, c.vers, hs.ctx) + + cert, err := c.getClientCertificate(cri) if err != nil { return err } + var dcPair *DelegatedCredentialPair + if hs.certReq.supportDelegatedCredential && len(hs.certReq.supportedSignatureAlgorithmsDC) > 0 { + // getClientDelegatedCredential selects a delegated credential that the server has advertised support for, if possible. + if delegatedCredentialPair, err := getClientDelegatedCredential(cri, cert); err == nil { + if delegatedCredentialPair.DC != nil && delegatedCredentialPair.PrivateKey != nil { + var err error + // Even if the Delegated Credential has already been marshalled, be sure it is the correct one. + if delegatedCredentialPair.DC.raw, err = delegatedCredentialPair.DC.Marshal(); err == nil { + dcPair = delegatedCredentialPair + cert.DelegatedCredential = dcPair.DC.raw + } + } + } + } + certMsg := new(certificateMsgTLS13) certMsg.certificate = *cert certMsg.scts = hs.certReq.scts && len(cert.SignedCertificateTimestamps) > 0 certMsg.ocspStapling = hs.certReq.ocspStapling && len(cert.OCSPStaple) > 0 + certMsg.delegatedCredential = hs.certReq.supportDelegatedCredential && len(cert.DelegatedCredential) > 0 if _, err := hs.c.writeHandshakeRecord(certMsg, hs.transcript); err != nil { return err } + hs.hsTimings.WriteCertificate = hs.hsTimings.elapsedTime() + // If we sent an empty certificate message, skip the CertificateVerify. if len(cert.Certificate) == 0 { return nil @@ -659,7 +1001,9 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { certVerifyMsg := new(certificateVerifyMsg) certVerifyMsg.hasSignatureAlgorithm = true - certVerifyMsg.signatureAlgorithm, err = selectSignatureScheme(c.vers, cert, hs.certReq.supportedSignatureAlgorithms) + var sigAlgorithm SignatureScheme + suppSigAlgo := hs.certReq.supportedSignatureAlgorithms + sigAlgorithm, err = selectSignatureScheme(c.vers, cert, suppSigAlgo) if err != nil { // getClientCertificate returned a certificate incompatible with the // CertificateRequestInfo supported signature algorithms. @@ -667,6 +1011,18 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { return err } + if certMsg.delegatedCredential { + suppSigAlgo = hs.certReq.supportedSignatureAlgorithmsDC + if dcPair == nil || dcPair.DC == nil { + cert.DelegatedCredential = nil + } else { + sigAlgorithm = dcPair.DC.cred.expCertVerfAlgo + cert.PrivateKey = dcPair.PrivateKey + } + } + + certVerifyMsg.signatureAlgorithm = sigAlgorithm + sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerifyMsg.signatureAlgorithm) if err != nil { return c.sendAlert(alertInternalError) @@ -688,6 +1044,8 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { return err } + hs.hsTimings.WriteCertificateVerify = hs.hsTimings.elapsedTime() + return nil } @@ -702,9 +1060,11 @@ func (hs *clientHandshakeStateTLS13) sendClientFinished() error { return err } + hs.hsTimings.WriteClientFinished = hs.hsTimings.elapsedTime() + c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret) - if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil { + if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil && !c.config.ECHEnabled { c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret, resumptionLabel, hs.transcript) } @@ -725,7 +1085,7 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { return errors.New("tls: received new session ticket from a client") } - if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { + if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil || c.config.ECHEnabled { return nil } @@ -770,3 +1130,13 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { return nil } + +func (hs *clientHandshakeStateTLS13) abortIfRequired() error { + c := hs.c + if c.ech.offered && !c.ech.accepted { + // If ECH was rejected, then abort the handshake. + c.sendAlert(alertECHRequired) + return errors.New("tls: ech: rejected") + } + return nil +} diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go index a86055a0601..b3840f6c10f 100644 --- a/src/crypto/tls/handshake_messages.go +++ b/src/crypto/tls/handshake_messages.go @@ -82,9 +82,11 @@ type clientHelloMsg struct { sessionTicket []uint8 supportedSignatureAlgorithms []SignatureScheme supportedSignatureAlgorithmsCert []SignatureScheme + supportedSignatureAlgorithmsDC []SignatureScheme secureRenegotiationSupported bool secureRenegotiation []byte extendedMasterSecret bool + delegatedCredentialSupported bool alpnProtocols []string scts bool supportedVersions []uint16 @@ -95,6 +97,7 @@ type clientHelloMsg struct { pskIdentities []pskIdentity pskBinders [][]byte quicTransportParameters []byte + ech []byte } func (m *clientHelloMsg) marshal() ([]byte, error) { @@ -103,6 +106,13 @@ func (m *clientHelloMsg) marshal() ([]byte, error) { } var exts cryptobyte.Builder + if len(m.ech) > 0 { + // draft-ietf-tls-esni-13, "encrypted_client_hello" + exts.AddUint16(extensionECH) + exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { + exts.AddBytes(m.ech) + }) + } if len(m.serverName) > 0 { // RFC 6066, Section 3 exts.AddUint16(extensionServerName) @@ -187,6 +197,19 @@ func (m *clientHelloMsg) marshal() ([]byte, error) { exts.AddUint16(extensionExtendedMasterSecret) exts.AddUint16(0) // empty extension_data } + if m.delegatedCredentialSupported { + if len(m.supportedSignatureAlgorithmsDC) > 0 { + // Draft: https://tools.ietf.org/html/draft-ietf-tls-subcerts-10 + exts.AddUint16(extensionDelegatedCredentials) + exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { + exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { + for _, sigAlgo := range m.supportedSignatureAlgorithmsDC { + exts.AddUint16(uint16(sigAlgo)) + } + }) + }) + } + } if len(m.alpnProtocols) > 0 { // RFC 7301, Section 3.1 exts.AddUint16(extensionALPN) @@ -225,7 +248,7 @@ func (m *clientHelloMsg) marshal() ([]byte, error) { }) }) } - if len(m.keyShares) > 0 { + if m.keyShares != nil { // RFC 8446, Section 4.2.8 exts.AddUint16(extensionKeyShare) exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { @@ -422,6 +445,12 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { seenExts[extension] = true switch extension { + case extensionECH: + // draft-ietf-tls-esni-13, "encrypted_client_hello" + if len(extData) == 0 || + !extData.ReadBytes(&m.ech, len(extData)) { + return false + } case extensionServerName: // RFC 6066, Section 3 var nameList cryptobyte.String @@ -554,6 +583,20 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { len(m.cookie) == 0 { return false } + case extensionDelegatedCredentials: + var sigAndAlgs cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { + return false + } + for !sigAndAlgs.Empty() { + var sigAndAlg uint16 + if !sigAndAlgs.ReadUint16(&sigAndAlg) { + return false + } + m.supportedSignatureAlgorithmsDC = append( + m.supportedSignatureAlgorithmsDC, SignatureScheme(sigAndAlg)) + } + m.delegatedCredentialSupported = true case extensionKeyShare: // RFC 8446, Section 4.2.8 var clientShares cryptobyte.String @@ -648,6 +691,7 @@ type serverHelloMsg struct { // HelloRetryRequest extensions cookie []byte selectedGroup CurveID + ech []byte } func (m *serverHelloMsg) marshal() ([]byte, error) { @@ -742,6 +786,13 @@ func (m *serverHelloMsg) marshal() ([]byte, error) { }) }) } + if len(m.ech) > 0 { + // draft-ietf-tls-esni-13, "encrypted_client_hello" + exts.AddUint16(extensionECH) + exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) { + exts.AddBytes(m.ech) + }) + } extBytes, err := exts.Bytes() if err != nil { @@ -875,6 +926,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { len(m.supportedPoints) == 0 { return false } + case extensionECH: + // draft-ietf-tls-esni-13, "encrypted_client_hello" + if !extData.ReadBytes(&m.ech, len(extData)) { + return false + } default: // Ignore unknown extensions. continue @@ -893,6 +949,7 @@ type encryptedExtensionsMsg struct { alpnProtocol string quicTransportParameters []byte earlyData bool + ech []byte } func (m *encryptedExtensionsMsg) marshal() ([]byte, error) { @@ -926,6 +983,15 @@ func (m *encryptedExtensionsMsg) marshal() ([]byte, error) { b.AddUint16(extensionEarlyData) b.AddUint16(0) // empty extension_data } + if len(m.ech) > 0 { + // draft-ietf-tls-esni-13, "encrypted_client_hello" + b.AddUint16(extensionECH) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + // If the client-facing server rejects ECH, then it may + // sends retry configurations here. + b.AddBytes(m.ech) + }) + } }) }) @@ -972,6 +1038,11 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { case extensionEarlyData: // RFC 8446, Section 4.2.10 m.earlyData = true + case extensionECH: + // draft-ietf-tls-esni-13 + if !extData.ReadBytes(&m.ech, len(extData)) { + return false + } default: // Ignore unknown extensions. continue @@ -1128,7 +1199,9 @@ type certificateRequestMsgTLS13 struct { raw []byte ocspStapling bool scts bool + supportDelegatedCredential bool supportedSignatureAlgorithms []SignatureScheme + supportedSignatureAlgorithmsDC []SignatureScheme supportedSignatureAlgorithmsCert []SignatureScheme certificateAuthorities [][]byte } @@ -1159,6 +1232,19 @@ func (m *certificateRequestMsgTLS13) marshal() ([]byte, error) { b.AddUint16(extensionSCT) b.AddUint16(0) // empty extension_data } + if m.supportDelegatedCredential { + if len(m.supportedSignatureAlgorithmsDC) > 0 { + // Draft: https://tools.ietf.org/html/draft-ietf-tls-subcerts-10 + b.AddUint16(extensionDelegatedCredentials) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, sigAlgo := range m.supportedSignatureAlgorithmsDC { + b.AddUint16(uint16(sigAlgo)) + } + }) + }) + } + } if len(m.supportedSignatureAlgorithms) > 0 { b.AddUint16(extensionSignatureAlgorithms) b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { @@ -1224,6 +1310,20 @@ func (m *certificateRequestMsgTLS13) unmarshal(data []byte) bool { m.ocspStapling = true case extensionSCT: m.scts = true + case extensionDelegatedCredentials: + var sigAndAlgs cryptobyte.String + if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { + return false + } + for !sigAndAlgs.Empty() { + var sigAndAlg uint16 + if !sigAndAlgs.ReadUint16(&sigAndAlg) { + return false + } + m.supportedSignatureAlgorithmsDC = append( + m.supportedSignatureAlgorithmsDC, SignatureScheme(sigAndAlg)) + } + m.supportDelegatedCredential = true case extensionSignatureAlgorithms: var sigAndAlgs cryptobyte.String if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() { @@ -1353,10 +1453,11 @@ func (m *certificateMsg) unmarshal(data []byte) bool { } type certificateMsgTLS13 struct { - raw []byte - certificate Certificate - ocspStapling bool - scts bool + raw []byte + certificate Certificate + ocspStapling bool + scts bool + delegatedCredential bool } func (m *certificateMsgTLS13) marshal() ([]byte, error) { @@ -1376,6 +1477,9 @@ func (m *certificateMsgTLS13) marshal() ([]byte, error) { if !m.scts { certificate.SignedCertificateTimestamps = nil } + if !m.delegatedCredential { + certificate.DelegatedCredential = nil + } marshalCertificate(b, certificate) }) @@ -1392,7 +1496,8 @@ func marshalCertificate(b *cryptobyte.Builder, certificate Certificate) { }) b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { if i > 0 { - // This library only supports OCSP and SCT for leaf certificates. + // This library only supports OCSP, SCT and Delegated Credentials for leaf certificates. + // Delegated Credentials are only supported on the leaf/end-entity certificate. return } if certificate.OCSPStaple != nil { @@ -1416,6 +1521,12 @@ func marshalCertificate(b *cryptobyte.Builder, certificate Certificate) { }) }) } + if certificate.DelegatedCredential != nil { + b.AddUint16(extensionDelegatedCredentials) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(certificate.DelegatedCredential) + }) + } }) } }) @@ -1435,6 +1546,7 @@ func (m *certificateMsgTLS13) unmarshal(data []byte) bool { m.scts = m.certificate.SignedCertificateTimestamps != nil m.ocspStapling = m.certificate.OCSPStaple != nil + m.delegatedCredential = m.certificate.DelegatedCredential != nil return true } @@ -1486,6 +1598,13 @@ func unmarshalCertificate(s *cryptobyte.String, certificate *Certificate) bool { certificate.SignedCertificateTimestamps = append( certificate.SignedCertificateTimestamps, sct) } + case extensionDelegatedCredentials: + if !extData.ReadBytes(&certificate.DelegatedCredential, len(extData)) { + return false + } + if len(certificate.DelegatedCredential) == 0 { + return false + } default: // Ignore unknown extensions. continue diff --git a/src/crypto/tls/handshake_messages_test.go b/src/crypto/tls/handshake_messages_test.go index 72e8bd8c256..27ec6e3d367 100644 --- a/src/crypto/tls/handshake_messages_test.go +++ b/src/crypto/tls/handshake_messages_test.go @@ -164,6 +164,10 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { if rand.Intn(10) > 5 { m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms() } + if rand.Intn(10) > 5 { + m.delegatedCredentialSupported = true + m.supportedSignatureAlgorithmsDC = supportedSignatureAlgorithmsDC + } for i := 0; i < rand.Intn(5); i++ { m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand)) } @@ -441,6 +445,10 @@ func (*certificateRequestMsgTLS13) Generate(rand *rand.Rand, size int) reflect.V if rand.Intn(10) > 5 { m.scts = true } + if rand.Intn(10) > 5 { + m.supportDelegatedCredential = true + m.supportedSignatureAlgorithmsDC = supportedSignatureAlgorithmsDC + } if rand.Intn(10) > 5 { m.supportedSignatureAlgorithms = supportedSignatureAlgorithms() } @@ -466,6 +474,10 @@ func (*certificateMsgTLS13) Generate(rand *rand.Rand, size int) reflect.Value { m.ocspStapling = true m.certificate.OCSPStaple = randomBytes(rand.Intn(100)+1, rand) } + if rand.Intn(10) > 5 { + m.delegatedCredential = true + m.certificate.DelegatedCredential = randomBytes(rand.Intn(100)+1, rand) + } if rand.Intn(10) > 5 { m.scts = true for i := 0; i < rand.Intn(2)+1; i++ { diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 4e84aa9d8f0..2182a438c97 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -17,6 +17,8 @@ import ( "hash" "io" "time" + + circlSign "github.com/cloudflare/circl/sign" ) // serverHandshakeState contains details of a server handshake in progress. @@ -49,6 +51,7 @@ func (c *Conn) serverHandshake(ctx context.Context) error { c: c, ctx: ctx, clientHello: clientHello, + hsTimings: createTLS13ServerHandshakeTimingInfo(c.config.Time), } return hs.handshake() } @@ -142,6 +145,15 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { return nil, unexpectedMessageError(clientHello, msg) } + // NOTE(cjpatton): ECH usage is resolved before calling GetConfigForClient() + // or GetCertifciate(). Hence, it is not currently possible to reject ECH if + // we don't recognize the inner SNI. This may or may not be desirable in the + // future. + clientHello, err = c.echAcceptOrReject(clientHello, false) // afterHRR == false + if err != nil { + return nil, fmt.Errorf("tls: %s", err) // Alert sent. + } + var configForClient *Config originalConfig := c.config if c.config.GetConfigForClient != nil { @@ -413,7 +425,7 @@ func (hs *serverHandshakeState) cipherSuiteOk(c *cipherSuite) bool { func (hs *serverHandshakeState) checkForResumption() error { c := hs.c - if c.config.SessionTicketsDisabled { + if c.config.SessionTicketsDisabled || c.config.ECHEnabled { return nil } @@ -548,7 +560,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { hs.hello.ocspStapling = true } - hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled + hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled && !c.config.ECHEnabled hs.hello.cipherSuite = hs.suite.id hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite) @@ -600,7 +612,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { } if c.vers >= VersionTLS12 { certReq.hasSignatureAlgorithm = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + certReq.supportedSignatureAlgorithms = c.config.supportedSignatureAlgorithms() } // An empty list of certificateAuthorities signals to @@ -674,6 +686,15 @@ func (hs *serverHandshakeState) doFullHandshake() error { c.sendAlert(alertHandshakeFailure) return err } + if eccKex, ok := keyAgreement.(*ecdheKeyAgreement); ok { + curveId, ok := curveIDForCurve(eccKex.key.Curve()) + if !ok { + panic("internal error: unknown curve") + } + c.handleCFEvent(CFEventTLSNegotiatedNamedKEX{ + KEX: curveId, + }) + } if hs.hello.extendedMasterSecret { c.extMasterSecret = true hs.masterSecret = extMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, @@ -924,7 +945,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { if len(certs) > 0 { switch certs[0].PublicKey.(type) { - case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey: + case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey, circlSign.PublicKey: default: c.sendAlert(alertUnsupportedCertificate) return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey) @@ -948,15 +969,17 @@ func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) } return &ClientHelloInfo{ - CipherSuites: clientHello.cipherSuites, - ServerName: clientHello.serverName, - SupportedCurves: clientHello.supportedCurves, - SupportedPoints: clientHello.supportedPoints, - SignatureSchemes: clientHello.supportedSignatureAlgorithms, - SupportedProtos: clientHello.alpnProtocols, - SupportedVersions: supportedVersions, - Conn: c.conn, - config: c.config, - ctx: ctx, + CipherSuites: clientHello.cipherSuites, + ServerName: clientHello.serverName, + SupportedCurves: clientHello.supportedCurves, + SupportedPoints: clientHello.supportedPoints, + SignatureSchemes: clientHello.supportedSignatureAlgorithms, + SupportedProtos: clientHello.alpnProtocols, + SupportedVersions: supportedVersions, + SupportsDelegatedCredential: clientHello.delegatedCredentialSupported, + SignatureSchemesDC: clientHello.supportedSignatureAlgorithmsDC, + Conn: c.conn, + config: c.config, + ctx: ctx, } } diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 15db760716c..eb740c03b5e 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -1932,6 +1932,7 @@ func TestAESCipherReorderingTLS13(t *testing.T) { supportedVersions: []uint16{VersionTLS13}, compressionMethods: []uint8{compressionNone}, keyShares: []keyShare{{group: X25519, data: pk.PublicKey().Bytes()}}, + supportedCurves: []CurveID{X25519}, }, } diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 21d798de37d..298d271d5c6 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -12,6 +12,7 @@ import ( "crypto/rsa" "encoding/binary" "errors" + "fmt" "hash" "io" "time" @@ -33,6 +34,7 @@ type serverHandshakeStateTLS13 struct { suite *cipherSuiteTLS13 cert *Certificate sigAlg SignatureScheme + selectedGroup CurveID earlySecret []byte sharedKey []byte handshakeSecret []byte @@ -40,6 +42,52 @@ type serverHandshakeStateTLS13 struct { trafficSecret []byte // client_application_traffic_secret_0 transcript hash.Hash clientFinished []byte + certReq *certificateRequestMsgTLS13 + + hsTimings CFEventTLS13ServerHandshakeTimingInfo +} + +func (hs *serverHandshakeStateTLS13) echIsInner() bool { + return len(hs.clientHello.ech) == 1 && hs.clientHello.ech[0] == echClientHelloInnerVariant +} + +// processDelegatedCredentialFromClient unmarshals the DelegatedCredential +// offered by the client (if present) and validates it using the peer's +// certificate. +func (hs *serverHandshakeStateTLS13) processDelegatedCredentialFromClient(rawDC []byte, certVerifyMsg *certificateVerifyMsg) error { + c := hs.c + + var dc *DelegatedCredential + var err error + if rawDC != nil { + // Assert that the DC extension was indicated by the client. + if !hs.certReq.supportDelegatedCredential { + c.sendAlert(alertUnexpectedMessage) + return errors.New("tls: got Delegated Credential extension without indication") + } + + dc, err = UnmarshalDelegatedCredential(rawDC) + if err != nil { + c.sendAlert(alertDecodeError) + return fmt.Errorf("tls: Delegated Credential: %s", err) + } + + if !isSupportedSignatureAlgorithm(dc.cred.expCertVerfAlgo, supportedSignatureAlgorithmsDC) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: Delegated Credential used with invalid signature algorithm") + } + } + + if dc != nil { + if !dc.Validate(c.peerCertificates[0], true, c.config.time(), certVerifyMsg) { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: invalid Delegated Credential") + } + } + + c.verifiedDC = dc + + return nil } func (hs *serverHandshakeStateTLS13) handshake() error { @@ -82,6 +130,7 @@ func (hs *serverHandshakeStateTLS13) handshake() error { return err } + c.handleCFEvent(hs.hsTimings) c.isHandshakeComplete.Store(true) return nil @@ -177,26 +226,49 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { hs.hello.cipherSuite = hs.suite.id hs.transcript = hs.suite.hash.New() - // Pick the ECDHE group in server preference order, but give priority to - // groups with a key share, to avoid a HelloRetryRequest round-trip. - var selectedGroup CurveID - var clientKeyShare *keyShare -GroupSelection: - for _, preferredGroup := range c.config.curvePreferences() { - for _, ks := range hs.clientHello.keyShares { - if ks.group == preferredGroup { - selectedGroup = ks.group - clientKeyShare = &ks - break GroupSelection + // Resolve the server's preference for the ECDHE group. + supportedCurves := c.config.curvePreferences() + if testingTriggerHRR { + // A HelloRetryRequest (HRR) is sent if the client does not offer a key + // share for a curve supported by the server. To trigger this condition + // intentionally, we compute the set of ECDHE groups supported by both + // the client and server but for which the client did not offer a key + // share. + m := make(map[CurveID]bool) + for _, serverGroup := range c.config.curvePreferences() { + for _, clientGroup := range hs.clientHello.supportedCurves { + if clientGroup == serverGroup { + m[clientGroup] = true + } } } - if selectedGroup != 0 { - continue + for _, ks := range hs.clientHello.keyShares { + delete(m, ks.group) + } + supportedCurves = nil + for group := range m { + supportedCurves = append(supportedCurves, group) } + if len(supportedCurves) == 0 { + // This occurs if the client offered a key share for each mutually + // supported group. + panic("failed to trigger HelloRetryRequest") + } + } + + // Pick group by server preference. In contrast to upstream Go, we will + // send an HelloRetryRequest and accept an extra roundtrip if there is + // a more preferred group, than those for which the client has sent + // a keyshare in the initial ClientHello. + // Cf. https://datatracker.ietf.org/doc/draft-davidben-tls-key-share-prediction/ + var selectedGroup CurveID + var clientKeyShare *keyShare +GroupSelection: + for _, preferredGroup := range supportedCurves { for _, group := range hs.clientHello.supportedCurves { if group == preferredGroup { selectedGroup = group - break + break GroupSelection } } } @@ -204,6 +276,12 @@ GroupSelection: c.sendAlert(alertHandshakeFailure) return errors.New("tls: no ECDHE curve supported by both client and server") } + for _, ks := range hs.clientHello.keyShares { + if ks.group == selectedGroup { + clientKeyShare = &ks + break + } + } if clientKeyShare == nil { if err := hs.doHelloRetryRequest(selectedGroup); err != nil { return err @@ -211,23 +289,31 @@ GroupSelection: clientKeyShare = &hs.clientHello.keyShares[0] } - if _, ok := curveForCurveID(selectedGroup); !ok { + if _, ok := curveForCurveID(selectedGroup); selectedGroup != X25519 && curveIdToCirclScheme(selectedGroup) == nil && !ok { c.sendAlert(alertInternalError) return errors.New("tls: CurvePreferences includes unsupported curve") } - key, err := generateECDHEKey(c.config.rand(), selectedGroup) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - hs.hello.serverShare = keyShare{group: selectedGroup, data: key.PublicKey().Bytes()} - peerKey, err := key.Curve().NewPublicKey(clientKeyShare.data) - if err != nil { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid client key share") + if kem := curveIdToCirclScheme(selectedGroup); kem != nil { + ct, ss, alert, err := encapsulateForKem(kem, c.config.rand(), clientKeyShare.data) + if err != nil { + c.sendAlert(alert) + return fmt.Errorf("%s encap: %w", kem.Name(), err) + } + hs.hello.serverShare = keyShare{group: selectedGroup, data: ct} + hs.sharedKey = ss + } else { + key, err := generateECDHEKey(c.config.rand(), selectedGroup) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + hs.hello.serverShare = keyShare{group: selectedGroup, data: key.PublicKey().Bytes()} + peerKey, err := key.Curve().NewPublicKey(clientKeyShare.data) + if err == nil { + hs.sharedKey, _ = key.ECDH(peerKey) + } } - hs.sharedKey, err = key.ECDH(peerKey) - if err != nil { + if hs.sharedKey == nil { c.sendAlert(alertIllegalParameter) return errors.New("tls: invalid client key share") } @@ -261,13 +347,19 @@ GroupSelection: } c.serverName = hs.clientHello.serverName + c.handleCFEvent(CFEventTLSNegotiatedNamedKEX{ + KEX: selectedGroup, + }) + + hs.hsTimings.ProcessClientHello = hs.hsTimings.elapsedTime() + return nil } func (hs *serverHandshakeStateTLS13) checkForResumption() error { c := hs.c - if c.config.SessionTicketsDisabled { + if c.config.SessionTicketsDisabled || c.config.ECHEnabled { return nil } @@ -426,6 +518,31 @@ func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash { return out } +// getDelegatedCredential will return a Delegated Credential pair (a Delegated +// Credential and its private key) for the given ClientHelloInfo, defaulting to +// the first element of cert.DelegatedCredentialPair. +// The returned Delegated Credential could be invalid for usage in the handshake. +// Returns an error if there are no delegated credentials or if the one found +// cannot be used for the current connection. +func getDelegatedCredential(clientHello *ClientHelloInfo, cert *Certificate) (*DelegatedCredentialPair, error) { + if len(cert.DelegatedCredentials) == 0 { + return nil, errors.New("no Delegated Credential found") + } + + for _, dcPair := range cert.DelegatedCredentials { + // The client must have sent the signature_algorithms in the DC extension: ensure it supports + // schemes we can use with this delegated credential. + if len(clientHello.SignatureSchemesDC) > 0 { + if _, err := selectSignatureSchemeDC(VersionTLS13, dcPair.DC, clientHello.SignatureSchemes, clientHello.SignatureSchemesDC); err == nil { + return &dcPair, nil + } + } + } + + // No delegated credential can be returned. + return nil, errors.New("no valid Delegated Credential found") +} + func (hs *serverHandshakeStateTLS13) pickCertificate() error { c := hs.c @@ -448,6 +565,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error { } return err } + hs.sigAlg, err = selectSignatureScheme(c.vers, certificate, hs.clientHello.supportedSignatureAlgorithms) if err != nil { // getCertificate returned a certificate that is unsupported or @@ -455,8 +573,29 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error { c.sendAlert(alertHandshakeFailure) return err } + hs.cert = certificate + if hs.clientHello.delegatedCredentialSupported && len(hs.clientHello.supportedSignatureAlgorithmsDC) > 0 { + // getDelegatedCredential selects a delegated credential that the client has advertised support for, if possible. + delegatedCredentialPair, err := getDelegatedCredential(clientHelloInfo(hs.ctx, c, hs.clientHello), hs.cert) + if err != nil { + // a Delegated Credential was not found. Fallback to the certificate. + return nil + } + if delegatedCredentialPair.DC != nil && delegatedCredentialPair.PrivateKey != nil { + // Even if the Delegated Credential has already been marshalled, be sure it is the correct one. + delegatedCredentialPair.DC.raw, err = delegatedCredentialPair.DC.Marshal() + if err != nil { + // invalid Delegated Credential. Fallback to the certificate. + return nil + } + hs.sigAlg = delegatedCredentialPair.DC.cred.expCertVerfAlgo + + hs.cert.PrivateKey = delegatedCredentialPair.PrivateKey + hs.cert.DelegatedCredential = delegatedCredentialPair.DC.raw + } + } return nil } @@ -477,6 +616,8 @@ func (hs *serverHandshakeStateTLS13) sendDummyChangeCipherSpec() error { func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error { c := hs.c + c.handleCFEvent(CFEventTLS13HRR{}) + // The first ClientHello gets double-hashed into the transcript upon a // HelloRetryRequest. See RFC 8446, Section 4.4.1. if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil { @@ -497,6 +638,42 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) selectedGroup: selectedGroup, } + // Decide whether to send "encrypted_client_hello" extension. + if hs.echIsInner() { + // Confirm ECH acceptance if this is the inner handshake. + echAcceptConfHRRTranscript := cloneHash(hs.transcript, hs.suite.hash) + if echAcceptConfHRRTranscript == nil { + c.sendAlert(alertInternalError) + return errors.New("tls: internal error: failed to clone hash") + } + + helloRetryRequest.ech = zeros[:8] + echAcceptConfHRR, err := helloRetryRequest.marshal() + if err != nil { + return fmt.Errorf("tls: ech: HRR.marshal(): %w", err) + } + echAcceptConfHRRTranscript.Write(echAcceptConfHRR) + echAcceptConfHRRSignal := hs.suite.expandLabel( + hs.suite.extract(hs.clientHello.random, nil), + echAcceptConfHRRLabel, + echAcceptConfHRRTranscript.Sum(nil), + 8) + + helloRetryRequest.ech = echAcceptConfHRRSignal + helloRetryRequest.raw = nil + } else if c.ech.greased { + // draft-ietf-tls-esni-13, Section 7.1: + // + // If sending a HelloRetryRequest, the server MAY include an + // "encrypted_client_hello" extension with a payload of 8 random bytes; + // see Section 10.9.4 for details. + helloRetryRequest.ech = make([]byte, 8) + if _, err := io.ReadFull(c.config.rand(), helloRetryRequest.ech); err != nil { + c.sendAlert(alertInternalError) + return fmt.Errorf("tls: internal error: rng failure: %s", err) + } + } + if _, err := hs.c.writeHandshakeRecord(helloRetryRequest, hs.transcript); err != nil { return err } @@ -517,6 +694,11 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) return unexpectedMessageError(clientHello, msg) } + clientHello, err = c.echAcceptOrReject(clientHello, true) // afterHRR == true + if err != nil { + return fmt.Errorf("tls: %s", err) // Alert sent + } + if len(clientHello.keyShares) != 1 || clientHello.keyShares[0].group != selectedGroup { c.sendAlert(alertIllegalParameter) return errors.New("tls: client sent invalid key share in second ClientHello") @@ -545,6 +727,7 @@ func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool { len(ch.supportedCurves) != len(ch1.supportedCurves) || len(ch.supportedSignatureAlgorithms) != len(ch1.supportedSignatureAlgorithms) || len(ch.supportedSignatureAlgorithmsCert) != len(ch1.supportedSignatureAlgorithmsCert) || + len(ch.supportedSignatureAlgorithmsDC) != len(ch1.supportedSignatureAlgorithmsDC) || len(ch.alpnProtocols) != len(ch1.alpnProtocols) { return true } @@ -573,6 +756,11 @@ func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool { return true } } + for i := range ch.supportedSignatureAlgorithmsDC { + if ch.supportedSignatureAlgorithmsDC[i] != ch1.supportedSignatureAlgorithmsDC[i] { + return true + } + } for i := range ch.alpnProtocols { if ch.alpnProtocols[i] != ch1.alpnProtocols[i] { return true @@ -589,6 +777,7 @@ func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool { !bytes.Equal(ch.sessionTicket, ch1.sessionTicket) || ch.secureRenegotiationSupported != ch1.secureRenegotiationSupported || !bytes.Equal(ch.secureRenegotiation, ch1.secureRenegotiation) || + ch.delegatedCredentialSupported != ch1.delegatedCredentialSupported || ch.scts != ch1.scts || !bytes.Equal(ch.cookie, ch1.cookie) || !bytes.Equal(ch.pskModes, ch1.pskModes) @@ -597,6 +786,40 @@ func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool { func (hs *serverHandshakeStateTLS13) sendServerParameters() error { c := hs.c + // Confirm ECH acceptance. + if hs.echIsInner() { + // Clear the last 8 bytes of the ServerHello.random in preparation for + // computing the confirmation hint. + copy(hs.hello.random[24:], zeros[:8]) + + // Set the last 8 bytes of ServerHello.random to a string derived from + // the inner handshake. + echAcceptConfTranscript := cloneHash(hs.transcript, hs.suite.hash) + if echAcceptConfTranscript == nil { + c.sendAlert(alertInternalError) + return errors.New("tls: internal error: failed to clone hash") + } + chMarshalled, err := hs.clientHello.marshal() + if err != nil { + return fmt.Errorf("tls: ech: clientHello.marshal(): %w", err) + } + echAcceptConfTranscript.Write(chMarshalled) + hMarshalled, err := hs.hello.marshal() + if err != nil { + return fmt.Errorf("tls: ech: hello.marshal(): %w", err) + } + echAcceptConfTranscript.Write(hMarshalled) + + echAcceptConf := hs.suite.expandLabel( + hs.suite.extract(hs.clientHello.random, nil), + echAcceptConfLabel, + echAcceptConfTranscript.Sum(nil), + 8) + + copy(hs.hello.random[24:], echAcceptConf) + hs.hello.raw = nil + } + if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil { return err } @@ -604,6 +827,8 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { return err } + hs.hsTimings.WriteServerHello = hs.hsTimings.elapsedTime() + if err := hs.sendDummyChangeCipherSpec(); err != nil { return err } @@ -653,10 +878,16 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { encryptedExtensions.earlyData = hs.earlyData } + if !c.ech.accepted && len(c.ech.retryConfigs) > 0 { + encryptedExtensions.ech = c.ech.retryConfigs + } + if _, err := hs.c.writeHandshakeRecord(encryptedExtensions, hs.transcript); err != nil { return err } + hs.hsTimings.WriteEncryptedExtensions = hs.hsTimings.elapsedTime() + return nil } @@ -677,11 +908,14 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { certReq := new(certificateRequestMsgTLS13) certReq.ocspStapling = true certReq.scts = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + certReq.supportedSignatureAlgorithms = c.config.supportedSignatureAlgorithms() + certReq.supportDelegatedCredential = c.config.SupportDelegatedCredential + certReq.supportedSignatureAlgorithmsDC = supportedSignatureAlgorithmsDC if c.config.ClientCAs != nil { certReq.certificateAuthorities = c.config.ClientCAs.Subjects() } + hs.certReq = certReq if _, err := hs.c.writeHandshakeRecord(certReq, hs.transcript); err != nil { return err } @@ -692,16 +926,18 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { certMsg.certificate = *hs.cert certMsg.scts = hs.clientHello.scts && len(hs.cert.SignedCertificateTimestamps) > 0 certMsg.ocspStapling = hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 + certMsg.delegatedCredential = hs.clientHello.delegatedCredentialSupported && len(hs.cert.DelegatedCredential) > 0 if _, err := hs.c.writeHandshakeRecord(certMsg, hs.transcript); err != nil { return err } + hs.hsTimings.WriteCertificate = hs.hsTimings.elapsedTime() + certVerifyMsg := new(certificateVerifyMsg) certVerifyMsg.hasSignatureAlgorithm = true certVerifyMsg.signatureAlgorithm = hs.sigAlg - - sigType, sigHash, err := typeAndHashFromSignatureScheme(hs.sigAlg) + sigType, sigHash, err := typeAndHashFromSignatureScheme(certVerifyMsg.signatureAlgorithm) if err != nil { return c.sendAlert(alertInternalError) } @@ -728,6 +964,8 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { return err } + hs.hsTimings.WriteCertificateVerify = hs.hsTimings.elapsedTime() + return nil } @@ -742,6 +980,8 @@ func (hs *serverHandshakeStateTLS13) sendServerFinished() error { return err } + hs.hsTimings.WriteServerFinished = hs.hsTimings.elapsedTime() + // Derive secrets that take context through the server Finished. hs.masterSecret = hs.suite.extract(nil, @@ -787,7 +1027,7 @@ func (hs *serverHandshakeStateTLS13) sendServerFinished() error { } func (hs *serverHandshakeStateTLS13) shouldSendSessionTickets() bool { - if hs.c.config.SessionTicketsDisabled { + if hs.c.config.SessionTicketsDisabled || hs.c.config.ECHEnabled { return false } @@ -923,6 +1163,8 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { } } + hs.hsTimings.ReadCertificate = hs.hsTimings.elapsedTime() + if len(certMsg.certificate.Certificate) != 0 { // certificateVerifyMsg is included in the transcript, but not until // after we verify the handshake signature, since the state before @@ -939,7 +1181,7 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { } // See RFC 8446, Section 4.4.3. - if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) { + if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, c.config.supportedSignatureAlgorithms()) { c.sendAlert(alertIllegalParameter) return errors.New("tls: client certificate used with invalid signature algorithm") } @@ -951,9 +1193,20 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: client certificate used with invalid signature algorithm") } + + if certMsg.delegatedCredential { + if err := hs.processDelegatedCredentialFromClient(certMsg.certificate.DelegatedCredential, certVerify); err != nil { + return err + } + } + + pk := c.peerCertificates[0].PublicKey + if c.verifiedDC != nil { + pk = c.verifiedDC.cred.publicKey + } + signed := signedMessage(sigHash, clientSignatureContext, hs.transcript) - if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, - sigHash, signed, certVerify.signature); err != nil { + if err := verifyHandshakeSignature(sigType, pk, sigHash, signed, certVerify.signature); err != nil { c.sendAlert(alertDecryptError) return errors.New("tls: invalid signature by the client certificate: " + err.Error()) } @@ -963,6 +1216,8 @@ func (hs *serverHandshakeStateTLS13) readClientCertificate() error { } } + hs.hsTimings.ReadCertificateVerify = hs.hsTimings.elapsedTime() + // If we waited until the client certificates to send session tickets, we // are ready to do it now. if err := hs.sendSessionTickets(); err != nil { @@ -992,6 +1247,8 @@ func (hs *serverHandshakeStateTLS13) readClientFinished() error { return errors.New("tls: invalid client finished hash") } + hs.hsTimings.ReadClientFinished = hs.hsTimings.elapsedTime() + c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret) return nil diff --git a/src/crypto/tls/hpke.go b/src/crypto/tls/hpke.go new file mode 100644 index 00000000000..b3861d0951b --- /dev/null +++ b/src/crypto/tls/hpke.go @@ -0,0 +1,42 @@ +// Copyright 2020 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "errors" + "fmt" + + "github.com/cloudflare/circl/hpke" +) + +// The mandatory-to-implement HPKE cipher suite for use with the ECH extension. +var defaultHPKESuite hpke.Suite + +func init() { + var err error + defaultHPKESuite, err = hpkeAssembleSuite( + uint16(hpke.KEM_X25519_HKDF_SHA256), + uint16(hpke.KDF_HKDF_SHA256), + uint16(hpke.AEAD_AES128GCM), + ) + if err != nil { + panic(fmt.Sprintf("hpke: mandatory-to-implement cipher suite not supported: %s", err)) + } +} + +func hpkeAssembleSuite(kemId, kdfId, aeadId uint16) (hpke.Suite, error) { + kem := hpke.KEM(kemId) + if !kem.IsValid() { + return hpke.Suite{}, errors.New("KEM is not supported") + } + kdf := hpke.KDF(kdfId) + if !kdf.IsValid() { + return hpke.Suite{}, errors.New("KDF is not supported") + } + aead := hpke.AEAD(aeadId) + if !aead.IsValid() { + return hpke.Suite{}, errors.New("AEAD is not supported") + } + return hpke.NewSuite(kem, kdf, aead), nil +} diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go index 2c8c5b8d771..b33b0f2d9ab 100644 --- a/src/crypto/tls/key_agreement.go +++ b/src/crypto/tls/key_agreement.go @@ -130,7 +130,7 @@ func md5SHA1Hash(slices [][]byte) []byte { // the sigType (for earlier TLS versions). For Ed25519 signatures, which don't // do pre-hashing, it returns the concatenation of the slices. func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte { - if sigType == signatureEd25519 { + if sigType == signatureEd25519 || circlSchemeBySigType(sigType) != nil { var signed []byte for _, slice := range slices { signed = append(signed, slice...) @@ -169,7 +169,7 @@ type ecdheKeyAgreement struct { func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { var curveID CurveID for _, c := range clientHello.supportedCurves { - if config.supportsCurve(c) { + if config.supportsCurve(c) && curveIdToCirclScheme(c) == nil { curveID = c break } diff --git a/src/crypto/tls/metrics_test.go b/src/crypto/tls/metrics_test.go new file mode 100644 index 00000000000..60b60291054 --- /dev/null +++ b/src/crypto/tls/metrics_test.go @@ -0,0 +1,132 @@ +// Copyright 2020 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "context" + "crypto/x509" + "fmt" + "io" + "io/ioutil" + "testing" + "time" +) + +type testTimingInfo struct { + serverTimingInfo CFEventTLS13ServerHandshakeTimingInfo + clientTimingInfo CFEventTLS13ClientHandshakeTimingInfo +} + +func (t testTimingInfo) isMonotonicallyIncreasing() bool { + serverIsMonotonicallyIncreasing := + t.serverTimingInfo.ProcessClientHello < t.serverTimingInfo.WriteServerHello && + t.serverTimingInfo.WriteServerHello < t.serverTimingInfo.WriteEncryptedExtensions && + t.serverTimingInfo.WriteEncryptedExtensions < t.serverTimingInfo.WriteCertificate && + t.serverTimingInfo.WriteCertificate < t.serverTimingInfo.WriteCertificateVerify && + t.serverTimingInfo.WriteCertificateVerify < t.serverTimingInfo.WriteServerFinished && + t.serverTimingInfo.WriteServerFinished < t.serverTimingInfo.ReadCertificate && + t.serverTimingInfo.ReadCertificate < t.serverTimingInfo.ReadCertificateVerify && + t.serverTimingInfo.ReadCertificateVerify < t.serverTimingInfo.ReadClientFinished + + clientIsMonotonicallyIncreasing := + t.clientTimingInfo.WriteClientHello < t.clientTimingInfo.ProcessServerHello && + t.clientTimingInfo.ProcessServerHello < t.clientTimingInfo.ReadEncryptedExtensions && + t.clientTimingInfo.ReadEncryptedExtensions < t.clientTimingInfo.ReadCertificate && + t.clientTimingInfo.ReadCertificate < t.clientTimingInfo.ReadCertificateVerify && + t.clientTimingInfo.ReadCertificateVerify < t.clientTimingInfo.ReadServerFinished && + t.clientTimingInfo.ReadServerFinished < t.clientTimingInfo.WriteCertificate && + t.clientTimingInfo.WriteCertificate < t.clientTimingInfo.WriteCertificateVerify && + t.clientTimingInfo.WriteCertificateVerify < t.clientTimingInfo.WriteClientFinished + + return (serverIsMonotonicallyIncreasing && clientIsMonotonicallyIncreasing) +} + +func (r *testTimingInfo) eventHandler(event CFEvent) { + switch e := event.(type) { + case CFEventTLS13ServerHandshakeTimingInfo: + r.serverTimingInfo = e + case CFEventTLS13ClientHandshakeTimingInfo: + r.clientTimingInfo = e + } +} + +func runHandshake(t *testing.T, clientConfig, serverConfig *Config) (timingState testTimingInfo, err error) { + const sentinel = "SENTINEL\n" + c, s := localPipe(t) + errChan := make(chan error) + + go func() { + cli := Client(c, clientConfig) + cCtx := context.WithValue(context.Background(), CFEventHandlerContextKey{}, timingState.eventHandler) + err := cli.HandshakeContext(cCtx) + if err != nil { + errChan <- fmt.Errorf("client: %v", err) + c.Close() + return + } + defer cli.Close() + buf, err := ioutil.ReadAll(cli) + if err != nil { + t.Errorf("failed to call cli.Read: %v", err) + } + if got := string(buf); got != sentinel { + t.Errorf("read %q from TLS connection, but expected %q", got, sentinel) + } + errChan <- nil + }() + + server := Server(s, serverConfig) + sCtx := context.WithValue(context.Background(), CFEventHandlerContextKey{}, timingState.eventHandler) + err = server.HandshakeContext(sCtx) + if err == nil { + if _, err := io.WriteString(server, sentinel); err != nil { + t.Errorf("failed to call server.Write: %v", err) + } + if err := server.Close(); err != nil { + t.Errorf("failed to call server.Close: %v", err) + } + err = <-errChan + } else { + s.Close() + <-errChan + } + + return +} + +func TestTLS13HandshakeTiming(t *testing.T) { + issuer, err := x509.ParseCertificate(testRSACertificateIssuer) + if err != nil { + panic(err) + } + rootCAs := x509.NewCertPool() + rootCAs.AddCert(issuer) + + const serverName = "example.golang" + + baseConfig := &Config{ + Time: time.Now, + Rand: zeroSource{}, + Certificates: make([]Certificate, 1), + MaxVersion: VersionTLS13, + RootCAs: rootCAs, + ClientCAs: rootCAs, + ClientAuth: RequireAndVerifyClientCert, + ServerName: serverName, + } + baseConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} + baseConfig.Certificates[0].PrivateKey = testRSAPrivateKey + + clientConfig := baseConfig.Clone() + serverConfig := baseConfig.Clone() + + ts, err := runHandshake(t, clientConfig, serverConfig) + if err != nil { + t.Fatalf("Handshake failed: %v", err) + } + + if !ts.isMonotonicallyIncreasing() { + t.Fatalf("Timing information is not monotonic") + } +} diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go index a7fa3370e66..1e6c49024f0 100644 --- a/src/crypto/tls/prf.go +++ b/src/crypto/tls/prf.go @@ -225,11 +225,11 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte { // hashForClientCertificate returns the handshake messages so far, pre-hashed if // necessary, suitable for signing by a TLS client certificate. func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash) []byte { - if (h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil { + if (h.version >= VersionTLS12 || sigType == signatureEd25519 || circlSchemeBySigType(sigType) != nil) && h.buffer == nil { panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer") } - if sigType == signatureEd25519 { + if sigType == signatureEd25519 || circlSchemeBySigType(sigType) != nil { return h.buffer } diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go index 8509b7dc0dd..a4826be91a6 100644 --- a/src/crypto/tls/tls.go +++ b/src/crypto/tls/tls.go @@ -4,8 +4,49 @@ // Package tls partially implements TLS 1.2, as specified in RFC 5246, // and TLS 1.3, as specified in RFC 8446. +// +// This package implements the "Encrypted ClientHello (ECH)" extension, as +// specified by draft-ietf-tls-esni-13. This extension allows the client to +// encrypt its ClientHello to the public key of an ECH-service provider, known +// as the client-facing server. If successful, then the client-facing server +// forwards the decrypted ClientHello to the intended recipient, known as the +// backend server. The goal of this mechanism is to ensure that connections made +// to backend servers are indistinguishable from one another. +// +// This package implements the "Delegated Credentials" extension, as +// specified by draft-ietf-tls-subcerts-10. This extension allows the usage +// of a limited delegation mechanism that allows a TLS peer to issue its own +// credentials within the scope of a certificate issued by an external +// CA. These credentials only enable the recipient of the delegation to +// speak for names that the CA has authorized. If the client or server supports +// this extension, then the server or client may use a "delegated credential" +// as the signing key in the handshake. A delegated credential is a short lived +// public/secret key pair delegated to the peer by an entity trusted by the +// corresponding peer. This allows a reverse proxy to terminate a TLS connection +// on behalf of the entity. Credentials can't be revoked; in order to +// mitigate risk in case the reverse proxy is compromised, the credential is only +// valid for a short time (days, hours, or even minutes). package tls +// BUG(cjpatton): In order to achieve its security goal, the ECH extension +// requires padding in order to ensure that the length of handshake messages +// doesn't depend on who terminates the connection. This package does not yet +// implement server-side padding: see +// https://github.com/tlswg/draft-ietf-tls-esni/issues/264. + +// BUG(cjpatton): The interaction of the ECH extension with PSK has not yet been +// fully vetted. For now, the server disables session tickets if ECH is enabled. + +// BUG(cjpatton): Upon ECH rejection, if retry configurations are provided, then +// the client is expected to retry the connection. Otherwise, it may regard ECH +// as being securely disabled by the client-facing server. The client in this +// package does not attempt to retry the handshake. + +// BUG(cjpatton): If the client offers the ECH extension and the client-facing +// server rejects it, then only the client-facing server is authenticated. In +// particular, the client is expected to respond to a CertificateRequest with an +// empty certificate. This package does not yet implement this behavior. + // BUG(agl): The crypto/tls package only implements some countermeasures // against Lucky13 attacks on CBC-mode encryption, and only on SHA1 // variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and @@ -25,6 +66,8 @@ import ( "net" "os" "strings" + + circlSign "github.com/cloudflare/circl/sign" ) // Server returns a new TLS server side connection @@ -326,6 +369,17 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { if !bytes.Equal(priv.Public().(ed25519.PublicKey), pub) { return fail(errors.New("tls: private key does not match public key")) } + case circlSign.PublicKey: + priv, ok := cert.PrivateKey.(circlSign.PrivateKey) + if !ok { + return fail(errors.New("tls: private key type does not match public key type")) + } + pkBytes, err := priv.Public().(circlSign.PublicKey).MarshalBinary() + pkBytes2, err2 := pub.MarshalBinary() + + if err != nil || err2 != nil || !bytes.Equal(pkBytes, pkBytes2) { + return fail(errors.New("tls: private key does not match public key")) + } default: return fail(errors.New("tls: unknown public key algorithm")) } @@ -342,7 +396,7 @@ func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { } if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { switch key := key.(type) { - case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey: + case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey, circlSign.PrivateKey: return key, nil default: return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping") diff --git a/src/crypto/tls/tls_cf.go b/src/crypto/tls/tls_cf.go new file mode 100644 index 00000000000..620615d8527 --- /dev/null +++ b/src/crypto/tls/tls_cf.go @@ -0,0 +1,68 @@ +// Copyright 2021 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + circlPki "github.com/cloudflare/circl/pki" + circlSign "github.com/cloudflare/circl/sign" + "github.com/cloudflare/circl/sign/eddilithium2" + "github.com/cloudflare/circl/sign/eddilithium3" +) + +// To add a signature scheme from Circl +// +// 1. make sure it implements TLSScheme and CertificateScheme, +// 2. follow the instructions in crypto/x509/x509_cf.go +// 3. add a signature to the iota in common.go +// 4. add row in the circlSchemes lists below + +var circlSchemes = [...]struct { + sigType uint8 + scheme circlSign.Scheme +}{ + {signatureEdDilithium2, eddilithium2.Scheme()}, + {signatureEdDilithium3, eddilithium3.Scheme()}, +} + +func circlSchemeBySigType(sigType uint8) circlSign.Scheme { + for _, cs := range circlSchemes { + if cs.sigType == sigType { + return cs.scheme + } + } + return nil +} + +func sigTypeByCirclScheme(scheme circlSign.Scheme) uint8 { + for _, cs := range circlSchemes { + if cs.scheme == scheme { + return cs.sigType + } + } + return 0 +} + +var supportedSignatureAlgorithmsWithCircl []SignatureScheme + +// supportedSignatureAlgorithms returns enabled signature schemes. PQ signature +// schemes are only included when tls.Config#PQSignatureSchemesEnabled is set +// and FIPS-only mode is not enabled. +func (c *Config) supportedSignatureAlgorithms() []SignatureScheme { + // If FIPS-only mode is requested, do not add other algos. + if needFIPS() { + return supportedSignatureAlgorithms() + } + if c != nil && c.PQSignatureSchemesEnabled { + return supportedSignatureAlgorithmsWithCircl + } + return defaultSupportedSignatureAlgorithms +} + +func init() { + supportedSignatureAlgorithmsWithCircl = append([]SignatureScheme{}, defaultSupportedSignatureAlgorithms...) + for _, cs := range circlSchemes { + supportedSignatureAlgorithmsWithCircl = append(supportedSignatureAlgorithmsWithCircl, + SignatureScheme(cs.scheme.(circlPki.TLSScheme).TLSIdentifier())) + } +} diff --git a/src/crypto/tls/tls_cf_circl_test.go b/src/crypto/tls/tls_cf_circl_test.go new file mode 100644 index 00000000000..f70ee0ad788 --- /dev/null +++ b/src/crypto/tls/tls_cf_circl_test.go @@ -0,0 +1,134 @@ +// Copyright 2022 Cloudflare, Inc. All rights reserved. Use of this source code +// is governed by a BSD-style license that can be found in the LICENSE file. + +package tls + +import ( + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "fmt" + "math/big" + "testing" + "time" + + "github.com/cloudflare/circl/sign" + "github.com/cloudflare/circl/sign/eddilithium2" +) + +func TestPQSignatureSchemes(t *testing.T) { + pqCert := createPQCert(t, eddilithium2.Scheme()) + rsaCert := Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + } + pqAndRsaCerts := []Certificate{pqCert, rsaCert} + rsaOnlyCerts := []Certificate{rsaCert} + + cases := []struct { + clientPQ, serverPQ bool + serverCerts []Certificate + expectedCertSigAlg x509.SignatureAlgorithm + }{ + { + clientPQ: false, + serverPQ: false, + serverCerts: pqAndRsaCerts, + expectedCertSigAlg: x509.SHA256WithRSA, + }, + { + clientPQ: false, + serverPQ: true, + serverCerts: pqAndRsaCerts, + expectedCertSigAlg: x509.SHA256WithRSA, + }, + { + // PQ is always selected when the clients supports it. + clientPQ: true, + serverPQ: false, + serverCerts: pqAndRsaCerts, + expectedCertSigAlg: x509.PureEdDilithium2, + }, + { + clientPQ: true, + serverPQ: true, + serverCerts: pqAndRsaCerts, + expectedCertSigAlg: x509.PureEdDilithium2, + }, + { + clientPQ: true, + serverPQ: true, + serverCerts: rsaOnlyCerts, + expectedCertSigAlg: x509.SHA256WithRSA, + }, + } + + for i, tc := range cases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + clientConfig := testConfig.Clone() + clientConfig.PQSignatureSchemesEnabled = tc.clientPQ + + serverConfig := testConfig.Clone() + serverConfig.PQSignatureSchemesEnabled = tc.serverPQ + serverConfig.Certificates = tc.serverCerts + + c, s := localPipe(t) + done := make(chan error) + defer c.Close() + + go func() { + defer s.Close() + done <- Server(s, serverConfig).Handshake() + }() + + cli := Client(c, clientConfig) + clientErr := cli.Handshake() + serverErr := <-done + if clientErr != nil { + t.Errorf("client error: %s", clientErr) + } + if serverErr != nil { + t.Errorf("server error: %s", serverErr) + } + serverCerts := cli.ConnectionState().PeerCertificates + if len(serverCerts) != 1 { + t.Errorf("expected 1 server cert, got %d", len(serverCerts)) + } + if serverCerts[0].SignatureAlgorithm != tc.expectedCertSigAlg { + t.Errorf("unexpected signature algorithm, got %s want %s", serverCerts[0].SignatureAlgorithm, tc.expectedCertSigAlg) + } + }) + } +} + +func createPQCert(t *testing.T, sch sign.Scheme) Certificate { + seed := make([]byte, sch.SeedSize()) + pub, priv := sch.DeriveKey(seed) + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + notBefore := time.Now() + notAfter := notBefore.Add(365 * 24 * time.Hour) + + template := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"Acme Co"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + + cert, err := x509.CreateCertificate(rand.Reader, template, template, pub, priv) + if err != nil { + t.Fatal(err) + } + + return Certificate{ + Certificate: [][]byte{cert}, + PrivateKey: priv, + } +} diff --git a/src/crypto/tls/tls_cf_test.go b/src/crypto/tls/tls_cf_test.go new file mode 100644 index 00000000000..3106795d5a3 --- /dev/null +++ b/src/crypto/tls/tls_cf_test.go @@ -0,0 +1,54 @@ +package tls + +import ( + "crypto/rand" + "testing" + + "github.com/cloudflare/circl/hpke" +) + +// If the client uses the wrong KEM algorithm to offer ECH, the ECH provider +// should reject rather than abort. We check for this condition by looking at +// the error returned by hpke.Receiver.Setup(). This test asserts that the +// CIRCL's HPKE implementation returns the error we expect. +func TestCirclHpkeKemAlgorithmMismatchError(t *testing.T) { + kem := hpke.KEM_P256_HKDF_SHA256 + kdf := hpke.KDF_HKDF_SHA256 + aead := hpke.AEAD_AES128GCM + suite := hpke.NewSuite(kem, kdf, aead) + _, sk, err := kem.Scheme().GenerateKeyPair() + if err != nil { + t.Fatal(err) + } + + incorrectKEM := hpke.KEM_X25519_HKDF_SHA256 + incorrectSuite := hpke.NewSuite(incorrectKEM, kdf, aead) + incorrectPK, _, err := incorrectKEM.Scheme().GenerateKeyPair() + if err != nil { + t.Fatal(err) + } + + // Generate an encapsulated key share with the incorrect KEM algorithm. + incorrectSender, err := incorrectSuite.NewSender(incorrectPK, []byte("some info string")) + if err != nil { + t.Fatal(err) + } + incorrectEnc, _, err := incorrectSender.Setup(rand.Reader) + if err != nil { + t.Fatal(err) + } + + // Attempt to parse an encapsulated key generated using the incorrect KEM + // algorithm. + receiver, err := suite.NewReceiver(sk, []byte("some info string")) + if err != nil { + t.Fatal(err) + } + + expectedErrorString := "hpke: invalid KEM public key" + if _, err := receiver.Setup(incorrectEnc); err == nil { + t.Errorf("expected error; got success") + } else if err.Error() != expectedErrorString { + t.Errorf("incorrect error string: got '%s'; want '%s'", err, expectedErrorString) + } +} diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index 42a0272f005..874548db670 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -830,7 +830,7 @@ func TestCloneNonFuncFields(t *testing.T) { switch fn := typ.Field(i).Name; fn { case "Rand": f.Set(reflect.ValueOf(io.Reader(os.Stdin))) - case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "VerifyConnection", "GetClientCertificate", "WrapSession", "UnwrapSession": + case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "VerifyConnection", "GetClientCertificate", "WrapSession", "UnwrapSession", "ServerECHProvider": // DeepEqual can't compare functions. If you add a // function field to this list, you must also change // TestCloneFuncFields to ensure that the func field is @@ -857,16 +857,26 @@ func TestCloneNonFuncFields(t *testing.T) { f.Set(reflect.ValueOf(true)) case "MinVersion", "MaxVersion": f.Set(reflect.ValueOf(uint16(VersionTLS12))) + case "SupportDelegatedCredential": + f.Set(reflect.ValueOf(true)) case "SessionTicketKey": f.Set(reflect.ValueOf([32]byte{})) case "CipherSuites": f.Set(reflect.ValueOf([]uint16{1, 2})) case "CurvePreferences": f.Set(reflect.ValueOf([]CurveID{CurveP256})) + case "ClientCurveGuess": + f.Set(reflect.ValueOf([]CurveID{CurveP256})) + case "PQSignatureSchemesEnabled": + f.Set(reflect.ValueOf(true)) case "Renegotiation": f.Set(reflect.ValueOf(RenegotiateOnceAsClient)) case "mutex", "autoSessionTicketKeys", "sessionTicketKeys": continue // these are unexported fields that are handled separately + case "ClientECHConfigs": + f.Set(reflect.ValueOf([]ECHConfig{ECHConfig{}})) + case "ECHEnabled": + f.Set(reflect.ValueOf(true)) default: t.Errorf("all fields must be accounted for, but saw unknown field %q", fn) } diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go index 812b0d2d285..0cda16738c6 100644 --- a/src/crypto/x509/parser.go +++ b/src/crypto/x509/parser.go @@ -25,6 +25,8 @@ import ( "unicode/utf16" "unicode/utf8" + circlPki "github.com/cloudflare/circl/pki" + "golang.org/x/crypto/cryptobyte" cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" ) @@ -312,6 +314,19 @@ func parsePublicKey(keyData *publicKeyInfo) (any, error) { } return pub, nil default: + if scheme := circlPki.SchemeByOid(oid); scheme != nil { + if len(keyData.Algorithm.Parameters.FullBytes) != 0 { + return nil, fmt.Errorf( + "x509: %skey encoded with illegal parameters", + scheme.Name(), + ) + } + pub, err := scheme.UnmarshalBinaryPublicKey([]byte(der)) + if err != nil { + return nil, fmt.Errorf("x509: %s: %v", scheme.Name(), err) + } + return pub, nil + } return nil, errors.New("x509: unknown public key algorithm") } } @@ -790,6 +805,15 @@ func processExtensions(out *Certificate) error { out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(aiaDER)) } } + } else if e.Id.Equal(oidExtensionDelegatedCredential) { + if !out.IsCA { + if out.KeyUsage == KeyUsageDigitalSignature { + if !bytes.Equal(e.Value, asn1.NullBytes) { + return errors.New("x509: invalid delegated credential extension") + } + out.AllowDC = true + } + } } else { // Unknown extensions are recorded if critical. unhandled = true diff --git a/src/crypto/x509/pkcs8.go b/src/crypto/x509/pkcs8.go index 08e9da404c3..411a549cbce 100644 --- a/src/crypto/x509/pkcs8.go +++ b/src/crypto/x509/pkcs8.go @@ -13,6 +13,9 @@ import ( "encoding/asn1" "errors" "fmt" + + circlPki "github.com/cloudflare/circl/pki" + circlSign "github.com/cloudflare/circl/sign" ) // pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See @@ -87,7 +90,22 @@ func ParsePKCS8PrivateKey(der []byte) (key any, err error) { return ecdh.X25519().NewPrivateKey(curvePrivateKey) default: - return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) + scheme := circlPki.SchemeByOid(privKey.Algo.Algorithm) + if scheme == nil { + return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) + } + if l := len(privKey.Algo.Parameters.FullBytes); l != 0 { + return nil, fmt.Errorf("x509: invalid %s private key parameters", scheme.Name()) + } + var packedSk []byte + if _, err := asn1.Unmarshal(privKey.PrivateKey, &packedSk); err != nil { + return nil, fmt.Errorf("x509: invalid %s private key: %v", scheme.Name(), err) + } + sk, err := scheme.UnmarshalBinaryPrivateKey(packedSk) + if err != nil { + return nil, fmt.Errorf("x509: invalid %s private key: %v", scheme.Name(), err) + } + return sk, nil } } @@ -167,6 +185,22 @@ func MarshalPKCS8PrivateKey(key any) ([]byte, error) { } } + case circlSign.PrivateKey: + scheme, ok := k.Scheme().(circlPki.CertificateScheme) + if !ok { + return nil, fmt.Errorf( + "x509: circl private key is not CertificateScheme") + } + privKey.Algo = pkix.AlgorithmIdentifier{ + Algorithm: scheme.Oid(), + } + bytes, _ := k.MarshalBinary() + packedSk, err := asn1.Marshal(bytes) + if err != nil { + return nil, fmt.Errorf("x509: failed to marshal private key: %v", err) + } + privKey.PrivateKey = packedSk + default: return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key) } diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index 8a7a5f6e2c6..52de3231429 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -1717,7 +1717,7 @@ func TestValidHostname(t *testing.T) { } } -func generateCert(cn string, isCA bool, issuer *Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) { +func generateCert(cn string, isCA bool, isDC bool, issuer *Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, nil, err @@ -1736,6 +1736,7 @@ func generateCert(cn string, isCA bool, issuer *Certificate, issuerKey crypto.Pr ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, BasicConstraintsValid: true, IsCA: isCA, + AllowDC: isDC, } if issuer == nil { issuer = template @@ -1763,21 +1764,21 @@ func TestPathologicalChain(t *testing.T) { // path building worst behavior. roots, intermediates := NewCertPool(), NewCertPool() - parent, parentKey, err := generateCert("Root CA", true, nil, nil) + parent, parentKey, err := generateCert("Root CA", true, false, nil, nil) if err != nil { t.Fatal(err) } roots.AddCert(parent) for i := 1; i < 100; i++ { - parent, parentKey, err = generateCert("Intermediate CA", true, parent, parentKey) + parent, parentKey, err = generateCert("Intermediate CA", true, false, parent, parentKey) if err != nil { t.Fatal(err) } intermediates.AddCert(parent) } - leaf, _, err := generateCert("Leaf", false, parent, parentKey) + leaf, _, err := generateCert("Leaf", false, true, parent, parentKey) if err != nil { t.Fatal(err) } @@ -1801,7 +1802,7 @@ func TestLongChain(t *testing.T) { roots, intermediates := NewCertPool(), NewCertPool() - parent, parentKey, err := generateCert("Root CA", true, nil, nil) + parent, parentKey, err := generateCert("Root CA", true, false, nil, nil) if err != nil { t.Fatal(err) } @@ -1809,14 +1810,14 @@ func TestLongChain(t *testing.T) { for i := 1; i < 15; i++ { name := fmt.Sprintf("Intermediate CA #%d", i) - parent, parentKey, err = generateCert(name, true, parent, parentKey) + parent, parentKey, err = generateCert(name, true, false, parent, parentKey) if err != nil { t.Fatal(err) } intermediates.AddCert(parent) } - leaf, _, err := generateCert("Leaf", false, parent, parentKey) + leaf, _, err := generateCert("Leaf", false, true, parent, parentKey) if err != nil { t.Fatal(err) } diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 15b3b9ed35e..194a18c88a0 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -49,6 +49,9 @@ import ( _ "crypto/sha256" _ "crypto/sha512" + circlPki "github.com/cloudflare/circl/pki" + circlSign "github.com/cloudflare/circl/sign" + "golang.org/x/crypto/cryptobyte" cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" ) @@ -131,6 +134,14 @@ func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.A } publicKeyAlgorithm.Parameters.FullBytes = paramBytes } + case circlSign.PublicKey: + scheme, ok := pub.Scheme().(circlPki.CertificateScheme) + if !ok { + return nil, pkix.AlgorithmIdentifier{}, errors.New( + "x509: circl scheme is not CertificateScheme") + } + publicKeyBytes, _ = pub.MarshalBinary() + publicKeyAlgorithm.Algorithm = scheme.Oid() default: return nil, pkix.AlgorithmIdentifier{}, fmt.Errorf("x509: unsupported public key type: %T", pub) } @@ -230,6 +241,8 @@ const ( SHA384WithRSAPSS SHA512WithRSAPSS PureEd25519 + PureEdDilithium2 + PureEdDilithium3 ) func (algo SignatureAlgorithm) isRSAPSS() bool { @@ -258,13 +271,17 @@ const ( DSA // Only supported for parsing. ECDSA Ed25519 + EdDilithium2 + EdDilithium3 ) var publicKeyAlgoName = [...]string{ - RSA: "RSA", - DSA: "DSA", - ECDSA: "ECDSA", - Ed25519: "Ed25519", + RSA: "RSA", + DSA: "DSA", + ECDSA: "ECDSA", + Ed25519: "Ed25519", + EdDilithium2: "Ed25519-Dilithium2", + EdDilithium3: "Ed448-Dilithium3", } func (algo PublicKeyAlgorithm) String() string { @@ -404,7 +421,7 @@ type pssParameters struct { } func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm { - if ai.Algorithm.Equal(oidSignatureEd25519) { + if ai.Algorithm.Equal(oidSignatureEd25519) || circlPki.SchemeByOid(ai.Algorithm) != nil { // RFC 8410, Section 3 // > For all of the OIDs, the parameters MUST be absent. if len(ai.Parameters.FullBytes) != 0 { @@ -497,8 +514,13 @@ func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm return ECDSA case oid.Equal(oidPublicKeyEd25519): return Ed25519 + default: + scheme := circlPki.SchemeByOid(oid) + if scheme == nil { + return UnknownPublicKeyAlgorithm + } + return PublicKeyAlgorithmByCirclScheme(scheme) } - return UnknownPublicKeyAlgorithm } // RFC 5480, 2.1.1.1. Named Curve @@ -724,6 +746,9 @@ type Certificate struct { BasicConstraintsValid bool IsCA bool + // AllowDC indicates if the certificate can be used for delegated credentials. + AllowDC bool + // MaxPathLen and MaxPathLenZero indicate the presence and // value of the BasicConstraints' "pathLenConstraint". // @@ -896,7 +921,7 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey switch hashType { case crypto.Hash(0): - if pubKeyAlgo != Ed25519 { + if pubKeyAlgo != Ed25519 && CirclSchemeByPublicKeyAlgorithm(pubKeyAlgo) == nil { return ErrUnsupportedAlgorithm } case crypto.MD5: @@ -945,6 +970,19 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey return errors.New("x509: Ed25519 verification failure") } return + case circlSign.PublicKey: + scheme := pub.Scheme() + expectedAlg := PublicKeyAlgorithmByCirclScheme(scheme) + if expectedAlg == UnknownPublicKeyAlgorithm { + return ErrUnsupportedAlgorithm + } + if expectedAlg != pubKeyAlgo { + return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub) + } + if !scheme.Verify(pub, signed, signature, nil) { + return fmt.Errorf("x509: %s verification failed", scheme.Name()) + } + return } return ErrUnsupportedAlgorithm } @@ -1039,6 +1077,7 @@ var ( oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1} oidExtensionCRLNumber = []int{2, 5, 29, 20} oidExtensionReasonCode = []int{2, 5, 29, 21} + oidExtensionDelegatedCredential = []int{1, 3, 6, 1, 4, 1, 44363, 44} ) var ( @@ -1143,6 +1182,16 @@ func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKe n++ } + // This extension is not critical + if template.AllowDC && !template.IsCA && !oidInExtensions(oidExtensionDelegatedCredential, template.ExtraExtensions) && (template.KeyUsage&KeyUsageDigitalSignature != 0) { + ret[n].Id = oidExtensionDelegatedCredential + ret[n].Value, err = asn1.Marshal(asn1.NullRawValue) + if err != nil { + return + } + n++ + } + if len(authorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) { ret[n].Id = oidExtensionAuthorityKeyId ret[n].Value, err = asn1.Marshal(authKeyId{authorityKeyId}) @@ -1469,9 +1518,21 @@ func signingParamsForPublicKey(pub any, requestedSigAlgo SignatureAlgorithm) (ha case ed25519.PublicKey: pubType = Ed25519 sigAlgo.Algorithm = oidSignatureEd25519 - + case circlSign.PublicKey: + scheme := pub.Scheme() + certScheme, ok := scheme.(circlPki.CertificateScheme) + if !ok { + err = errors.New("x509: circl scheme is not CertificateScheme") + return + } + pubType = PublicKeyAlgorithmByCirclScheme(scheme) + if pubType == UnknownPublicKeyAlgorithm { + err = errors.New("x509: particular circl scheme not supported") + return + } + sigAlgo.Algorithm = certScheme.Oid() default: - err = errors.New("x509: only RSA, ECDSA and Ed25519 keys supported") + err = errors.New("x509: only RSA, ECDSA, Ed25519 and circl keys supported") } if err != nil { @@ -1490,7 +1551,8 @@ func signingParamsForPublicKey(pub any, requestedSigAlgo SignatureAlgorithm) (ha return } sigAlgo.Algorithm, hashFunc = details.oid, details.hash - if hashFunc == 0 && pubType != Ed25519 { + if hashFunc == 0 && (pubType != Ed25519 && + CirclSchemeByPublicKeyAlgorithm(pubType) == nil) { err = errors.New("x509: cannot sign with hash function requested") return } @@ -1520,6 +1582,7 @@ var emptyASN1Subject = []byte{0x30, 0} // CreateCertificate creates a new X.509 v3 certificate based on a template. // The following members of template are currently used: // +// - AllowDC // - AuthorityKeyId // - BasicConstraintsValid // - CRLDistributionPoints diff --git a/src/crypto/x509/x509_cf.go b/src/crypto/x509/x509_cf.go new file mode 100644 index 00000000000..43446318cb2 --- /dev/null +++ b/src/crypto/x509/x509_cf.go @@ -0,0 +1,74 @@ +package x509 + +import ( + "crypto" + "encoding/asn1" + + circlPki "github.com/cloudflare/circl/pki" + circlSign "github.com/cloudflare/circl/sign" + "github.com/cloudflare/circl/sign/eddilithium3" + "github.com/cloudflare/circl/sign/eddilithium2" +) + +// To add a signature scheme from Circl +// +// 1. make sure it implements CertificateScheme, +// 2. add SignatureAlgorithm and PublicKeyAlgorithm constants in x509.go +// 3. add row in circlSchemes below +// 4. update publicKeyAlgoName in x509.go + +var circlSchemes = [...]struct { + sga SignatureAlgorithm + alg PublicKeyAlgorithm + scheme circlSign.Scheme +}{ + {PureEdDilithium2, EdDilithium2, eddilithium2.Scheme()}, + {PureEdDilithium3, EdDilithium3, eddilithium3.Scheme()}, +} + +func CirclSchemeByPublicKeyAlgorithm(alg PublicKeyAlgorithm) circlSign.Scheme { + for _, cs := range circlSchemes { + if cs.alg == alg { + return cs.scheme + } + } + return nil +} + +func SignatureAlgorithmByCirclScheme(scheme circlSign.Scheme) SignatureAlgorithm { + for _, cs := range circlSchemes { + if cs.scheme == scheme { + return cs.sga + } + } + return UnknownSignatureAlgorithm +} + +func PublicKeyAlgorithmByCirclScheme(scheme circlSign.Scheme) PublicKeyAlgorithm { + for _, cs := range circlSchemes { + if cs.scheme == scheme { + return cs.alg + } + } + return UnknownPublicKeyAlgorithm +} + +func init() { + for _, cs := range circlSchemes { + signatureAlgorithmDetails = append(signatureAlgorithmDetails, + struct { + algo SignatureAlgorithm + name string + oid asn1.ObjectIdentifier + pubKeyAlgo PublicKeyAlgorithm + hash crypto.Hash + }{ + cs.sga, + cs.scheme.Name(), + cs.scheme.(circlPki.CertificateScheme).Oid(), + cs.alg, + crypto.Hash(0), + }, + ) + } +} diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 548b8d940e1..480f8dae4eb 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -627,6 +627,25 @@ func TestCreateSelfSignedCertificate(t *testing.T) { {"Ed25519", ed25519Pub, ed25519Priv, true, PureEd25519}, } + for _, cs := range circlSchemes { + pk, sk, err := cs.scheme.GenerateKey() + if err != nil { + t.Fatal() + } + tests = append(tests, struct { + name string + pub, priv interface{} + checkSig bool + sigAlgo SignatureAlgorithm + }{ + cs.scheme.Name(), + pk, + sk, + true, + cs.sga, + }) + } + testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth} testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}} extraExtensionData := []byte("extra extension") @@ -1951,6 +1970,48 @@ func TestISOOIDInCertificate(t *testing.T) { } } +const certIsDCOID = ` +-----BEGIN CERTIFICATE----- +MIIFRjCCBMugAwIBAgIQDGevB+lY0o/OecHFSJ6YnTAKBggqhkjOPQQDAzBMMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSYwJAYDVQQDEx1EaWdp +Q2VydCBFQ0MgU2VjdXJlIFNlcnZlciBDQTAeFw0xOTAzMjYwMDAwMDBaFw0yMTAz +MzAxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYw +FAYDVQQHEw1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBDbG91ZGZsYXJlLCBJbmMu +MRMwEQYDVQQDEwprYzJrZG0uY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +d4azI83Bw0fcPgfoeiZpZZnwGuxjBjv++wzE0zAj8vNiUkKxOWSQiGNLn+xlWUpL +lw9djRN1rLmVmn2gb9GgdKOCA28wggNrMB8GA1UdIwQYMBaAFKOd5h/52jlPwG7o +kcuVpdox4gqfMB0GA1UdDgQWBBSfcb7fS3fUFAyB91fRcwoDPtgtJjAjBgNVHREE +HDAaggprYzJrZG0uY29tggwqLmtjMmtkbS5jb20wDgYDVR0PAQH/BAQDAgeAMB0G +A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBpBgNVHR8EYjBgMC6gLKAqhiho +dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1lY2MtZzEuY3JsMC6gLKAqhiho +dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc3NjYS1lY2MtZzEuY3JsMEwGA1UdIARF +MEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2lj +ZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMHsGCCsGAQUFBwEBBG8wbTAkBggrBgEFBQcw +AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEUGCCsGAQUFBzAChjlodHRwOi8v +Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRFQ0NTZWN1cmVTZXJ2ZXJDQS5j +cnQwDAYDVR0TAQH/BAIwADAPBgkrBgEEAYLaSywEAgUAMIIBfgYKKwYBBAHWeQIE +AgSCAW4EggFqAWgAdgC72d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAA +AWm5hYJ5AAAEAwBHMEUCICiGfq+hSThRL2m8H0awoDR8OpnEHNkF0nI6nL5yYL/j +AiEAxwebGs/T6Es0YarPzoQJrVZqk+sHH/t+jrSrKd5TDjcAdgCHdb/nWXz4jEOZ +X73zbv9WjUdWNv9KtWDBtOr/XqCDDwAAAWm5hYNgAAAEAwBHMEUCIQD9OWA8KGL6 +bxDKfgIleHJWB0iWieRs88VgJyfAg/aFDgIgQ/OsdSF9XOy1foqge0DTDM2FExuw +0JR0AGZWXoNtJzMAdgBElGUusO7Or8RAB9io/ijA2uaCvtjLMbU/0zOWtbaBqAAA +AWm5hYHgAAAEAwBHMEUCIQC4vua1n3BqthEqpA/VBTcsNwMtAwpCuac2IhJ9wx6X +/AIgb+o00k28JQo9TMpP4vzJ3BD3HXWSNc2Zizbq7mkUQYMwCgYIKoZIzj0EAwMD +aQAwZgIxAJsX7d0SuA8ddf/m7IWfNfs3MQfJyGkEezMJX1t6sRso5z50SS12LpXe +muGa1FE2ZgIxAL+CDUF5pz7mhrAEIjQ1MqlpF9tH40dJGvYZZQ3W23cMzSkDfvlt +y5S4RfWHIIPjbw== +-----END CERTIFICATE-----` + +func TestIsDCOIDInCertificate(t *testing.T) { + block, _ := pem.Decode([]byte(certIsDCOID)) + if cert, err := ParseCertificate(block.Bytes); err != nil { + t.Errorf("certificate with DC OID failed to parse: %s", err) + } else if cert.SignatureAlgorithm == UnknownSignatureAlgorithm { + t.Errorf("DC OID not recognised in certificate") + } +} + // certMultipleRDN contains a RelativeDistinguishedName with two elements (the // common name and serial number). This particular certificate was the first // such certificate in the “Pilot” Certificate Transparency log. diff --git a/src/go.mod b/src/go.mod index 737d78da5d9..24f3d5946e0 100644 --- a/src/go.mod +++ b/src/go.mod @@ -3,6 +3,7 @@ module std go 1.22 require ( + github.com/cloudflare/circl v1.4.1-0.20240905130006-2d6cd9871f69 golang.org/x/crypto v0.16.1-0.20231129163542-152cdb1503eb golang.org/x/net v0.19.1-0.20240412193750-db050b07227e ) diff --git a/src/go.sum b/src/go.sum index 86d173c9e6f..4e86797268f 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,3 +1,5 @@ +github.com/cloudflare/circl v1.4.1-0.20240905130006-2d6cd9871f69 h1:AYiEIB+pGooAgRNMQtk3dCcp+D2x0UioEaKELFIxkx4= +github.com/cloudflare/circl v1.4.1-0.20240905130006-2d6cd9871f69/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= golang.org/x/crypto v0.16.1-0.20231129163542-152cdb1503eb h1:1ceSY7sk6sJuiDREHpfyrqDnDljsLfEP2GuTClhBBfI= golang.org/x/crypto v0.16.1-0.20231129163542-152cdb1503eb/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/net v0.19.1-0.20240412193750-db050b07227e h1:oDnvqaqHo3ho8OChMtkQbQAyp9eqnm3J7JRtt0+Cabc= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 7ce8d346b40..c4f877e3396 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -455,6 +455,9 @@ var depsRules = ` crypto/boring, crypto/internal/edwards25519/field < crypto/ecdh; + # Unfortunately, stuck with reflect via encoding/binary. + encoding/binary, crypto/boring < golang.org/x/crypto/sha3; + crypto/aes, crypto/des, crypto/ecdh, @@ -464,7 +467,8 @@ var depsRules = ` crypto/rc4, crypto/sha1, crypto/sha256, - crypto/sha512 + crypto/sha512, + golang.org/x/crypto/sha3 < CRYPTO; CGO, fmt, net !< CRYPTO; @@ -499,6 +503,11 @@ var depsRules = ` < crypto/x509 < crypto/tls; + # CIRCL + crypto, golang.org/x/sys/cpu, hash + < golang.org/x/crypto/blake2b + < golang.org/x/crypto/blake2s; + # crypto-aware packages DEBUG, go/build, go/types, text/scanner, crypto/md5 @@ -730,6 +739,11 @@ func TestDependencies(t *testing.T) { policy := depsPolicy(t) for _, pkg := range all { + // Skip import dependency checking within the CIRCL library, + // there are too many packages. + if strings.HasPrefix(pkg, "github.com/cloudflare/circl/") { + continue + } imports, err := findImports(pkg) if err != nil { t.Error(err) @@ -740,6 +754,11 @@ func TestDependencies(t *testing.T) { } var bad []string for _, imp := range imports { + // TODO Remove this exception for github.com/cloudflare/circl + // and add CIRCL to the dependency graph specified by `depsRules`. + if strings.HasPrefix(imp, "github.com/cloudflare/circl/") { + continue + } sawImport[pkg][imp] = true if !policy.HasEdge(pkg, imp) { bad = append(bad, imp) @@ -755,7 +774,7 @@ var buildIgnore = []byte("\n//go:build ignore") func findImports(pkg string) ([]string, error) { vpkg := pkg - if strings.HasPrefix(pkg, "golang.org") { + if strings.HasPrefix(pkg, "golang.org") || strings.HasPrefix(pkg, "github.com") { vpkg = "vendor/" + pkg } dir := filepath.Join(Default.GOROOT, "src", vpkg) diff --git a/src/internal/buildcfg/cfg.go b/src/internal/buildcfg/cfg.go index 8b97a653d77..8f0671dc4e3 100644 --- a/src/internal/buildcfg/cfg.go +++ b/src/internal/buildcfg/cfg.go @@ -209,6 +209,7 @@ func experimentTags() []string { for _, exp := range Experiment.Enabled() { list = append(list, "goexperiment."+exp) } + list = append(list, "cfgo") return list } diff --git a/src/vendor/github.com/cloudflare/circl/LICENSE b/src/vendor/github.com/cloudflare/circl/LICENSE new file mode 100644 index 00000000000..67edaa90a04 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/LICENSE @@ -0,0 +1,57 @@ +Copyright (c) 2019 Cloudflare. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Cloudflare nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +======================================================================== + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/curve.go b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve.go new file mode 100644 index 00000000000..f9057c2b866 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve.go @@ -0,0 +1,96 @@ +package x25519 + +import ( + fp "github.com/cloudflare/circl/math/fp25519" +) + +// ladderJoye calculates a fixed-point multiplication with the generator point. +// The algorithm is the right-to-left Joye's ladder as described +// in "How to precompute a ladder" in SAC'2017. +func ladderJoye(k *Key) { + w := [5]fp.Elt{} // [mu,x1,z1,x2,z2] order must be preserved. + fp.SetOne(&w[1]) // x1 = 1 + fp.SetOne(&w[2]) // z1 = 1 + w[3] = fp.Elt{ // x2 = G-S + 0xbd, 0xaa, 0x2f, 0xc8, 0xfe, 0xe1, 0x94, 0x7e, + 0xf8, 0xed, 0xb2, 0x14, 0xae, 0x95, 0xf0, 0xbb, + 0xe2, 0x48, 0x5d, 0x23, 0xb9, 0xa0, 0xc7, 0xad, + 0x34, 0xab, 0x7c, 0xe2, 0xee, 0xcd, 0xae, 0x1e, + } + fp.SetOne(&w[4]) // z2 = 1 + + const n = 255 + const h = 3 + swap := uint(1) + for s := 0; s < n-h; s++ { + i := (s + h) / 8 + j := (s + h) % 8 + bit := uint((k[i] >> uint(j)) & 1) + copy(w[0][:], tableGenerator[s*Size:(s+1)*Size]) + diffAdd(&w, swap^bit) + swap = bit + } + for s := 0; s < h; s++ { + double(&w[1], &w[2]) + } + toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) +} + +// ladderMontgomery calculates a generic scalar point multiplication +// The algorithm implemented is the left-to-right Montgomery's ladder. +func ladderMontgomery(k, xP *Key) { + w := [5]fp.Elt{} // [x1, x2, z2, x3, z3] order must be preserved. + w[0] = *(*fp.Elt)(xP) // x1 = xP + fp.SetOne(&w[1]) // x2 = 1 + w[3] = *(*fp.Elt)(xP) // x3 = xP + fp.SetOne(&w[4]) // z3 = 1 + + move := uint(0) + for s := 255 - 1; s >= 0; s-- { + i := s / 8 + j := s % 8 + bit := uint((k[i] >> uint(j)) & 1) + ladderStep(&w, move^bit) + move = bit + } + toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) +} + +func toAffine(k *[fp.Size]byte, x, z *fp.Elt) { + fp.Inv(z, z) + fp.Mul(x, x, z) + _ = fp.ToBytes(k[:], x) +} + +var lowOrderPoints = [5]fp.Elt{ + { /* (0,_,1) point of order 2 on Curve25519 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + { /* (1,_,1) point of order 4 on Curve25519 */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + { /* (x,_,1) first point of order 8 on Curve25519 */ + 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, + 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, + 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, + 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00, + }, + { /* (x,_,1) second point of order 8 on Curve25519 */ + 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, + 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, + 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, + 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57, + }, + { /* (-1,_,1) a point of order 4 on the twist of Curve25519 */ + 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + }, +} diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go new file mode 100644 index 00000000000..8a3d54c570f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go @@ -0,0 +1,30 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package x25519 + +import ( + fp "github.com/cloudflare/circl/math/fp25519" + "golang.org/x/sys/cpu" +) + +var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX + +var _ = hasBmi2Adx + +func double(x, z *fp.Elt) { doubleAmd64(x, z) } +func diffAdd(w *[5]fp.Elt, b uint) { diffAddAmd64(w, b) } +func ladderStep(w *[5]fp.Elt, b uint) { ladderStepAmd64(w, b) } +func mulA24(z, x *fp.Elt) { mulA24Amd64(z, x) } + +//go:noescape +func ladderStepAmd64(w *[5]fp.Elt, b uint) + +//go:noescape +func diffAddAmd64(w *[5]fp.Elt, b uint) + +//go:noescape +func doubleAmd64(x, z *fp.Elt) + +//go:noescape +func mulA24Amd64(z, x *fp.Elt) diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h new file mode 100644 index 00000000000..8c1ae4d0fbb --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h @@ -0,0 +1,111 @@ +#define ladderStepLeg \ + addSub(x2,z2) \ + addSub(x3,z3) \ + integerMulLeg(b0,x2,z3) \ + integerMulLeg(b1,x3,z2) \ + reduceFromDoubleLeg(t0,b0) \ + reduceFromDoubleLeg(t1,b1) \ + addSub(t0,t1) \ + cselect(x2,x3,regMove) \ + cselect(z2,z3,regMove) \ + integerSqrLeg(b0,t0) \ + integerSqrLeg(b1,t1) \ + reduceFromDoubleLeg(x3,b0) \ + reduceFromDoubleLeg(z3,b1) \ + integerMulLeg(b0,x1,z3) \ + reduceFromDoubleLeg(z3,b0) \ + integerSqrLeg(b0,x2) \ + integerSqrLeg(b1,z2) \ + reduceFromDoubleLeg(x2,b0) \ + reduceFromDoubleLeg(z2,b1) \ + subtraction(t0,x2,z2) \ + multiplyA24Leg(t1,t0) \ + additionLeg(t1,t1,z2) \ + integerMulLeg(b0,x2,z2) \ + integerMulLeg(b1,t0,t1) \ + reduceFromDoubleLeg(x2,b0) \ + reduceFromDoubleLeg(z2,b1) + +#define ladderStepBmi2Adx \ + addSub(x2,z2) \ + addSub(x3,z3) \ + integerMulAdx(b0,x2,z3) \ + integerMulAdx(b1,x3,z2) \ + reduceFromDoubleAdx(t0,b0) \ + reduceFromDoubleAdx(t1,b1) \ + addSub(t0,t1) \ + cselect(x2,x3,regMove) \ + cselect(z2,z3,regMove) \ + integerSqrAdx(b0,t0) \ + integerSqrAdx(b1,t1) \ + reduceFromDoubleAdx(x3,b0) \ + reduceFromDoubleAdx(z3,b1) \ + integerMulAdx(b0,x1,z3) \ + reduceFromDoubleAdx(z3,b0) \ + integerSqrAdx(b0,x2) \ + integerSqrAdx(b1,z2) \ + reduceFromDoubleAdx(x2,b0) \ + reduceFromDoubleAdx(z2,b1) \ + subtraction(t0,x2,z2) \ + multiplyA24Adx(t1,t0) \ + additionAdx(t1,t1,z2) \ + integerMulAdx(b0,x2,z2) \ + integerMulAdx(b1,t0,t1) \ + reduceFromDoubleAdx(x2,b0) \ + reduceFromDoubleAdx(z2,b1) + +#define difAddLeg \ + addSub(x1,z1) \ + integerMulLeg(b0,z1,ui) \ + reduceFromDoubleLeg(z1,b0) \ + addSub(x1,z1) \ + integerSqrLeg(b0,x1) \ + integerSqrLeg(b1,z1) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) \ + integerMulLeg(b0,x1,z2) \ + integerMulLeg(b1,z1,x2) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) + +#define difAddBmi2Adx \ + addSub(x1,z1) \ + integerMulAdx(b0,z1,ui) \ + reduceFromDoubleAdx(z1,b0) \ + addSub(x1,z1) \ + integerSqrAdx(b0,x1) \ + integerSqrAdx(b1,z1) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) \ + integerMulAdx(b0,x1,z2) \ + integerMulAdx(b1,z1,x2) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) + +#define doubleLeg \ + addSub(x1,z1) \ + integerSqrLeg(b0,x1) \ + integerSqrLeg(b1,z1) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) \ + subtraction(t0,x1,z1) \ + multiplyA24Leg(t1,t0) \ + additionLeg(t1,t1,z1) \ + integerMulLeg(b0,x1,z1) \ + integerMulLeg(b1,t0,t1) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) + +#define doubleBmi2Adx \ + addSub(x1,z1) \ + integerSqrAdx(b0,x1) \ + integerSqrAdx(b1,z1) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) \ + subtraction(t0,x1,z1) \ + multiplyA24Adx(t1,t0) \ + additionAdx(t1,t1,z1) \ + integerMulAdx(b0,x1,z1) \ + integerMulAdx(b1,t0,t1) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s new file mode 100644 index 00000000000..ce9f062894a --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s @@ -0,0 +1,157 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +#include "textflag.h" + +// Depends on circl/math/fp25519 package +#include "../../math/fp25519/fp_amd64.h" +#include "curve_amd64.h" + +// CTE_A24 is (A+2)/4 from Curve25519 +#define CTE_A24 121666 + +#define Size 32 + +// multiplyA24Leg multiplies x times CTE_A24 and stores in z +// Uses: AX, DX, R8-R13, FLAGS +// Instr: x86_64, cmov +#define multiplyA24Leg(z,x) \ + MOVL $CTE_A24, AX; MULQ 0+x; MOVQ AX, R8; MOVQ DX, R9; \ + MOVL $CTE_A24, AX; MULQ 8+x; MOVQ AX, R12; MOVQ DX, R10; \ + MOVL $CTE_A24, AX; MULQ 16+x; MOVQ AX, R13; MOVQ DX, R11; \ + MOVL $CTE_A24, AX; MULQ 24+x; \ + ADDQ R12, R9; \ + ADCQ R13, R10; \ + ADCQ AX, R11; \ + ADCQ $0, DX; \ + MOVL $38, AX; /* 2*C = 38 = 2^256 MOD 2^255-19*/ \ + IMULQ AX, DX; \ + ADDQ DX, R8; \ + ADCQ $0, R9; MOVQ R9, 8+z; \ + ADCQ $0, R10; MOVQ R10, 16+z; \ + ADCQ $0, R11; MOVQ R11, 24+z; \ + MOVQ $0, DX; \ + CMOVQCS AX, DX; \ + ADDQ DX, R8; MOVQ R8, 0+z; + +// multiplyA24Adx multiplies x times CTE_A24 and stores in z +// Uses: AX, DX, R8-R12, FLAGS +// Instr: x86_64, cmov, bmi2 +#define multiplyA24Adx(z,x) \ + MOVQ $CTE_A24, DX; \ + MULXQ 0+x, R8, R10; \ + MULXQ 8+x, R9, R11; ADDQ R10, R9; \ + MULXQ 16+x, R10, AX; ADCQ R11, R10; \ + MULXQ 24+x, R11, R12; ADCQ AX, R11; \ + ;;;;;;;;;;;;;;;;;;;;; ADCQ $0, R12; \ + MOVL $38, DX; /* 2*C = 38 = 2^256 MOD 2^255-19*/ \ + IMULQ DX, R12; \ + ADDQ R12, R8; \ + ADCQ $0, R9; MOVQ R9, 8+z; \ + ADCQ $0, R10; MOVQ R10, 16+z; \ + ADCQ $0, R11; MOVQ R11, 24+z; \ + MOVQ $0, R12; \ + CMOVQCS DX, R12; \ + ADDQ R12, R8; MOVQ R8, 0+z; + +#define mulA24Legacy \ + multiplyA24Leg(0(DI),0(SI)) +#define mulA24Bmi2Adx \ + multiplyA24Adx(0(DI),0(SI)) + +// func mulA24Amd64(z, x *fp255.Elt) +TEXT ·mulA24Amd64(SB),NOSPLIT,$0-16 + MOVQ z+0(FP), DI + MOVQ x+8(FP), SI + CHECK_BMI2ADX(LMA24, mulA24Legacy, mulA24Bmi2Adx) + + +// func ladderStepAmd64(w *[5]fp255.Elt, b uint) +// ladderStepAmd64 calculates a point addition and doubling as follows: +// (x2,z2) = 2*(x2,z2) and (x3,z3) = (x2,z2)+(x3,z3) using as a difference (x1,-). +// work = (x1,x2,z2,x3,z3) are five fp255.Elt of 32 bytes. +// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and +// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. +TEXT ·ladderStepAmd64(SB),NOSPLIT,$192-16 + // Parameters + #define regWork DI + #define regMove SI + #define x1 0*Size(regWork) + #define x2 1*Size(regWork) + #define z2 2*Size(regWork) + #define x3 3*Size(regWork) + #define z3 4*Size(regWork) + // Local variables + #define t0 0*Size(SP) + #define t1 1*Size(SP) + #define b0 2*Size(SP) + #define b1 4*Size(SP) + MOVQ w+0(FP), regWork + MOVQ b+8(FP), regMove + CHECK_BMI2ADX(LLADSTEP, ladderStepLeg, ladderStepBmi2Adx) + #undef regWork + #undef regMove + #undef x1 + #undef x2 + #undef z2 + #undef x3 + #undef z3 + #undef t0 + #undef t1 + #undef b0 + #undef b1 + +// func diffAddAmd64(w *[5]fp255.Elt, b uint) +// diffAddAmd64 calculates a differential point addition using a precomputed point. +// (x1,z1) = (x1,z1)+(mu) using a difference point (x2,z2) +// w = (mu,x1,z1,x2,z2) are five fp.Elt, and +// stack = (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. +TEXT ·diffAddAmd64(SB),NOSPLIT,$128-16 + // Parameters + #define regWork DI + #define regSwap SI + #define ui 0*Size(regWork) + #define x1 1*Size(regWork) + #define z1 2*Size(regWork) + #define x2 3*Size(regWork) + #define z2 4*Size(regWork) + // Local variables + #define b0 0*Size(SP) + #define b1 2*Size(SP) + MOVQ w+0(FP), regWork + MOVQ b+8(FP), regSwap + cswap(x1,x2,regSwap) + cswap(z1,z2,regSwap) + CHECK_BMI2ADX(LDIFADD, difAddLeg, difAddBmi2Adx) + #undef regWork + #undef regSwap + #undef ui + #undef x1 + #undef z1 + #undef x2 + #undef z2 + #undef b0 + #undef b1 + +// func doubleAmd64(x, z *fp255.Elt) +// doubleAmd64 calculates a point doubling (x1,z1) = 2*(x1,z1). +// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and +// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. +TEXT ·doubleAmd64(SB),NOSPLIT,$192-16 + // Parameters + #define x1 0(DI) + #define z1 0(SI) + // Local variables + #define t0 0*Size(SP) + #define t1 1*Size(SP) + #define b0 2*Size(SP) + #define b1 4*Size(SP) + MOVQ x+0(FP), DI + MOVQ z+8(FP), SI + CHECK_BMI2ADX(LDOUB,doubleLeg,doubleBmi2Adx) + #undef x1 + #undef z1 + #undef t0 + #undef t1 + #undef b0 + #undef b1 diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go new file mode 100644 index 00000000000..dae67ea37df --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go @@ -0,0 +1,85 @@ +package x25519 + +import ( + "encoding/binary" + "math/bits" + + fp "github.com/cloudflare/circl/math/fp25519" +) + +func doubleGeneric(x, z *fp.Elt) { + t0, t1 := &fp.Elt{}, &fp.Elt{} + fp.AddSub(x, z) + fp.Sqr(x, x) + fp.Sqr(z, z) + fp.Sub(t0, x, z) + mulA24Generic(t1, t0) + fp.Add(t1, t1, z) + fp.Mul(x, x, z) + fp.Mul(z, t0, t1) +} + +func diffAddGeneric(w *[5]fp.Elt, b uint) { + mu, x1, z1, x2, z2 := &w[0], &w[1], &w[2], &w[3], &w[4] + fp.Cswap(x1, x2, b) + fp.Cswap(z1, z2, b) + fp.AddSub(x1, z1) + fp.Mul(z1, z1, mu) + fp.AddSub(x1, z1) + fp.Sqr(x1, x1) + fp.Sqr(z1, z1) + fp.Mul(x1, x1, z2) + fp.Mul(z1, z1, x2) +} + +func ladderStepGeneric(w *[5]fp.Elt, b uint) { + x1, x2, z2, x3, z3 := &w[0], &w[1], &w[2], &w[3], &w[4] + t0 := &fp.Elt{} + t1 := &fp.Elt{} + fp.AddSub(x2, z2) + fp.AddSub(x3, z3) + fp.Mul(t0, x2, z3) + fp.Mul(t1, x3, z2) + fp.AddSub(t0, t1) + fp.Cmov(x2, x3, b) + fp.Cmov(z2, z3, b) + fp.Sqr(x3, t0) + fp.Sqr(z3, t1) + fp.Mul(z3, x1, z3) + fp.Sqr(x2, x2) + fp.Sqr(z2, z2) + fp.Sub(t0, x2, z2) + mulA24Generic(t1, t0) + fp.Add(t1, t1, z2) + fp.Mul(x2, x2, z2) + fp.Mul(z2, t0, t1) +} + +func mulA24Generic(z, x *fp.Elt) { + const A24 = 121666 + const n = 8 + var xx [4]uint64 + for i := range xx { + xx[i] = binary.LittleEndian.Uint64(x[i*n : (i+1)*n]) + } + + h0, l0 := bits.Mul64(xx[0], A24) + h1, l1 := bits.Mul64(xx[1], A24) + h2, l2 := bits.Mul64(xx[2], A24) + h3, l3 := bits.Mul64(xx[3], A24) + + var c3 uint64 + l1, c0 := bits.Add64(h0, l1, 0) + l2, c1 := bits.Add64(h1, l2, c0) + l3, c2 := bits.Add64(h2, l3, c1) + l4, _ := bits.Add64(h3, 0, c2) + _, l4 = bits.Mul64(l4, 38) + l0, c0 = bits.Add64(l0, l4, 0) + xx[1], c1 = bits.Add64(l1, 0, c0) + xx[2], c2 = bits.Add64(l2, 0, c1) + xx[3], c3 = bits.Add64(l3, 0, c2) + xx[0], _ = bits.Add64(l0, (-c3)&38, 0) + for i := range xx { + binary.LittleEndian.PutUint64(z[i*n:(i+1)*n], xx[i]) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go new file mode 100644 index 00000000000..07fab97d2af --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go @@ -0,0 +1,11 @@ +//go:build !amd64 || purego +// +build !amd64 purego + +package x25519 + +import fp "github.com/cloudflare/circl/math/fp25519" + +func double(x, z *fp.Elt) { doubleGeneric(x, z) } +func diffAdd(w *[5]fp.Elt, b uint) { diffAddGeneric(w, b) } +func ladderStep(w *[5]fp.Elt, b uint) { ladderStepGeneric(w, b) } +func mulA24(z, x *fp.Elt) { mulA24Generic(z, x) } diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/doc.go b/src/vendor/github.com/cloudflare/circl/dh/x25519/doc.go new file mode 100644 index 00000000000..3ce102d1457 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/doc.go @@ -0,0 +1,19 @@ +/* +Package x25519 provides Diffie-Hellman functions as specified in RFC-7748. + +Validation of public keys. + +The Diffie-Hellman function, as described in RFC-7748 [1], works for any +public key. However, if a different protocol requires contributory +behaviour [2,3], then the public keys must be validated against low-order +points [3,4]. To do that, the Shared function performs this validation +internally and returns false when the public key is invalid (i.e., it +is a low-order point). + +References: + - [1] RFC7748 by Langley, Hamburg, Turner (https://rfc-editor.org/rfc/rfc7748.txt) + - [2] Curve25519 by Bernstein (https://cr.yp.to/ecdh.html) + - [3] Bernstein (https://cr.yp.to/ecdh.html#validate) + - [4] Cremers&Jackson (https://eprint.iacr.org/2019/526) +*/ +package x25519 diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/key.go b/src/vendor/github.com/cloudflare/circl/dh/x25519/key.go new file mode 100644 index 00000000000..c76f72ac7fa --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/key.go @@ -0,0 +1,47 @@ +package x25519 + +import ( + "crypto/subtle" + + fp "github.com/cloudflare/circl/math/fp25519" +) + +// Size is the length in bytes of a X25519 key. +const Size = 32 + +// Key represents a X25519 key. +type Key [Size]byte + +func (k *Key) clamp(in *Key) *Key { + *k = *in + k[0] &= 248 + k[31] = (k[31] & 127) | 64 + return k +} + +// isValidPubKey verifies if the public key is not a low-order point. +func (k *Key) isValidPubKey() bool { + fp.Modp((*fp.Elt)(k)) + var isLowOrder int + for _, P := range lowOrderPoints { + isLowOrder |= subtle.ConstantTimeCompare(P[:], k[:]) + } + return isLowOrder == 0 +} + +// KeyGen obtains a public key given a secret key. +func KeyGen(public, secret *Key) { + ladderJoye(public.clamp(secret)) +} + +// Shared calculates Alice's shared key from Alice's secret key and Bob's +// public key returning true on success. A failure case happens when the public +// key is a low-order point, thus the shared key is all-zeros and the function +// returns false. +func Shared(shared, secret, public *Key) bool { + validPk := *public + validPk[31] &= (1 << (255 % 8)) - 1 + ok := validPk.isValidPubKey() + ladderMontgomery(shared.clamp(secret), &validPk) + return ok +} diff --git a/src/vendor/github.com/cloudflare/circl/dh/x25519/table.go b/src/vendor/github.com/cloudflare/circl/dh/x25519/table.go new file mode 100644 index 00000000000..28c8c4ac032 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/table.go @@ -0,0 +1,268 @@ +package x25519 + +import "github.com/cloudflare/circl/math/fp25519" + +// tableGenerator contains the set of points: +// +// t[i] = (xi+1)/(xi-1), +// +// where (xi,yi) = 2^iG and G is the generator point +// Size = (256)*(256/8) = 8192 bytes. +var tableGenerator = [256 * fp25519.Size]byte{ + /* (2^ 0)P */ 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, + /* (2^ 1)P */ 0x96, 0xfe, 0xaa, 0x16, 0xf4, 0x20, 0x82, 0x6b, 0x34, 0x6a, 0x56, 0x4f, 0x2b, 0xeb, 0xeb, 0x82, 0x0f, 0x95, 0xa5, 0x75, 0xb0, 0xa5, 0xa9, 0xd5, 0xf4, 0x88, 0x24, 0x4b, 0xcf, 0xb2, 0x42, 0x51, + /* (2^ 2)P */ 0x0c, 0x68, 0x69, 0x00, 0x75, 0xbc, 0xae, 0x6a, 0x41, 0x9c, 0xf9, 0xa0, 0x20, 0x78, 0xcf, 0x89, 0xf4, 0xd0, 0x56, 0x3b, 0x18, 0xd9, 0x58, 0x2a, 0xa4, 0x11, 0x60, 0xe3, 0x80, 0xca, 0x5a, 0x4b, + /* (2^ 3)P */ 0x5d, 0x74, 0x29, 0x8c, 0x34, 0x32, 0x91, 0x32, 0xd7, 0x2f, 0x64, 0xe1, 0x16, 0xe6, 0xa2, 0xf4, 0x34, 0xbc, 0x67, 0xff, 0x03, 0xbb, 0x45, 0x1e, 0x4a, 0x9b, 0x2a, 0xf4, 0xd0, 0x12, 0x69, 0x30, + /* (2^ 4)P */ 0x54, 0x71, 0xaf, 0xe6, 0x07, 0x65, 0x88, 0xff, 0x2f, 0xc8, 0xee, 0xdf, 0x13, 0x0e, 0xf5, 0x04, 0xce, 0xb5, 0xba, 0x2a, 0xe8, 0x2f, 0x51, 0xaa, 0x22, 0xf2, 0xd5, 0x68, 0x1a, 0x25, 0x4e, 0x17, + /* (2^ 5)P */ 0x98, 0x88, 0x02, 0x82, 0x0d, 0x70, 0x96, 0xcf, 0xc5, 0x02, 0x2c, 0x0a, 0x37, 0xe3, 0x43, 0x17, 0xaa, 0x6e, 0xe8, 0xb4, 0x98, 0xec, 0x9e, 0x37, 0x2e, 0x48, 0xe0, 0x51, 0x8a, 0x88, 0x59, 0x0c, + /* (2^ 6)P */ 0x89, 0xd1, 0xb5, 0x99, 0xd6, 0xf1, 0xcb, 0xfb, 0x84, 0xdc, 0x9f, 0x8e, 0xd5, 0xf0, 0xae, 0xac, 0x14, 0x76, 0x1f, 0x23, 0x06, 0x0d, 0xc2, 0xc1, 0x72, 0xf9, 0x74, 0xa2, 0x8d, 0x21, 0x38, 0x29, + /* (2^ 7)P */ 0x18, 0x7f, 0x1d, 0xff, 0xbe, 0x49, 0xaf, 0xf6, 0xc2, 0xc9, 0x7a, 0x38, 0x22, 0x1c, 0x54, 0xcc, 0x6b, 0xc5, 0x15, 0x40, 0xef, 0xc9, 0xfc, 0x96, 0xa9, 0x13, 0x09, 0x69, 0x7c, 0x62, 0xc1, 0x69, + /* (2^ 8)P */ 0x0e, 0xdb, 0x33, 0x47, 0x2f, 0xfd, 0x86, 0x7a, 0xe9, 0x7d, 0x08, 0x9e, 0xf2, 0xc4, 0xb8, 0xfd, 0x29, 0xa2, 0xa2, 0x8e, 0x1a, 0x4b, 0x5e, 0x09, 0x79, 0x7a, 0xb3, 0x29, 0xc8, 0xa7, 0xd7, 0x1a, + /* (2^ 9)P */ 0xc0, 0xa0, 0x7e, 0xd1, 0xca, 0x89, 0x2d, 0x34, 0x51, 0x20, 0xed, 0xcc, 0xa6, 0xdd, 0xbe, 0x67, 0x74, 0x2f, 0xb4, 0x2b, 0xbf, 0x31, 0xca, 0x19, 0xbb, 0xac, 0x80, 0x49, 0xc8, 0xb4, 0xf7, 0x3d, + /* (2^ 10)P */ 0x83, 0xd8, 0x0a, 0xc8, 0x4d, 0x44, 0xc6, 0xa8, 0x85, 0xab, 0xe3, 0x66, 0x03, 0x44, 0x1e, 0xb9, 0xd8, 0xf6, 0x64, 0x01, 0xa0, 0xcd, 0x15, 0xc2, 0x68, 0xe6, 0x47, 0xf2, 0x6e, 0x7c, 0x86, 0x3d, + /* (2^ 11)P */ 0x8c, 0x65, 0x3e, 0xcc, 0x2b, 0x58, 0xdd, 0xc7, 0x28, 0x55, 0x0e, 0xee, 0x48, 0x47, 0x2c, 0xfd, 0x71, 0x4f, 0x9f, 0xcc, 0x95, 0x9b, 0xfd, 0xa0, 0xdf, 0x5d, 0x67, 0xb0, 0x71, 0xd8, 0x29, 0x75, + /* (2^ 12)P */ 0x78, 0xbd, 0x3c, 0x2d, 0xb4, 0x68, 0xf5, 0xb8, 0x82, 0xda, 0xf3, 0x91, 0x1b, 0x01, 0x33, 0x12, 0x62, 0x3b, 0x7c, 0x4a, 0xcd, 0x6c, 0xce, 0x2d, 0x03, 0x86, 0x49, 0x9e, 0x8e, 0xfc, 0xe7, 0x75, + /* (2^ 13)P */ 0xec, 0xb6, 0xd0, 0xfc, 0xf1, 0x13, 0x4f, 0x2f, 0x45, 0x7a, 0xff, 0x29, 0x1f, 0xca, 0xa8, 0xf1, 0x9b, 0xe2, 0x81, 0x29, 0xa7, 0xc1, 0x49, 0xc2, 0x6a, 0xb5, 0x83, 0x8c, 0xbb, 0x0d, 0xbe, 0x6e, + /* (2^ 14)P */ 0x22, 0xb2, 0x0b, 0x17, 0x8d, 0xfa, 0x14, 0x71, 0x5f, 0x93, 0x93, 0xbf, 0xd5, 0xdc, 0xa2, 0x65, 0x9a, 0x97, 0x9c, 0xb5, 0x68, 0x1f, 0xc4, 0xbd, 0x89, 0x92, 0xce, 0xa2, 0x79, 0xef, 0x0e, 0x2f, + /* (2^ 15)P */ 0xce, 0x37, 0x3c, 0x08, 0x0c, 0xbf, 0xec, 0x42, 0x22, 0x63, 0x49, 0xec, 0x09, 0xbc, 0x30, 0x29, 0x0d, 0xac, 0xfe, 0x9c, 0xc1, 0xb0, 0x94, 0xf2, 0x80, 0xbb, 0xfa, 0xed, 0x4b, 0xaa, 0x80, 0x37, + /* (2^ 16)P */ 0x29, 0xd9, 0xea, 0x7c, 0x3e, 0x7d, 0xc1, 0x56, 0xc5, 0x22, 0x57, 0x2e, 0xeb, 0x4b, 0xcb, 0xe7, 0x5a, 0xe1, 0xbf, 0x2d, 0x73, 0x31, 0xe9, 0x0c, 0xf8, 0x52, 0x10, 0x62, 0xc7, 0x83, 0xb8, 0x41, + /* (2^ 17)P */ 0x50, 0x53, 0xd2, 0xc3, 0xa0, 0x5c, 0xf7, 0xdb, 0x51, 0xe3, 0xb1, 0x6e, 0x08, 0xbe, 0x36, 0x29, 0x12, 0xb2, 0xa9, 0xb4, 0x3c, 0xe0, 0x36, 0xc9, 0xaa, 0x25, 0x22, 0x32, 0x82, 0xbf, 0x45, 0x1d, + /* (2^ 18)P */ 0xc5, 0x4c, 0x02, 0x6a, 0x03, 0xb1, 0x1a, 0xe8, 0x72, 0x9a, 0x4c, 0x30, 0x1c, 0x20, 0x12, 0xe2, 0xfc, 0xb1, 0x32, 0x68, 0xba, 0x3f, 0xd7, 0xc5, 0x81, 0x95, 0x83, 0x4d, 0x5a, 0xdb, 0xff, 0x20, + /* (2^ 19)P */ 0xad, 0x0f, 0x5d, 0xbe, 0x67, 0xd3, 0x83, 0xa2, 0x75, 0x44, 0x16, 0x8b, 0xca, 0x25, 0x2b, 0x6c, 0x2e, 0xf2, 0xaa, 0x7c, 0x46, 0x35, 0x49, 0x9d, 0x49, 0xff, 0x85, 0xee, 0x8e, 0x40, 0x66, 0x51, + /* (2^ 20)P */ 0x61, 0xe3, 0xb4, 0xfa, 0xa2, 0xba, 0x67, 0x3c, 0xef, 0x5c, 0xf3, 0x7e, 0xc6, 0x33, 0xe4, 0xb3, 0x1c, 0x9b, 0x15, 0x41, 0x92, 0x72, 0x59, 0x52, 0x33, 0xab, 0xb0, 0xd5, 0x92, 0x18, 0x62, 0x6a, + /* (2^ 21)P */ 0xcb, 0xcd, 0x55, 0x75, 0x38, 0x4a, 0xb7, 0x20, 0x3f, 0x92, 0x08, 0x12, 0x0e, 0xa1, 0x2a, 0x53, 0xd1, 0x1d, 0x28, 0x62, 0x77, 0x7b, 0xa1, 0xea, 0xbf, 0x44, 0x5c, 0xf0, 0x43, 0x34, 0xab, 0x61, + /* (2^ 22)P */ 0xf8, 0xde, 0x24, 0x23, 0x42, 0x6c, 0x7a, 0x25, 0x7f, 0xcf, 0xe3, 0x17, 0x10, 0x6c, 0x1c, 0x13, 0x57, 0xa2, 0x30, 0xf6, 0x39, 0x87, 0x75, 0x23, 0x80, 0x85, 0xa7, 0x01, 0x7a, 0x40, 0x5a, 0x29, + /* (2^ 23)P */ 0xd9, 0xa8, 0x5d, 0x6d, 0x24, 0x43, 0xc4, 0xf8, 0x5d, 0xfa, 0x52, 0x0c, 0x45, 0x75, 0xd7, 0x19, 0x3d, 0xf8, 0x1b, 0x73, 0x92, 0xfc, 0xfc, 0x2a, 0x00, 0x47, 0x2b, 0x1b, 0xe8, 0xc8, 0x10, 0x7d, + /* (2^ 24)P */ 0x0b, 0xa2, 0xba, 0x70, 0x1f, 0x27, 0xe0, 0xc8, 0x57, 0x39, 0xa6, 0x7c, 0x86, 0x48, 0x37, 0x99, 0xbb, 0xd4, 0x7e, 0xcb, 0xb3, 0xef, 0x12, 0x54, 0x75, 0x29, 0xe6, 0x73, 0x61, 0xd3, 0x96, 0x31, + /* (2^ 25)P */ 0xfc, 0xdf, 0xc7, 0x41, 0xd1, 0xca, 0x5b, 0xde, 0x48, 0xc8, 0x95, 0xb3, 0xd2, 0x8c, 0xcc, 0x47, 0xcb, 0xf3, 0x1a, 0xe1, 0x42, 0xd9, 0x4c, 0xa3, 0xc2, 0xce, 0x4e, 0xd0, 0xf2, 0xdb, 0x56, 0x02, + /* (2^ 26)P */ 0x7f, 0x66, 0x0e, 0x4b, 0xe9, 0xb7, 0x5a, 0x87, 0x10, 0x0d, 0x85, 0xc0, 0x83, 0xdd, 0xd4, 0xca, 0x9f, 0xc7, 0x72, 0x4e, 0x8f, 0x2e, 0xf1, 0x47, 0x9b, 0xb1, 0x85, 0x8c, 0xbb, 0x87, 0x1a, 0x5f, + /* (2^ 27)P */ 0xb8, 0x51, 0x7f, 0x43, 0xb6, 0xd0, 0xe9, 0x7a, 0x65, 0x90, 0x87, 0x18, 0x55, 0xce, 0xc7, 0x12, 0xee, 0x7a, 0xf7, 0x5c, 0xfe, 0x09, 0xde, 0x2a, 0x27, 0x56, 0x2c, 0x7d, 0x2f, 0x5a, 0xa0, 0x23, + /* (2^ 28)P */ 0x9a, 0x16, 0x7c, 0xf1, 0x28, 0xe1, 0x08, 0x59, 0x2d, 0x85, 0xd0, 0x8a, 0xdd, 0x98, 0x74, 0xf7, 0x64, 0x2f, 0x10, 0xab, 0xce, 0xc4, 0xb4, 0x74, 0x45, 0x98, 0x13, 0x10, 0xdd, 0xba, 0x3a, 0x18, + /* (2^ 29)P */ 0xac, 0xaa, 0x92, 0xaa, 0x8d, 0xba, 0x65, 0xb1, 0x05, 0x67, 0x38, 0x99, 0x95, 0xef, 0xc5, 0xd5, 0xd1, 0x40, 0xfc, 0xf8, 0x0c, 0x8f, 0x2f, 0xbe, 0x14, 0x45, 0x20, 0xee, 0x35, 0xe6, 0x01, 0x27, + /* (2^ 30)P */ 0x14, 0x65, 0x15, 0x20, 0x00, 0xa8, 0x9f, 0x62, 0xce, 0xc1, 0xa8, 0x64, 0x87, 0x86, 0x23, 0xf2, 0x0e, 0x06, 0x3f, 0x0b, 0xff, 0x4f, 0x89, 0x5b, 0xfa, 0xa3, 0x08, 0xf7, 0x4c, 0x94, 0xd9, 0x60, + /* (2^ 31)P */ 0x1f, 0x20, 0x7a, 0x1c, 0x1a, 0x00, 0xea, 0xae, 0x63, 0xce, 0xe2, 0x3e, 0x63, 0x6a, 0xf1, 0xeb, 0xe1, 0x07, 0x7a, 0x4c, 0x59, 0x09, 0x77, 0x6f, 0xcb, 0x08, 0x02, 0x0d, 0x15, 0x58, 0xb9, 0x79, + /* (2^ 32)P */ 0xe7, 0x10, 0xd4, 0x01, 0x53, 0x5e, 0xb5, 0x24, 0x4d, 0xc8, 0xfd, 0xf3, 0xdf, 0x4e, 0xa3, 0xe3, 0xd8, 0x32, 0x40, 0x90, 0xe4, 0x68, 0x87, 0xd8, 0xec, 0xae, 0x3a, 0x7b, 0x42, 0x84, 0x13, 0x13, + /* (2^ 33)P */ 0x14, 0x4f, 0x23, 0x86, 0x12, 0xe5, 0x05, 0x84, 0x29, 0xc5, 0xb4, 0xad, 0x39, 0x47, 0xdc, 0x14, 0xfd, 0x4f, 0x63, 0x50, 0xb2, 0xb5, 0xa2, 0xb8, 0x93, 0xff, 0xa7, 0xd8, 0x4a, 0xa9, 0xe2, 0x2f, + /* (2^ 34)P */ 0xdd, 0xfa, 0x43, 0xe8, 0xef, 0x57, 0x5c, 0xec, 0x18, 0x99, 0xbb, 0xf0, 0x40, 0xce, 0x43, 0x28, 0x05, 0x63, 0x3d, 0xcf, 0xd6, 0x61, 0xb5, 0xa4, 0x7e, 0x77, 0xfb, 0xe8, 0xbd, 0x29, 0x36, 0x74, + /* (2^ 35)P */ 0x8f, 0x73, 0xaf, 0xbb, 0x46, 0xdd, 0x3e, 0x34, 0x51, 0xa6, 0x01, 0xb1, 0x28, 0x18, 0x98, 0xed, 0x7a, 0x79, 0x2c, 0x88, 0x0b, 0x76, 0x01, 0xa4, 0x30, 0x87, 0xc8, 0x8d, 0xe2, 0x23, 0xc2, 0x1f, + /* (2^ 36)P */ 0x0e, 0xba, 0x0f, 0xfc, 0x91, 0x4e, 0x60, 0x48, 0xa4, 0x6f, 0x2c, 0x05, 0x8f, 0xf7, 0x37, 0xb6, 0x9c, 0x23, 0xe9, 0x09, 0x3d, 0xac, 0xcc, 0x91, 0x7c, 0x68, 0x7a, 0x43, 0xd4, 0xee, 0xf7, 0x23, + /* (2^ 37)P */ 0x00, 0xd8, 0x9b, 0x8d, 0x11, 0xb1, 0x73, 0x51, 0xa7, 0xd4, 0x89, 0x31, 0xb6, 0x41, 0xd6, 0x29, 0x86, 0xc5, 0xbb, 0x88, 0x79, 0x17, 0xbf, 0xfd, 0xf5, 0x1d, 0xd8, 0xca, 0x4f, 0x89, 0x59, 0x29, + /* (2^ 38)P */ 0x99, 0xc8, 0xbb, 0xb4, 0xf3, 0x8e, 0xbc, 0xae, 0xb9, 0x92, 0x69, 0xb2, 0x5a, 0x99, 0x48, 0x41, 0xfb, 0x2c, 0xf9, 0x34, 0x01, 0x0b, 0xe2, 0x24, 0xe8, 0xde, 0x05, 0x4a, 0x89, 0x58, 0xd1, 0x40, + /* (2^ 39)P */ 0xf6, 0x76, 0xaf, 0x85, 0x11, 0x0b, 0xb0, 0x46, 0x79, 0x7a, 0x18, 0x73, 0x78, 0xc7, 0xba, 0x26, 0x5f, 0xff, 0x8f, 0xab, 0x95, 0xbf, 0xc0, 0x3d, 0xd7, 0x24, 0x55, 0x94, 0xd8, 0x8b, 0x60, 0x2a, + /* (2^ 40)P */ 0x02, 0x63, 0x44, 0xbd, 0x88, 0x95, 0x44, 0x26, 0x9c, 0x43, 0x88, 0x03, 0x1c, 0xc2, 0x4b, 0x7c, 0xb2, 0x11, 0xbd, 0x83, 0xf3, 0xa4, 0x98, 0x8e, 0xb9, 0x76, 0xd8, 0xc9, 0x7b, 0x8d, 0x21, 0x26, + /* (2^ 41)P */ 0x8a, 0x17, 0x7c, 0x99, 0x42, 0x15, 0x08, 0xe3, 0x6f, 0x60, 0xb6, 0x6f, 0xa8, 0x29, 0x2d, 0x3c, 0x74, 0x93, 0x27, 0xfa, 0x36, 0x77, 0x21, 0x5c, 0xfa, 0xb1, 0xfe, 0x4a, 0x73, 0x05, 0xde, 0x7d, + /* (2^ 42)P */ 0xab, 0x2b, 0xd4, 0x06, 0x39, 0x0e, 0xf1, 0x3b, 0x9c, 0x64, 0x80, 0x19, 0x3e, 0x80, 0xf7, 0xe4, 0x7a, 0xbf, 0x95, 0x95, 0xf8, 0x3b, 0x05, 0xe6, 0x30, 0x55, 0x24, 0xda, 0x38, 0xaf, 0x4f, 0x39, + /* (2^ 43)P */ 0xf4, 0x28, 0x69, 0x89, 0x58, 0xfb, 0x8e, 0x7a, 0x3c, 0x11, 0x6a, 0xcc, 0xe9, 0x78, 0xc7, 0xfb, 0x6f, 0x59, 0xaf, 0x30, 0xe3, 0x0c, 0x67, 0x72, 0xf7, 0x6c, 0x3d, 0x1d, 0xa8, 0x22, 0xf2, 0x48, + /* (2^ 44)P */ 0xa7, 0xca, 0x72, 0x0d, 0x41, 0xce, 0x1f, 0xf0, 0x95, 0x55, 0x3b, 0x21, 0xc7, 0xec, 0x20, 0x5a, 0x83, 0x14, 0xfa, 0xc1, 0x65, 0x11, 0xc2, 0x7b, 0x41, 0xa7, 0xa8, 0x1d, 0xe3, 0x9a, 0xf8, 0x07, + /* (2^ 45)P */ 0xf9, 0x0f, 0x83, 0xc6, 0xb4, 0xc2, 0xd2, 0x05, 0x93, 0x62, 0x31, 0xc6, 0x0f, 0x33, 0x3e, 0xd4, 0x04, 0xa9, 0xd3, 0x96, 0x0a, 0x59, 0xa5, 0xa5, 0xb6, 0x33, 0x53, 0xa6, 0x91, 0xdb, 0x5e, 0x70, + /* (2^ 46)P */ 0xf7, 0xa5, 0xb9, 0x0b, 0x5e, 0xe1, 0x8e, 0x04, 0x5d, 0xaf, 0x0a, 0x9e, 0xca, 0xcf, 0x40, 0x32, 0x0b, 0xa4, 0xc4, 0xed, 0xce, 0x71, 0x4b, 0x8f, 0x6d, 0x4a, 0x54, 0xde, 0xa3, 0x0d, 0x1c, 0x62, + /* (2^ 47)P */ 0x91, 0x40, 0x8c, 0xa0, 0x36, 0x28, 0x87, 0x92, 0x45, 0x14, 0xc9, 0x10, 0xb0, 0x75, 0x83, 0xce, 0x94, 0x63, 0x27, 0x4f, 0x52, 0xeb, 0x72, 0x8a, 0x35, 0x36, 0xc8, 0x7e, 0xfa, 0xfc, 0x67, 0x26, + /* (2^ 48)P */ 0x2a, 0x75, 0xe8, 0x45, 0x33, 0x17, 0x4c, 0x7f, 0xa5, 0x79, 0x70, 0xee, 0xfe, 0x47, 0x1b, 0x06, 0x34, 0xff, 0x86, 0x9f, 0xfa, 0x9a, 0xdd, 0x25, 0x9c, 0xc8, 0x5d, 0x42, 0xf5, 0xce, 0x80, 0x37, + /* (2^ 49)P */ 0xe9, 0xb4, 0x3b, 0x51, 0x5a, 0x03, 0x46, 0x1a, 0xda, 0x5a, 0x57, 0xac, 0x79, 0xf3, 0x1e, 0x3e, 0x50, 0x4b, 0xa2, 0x5f, 0x1c, 0x5f, 0x8c, 0xc7, 0x22, 0x9f, 0xfd, 0x34, 0x76, 0x96, 0x1a, 0x32, + /* (2^ 50)P */ 0xfa, 0x27, 0x6e, 0x82, 0xb8, 0x07, 0x67, 0x94, 0xd0, 0x6f, 0x50, 0x4c, 0xd6, 0x84, 0xca, 0x3d, 0x36, 0x14, 0xe9, 0x75, 0x80, 0x21, 0x89, 0xc1, 0x84, 0x84, 0x3b, 0x9b, 0x16, 0x84, 0x92, 0x6d, + /* (2^ 51)P */ 0xdf, 0x2d, 0x3f, 0x38, 0x40, 0xe8, 0x67, 0x3a, 0x75, 0x9b, 0x4f, 0x0c, 0xa3, 0xc9, 0xee, 0x33, 0x47, 0xef, 0x83, 0xa7, 0x6f, 0xc8, 0xc7, 0x3e, 0xc4, 0xfb, 0xc9, 0xba, 0x9f, 0x44, 0xec, 0x26, + /* (2^ 52)P */ 0x7d, 0x9e, 0x9b, 0xa0, 0xcb, 0x38, 0x0f, 0x5c, 0x8c, 0x47, 0xa3, 0x62, 0xc7, 0x8c, 0x16, 0x81, 0x1c, 0x12, 0xfc, 0x06, 0xd3, 0xb0, 0x23, 0x3e, 0xdd, 0xdc, 0xef, 0xa5, 0xa0, 0x8a, 0x23, 0x5a, + /* (2^ 53)P */ 0xff, 0x43, 0xea, 0xc4, 0x21, 0x61, 0xa2, 0x1b, 0xb5, 0x32, 0x88, 0x7c, 0x7f, 0xc7, 0xf8, 0x36, 0x9a, 0xf9, 0xdc, 0x0a, 0x0b, 0xea, 0xfb, 0x88, 0xf9, 0xeb, 0x5b, 0xc2, 0x8e, 0x93, 0xa9, 0x5c, + /* (2^ 54)P */ 0xa0, 0xcd, 0xfc, 0x51, 0x5e, 0x6a, 0x43, 0xd5, 0x3b, 0x89, 0xcd, 0xc2, 0x97, 0x47, 0xbc, 0x1d, 0x08, 0x4a, 0x22, 0xd3, 0x65, 0x6a, 0x34, 0x19, 0x66, 0xf4, 0x9a, 0x9b, 0xe4, 0x34, 0x50, 0x0f, + /* (2^ 55)P */ 0x6e, 0xb9, 0xe0, 0xa1, 0x67, 0x39, 0x3c, 0xf2, 0x88, 0x4d, 0x7a, 0x86, 0xfa, 0x08, 0x8b, 0xe5, 0x79, 0x16, 0x34, 0xa7, 0xc6, 0xab, 0x2f, 0xfb, 0x46, 0x69, 0x02, 0xb6, 0x1e, 0x38, 0x75, 0x2a, + /* (2^ 56)P */ 0xac, 0x20, 0x94, 0xc1, 0xe4, 0x3b, 0x0a, 0xc8, 0xdc, 0xb6, 0xf2, 0x81, 0xc6, 0xf6, 0xb1, 0x66, 0x88, 0x33, 0xe9, 0x61, 0x67, 0x03, 0xf7, 0x7c, 0xc4, 0xa4, 0x60, 0xa6, 0xd8, 0xbb, 0xab, 0x25, + /* (2^ 57)P */ 0x98, 0x51, 0xfd, 0x14, 0xba, 0x12, 0xea, 0x91, 0xa9, 0xff, 0x3c, 0x4a, 0xfc, 0x50, 0x49, 0x68, 0x28, 0xad, 0xf5, 0x30, 0x21, 0x84, 0x26, 0xf8, 0x41, 0xa4, 0x01, 0x53, 0xf7, 0x88, 0xa9, 0x3e, + /* (2^ 58)P */ 0x6f, 0x8c, 0x5f, 0x69, 0x9a, 0x10, 0x78, 0xc9, 0xf3, 0xc3, 0x30, 0x05, 0x4a, 0xeb, 0x46, 0x17, 0x95, 0x99, 0x45, 0xb4, 0x77, 0x6d, 0x4d, 0x44, 0xc7, 0x5c, 0x4e, 0x05, 0x8c, 0x2b, 0x95, 0x75, + /* (2^ 59)P */ 0xaa, 0xd6, 0xf4, 0x15, 0x79, 0x3f, 0x70, 0xa3, 0xd8, 0x47, 0x26, 0x2f, 0x20, 0x46, 0xc3, 0x66, 0x4b, 0x64, 0x1d, 0x81, 0xdf, 0x69, 0x14, 0xd0, 0x1f, 0xd7, 0xa5, 0x81, 0x7d, 0xa4, 0xfe, 0x77, + /* (2^ 60)P */ 0x81, 0xa3, 0x7c, 0xf5, 0x9e, 0x52, 0xe9, 0xc5, 0x1a, 0x88, 0x2f, 0xce, 0xb9, 0xb4, 0xee, 0x6e, 0xd6, 0x9b, 0x00, 0xe8, 0x28, 0x1a, 0xe9, 0xb6, 0xec, 0x3f, 0xfc, 0x9a, 0x3e, 0xbe, 0x80, 0x4b, + /* (2^ 61)P */ 0xc5, 0xd2, 0xae, 0x26, 0xc5, 0x73, 0x37, 0x7e, 0x9d, 0xa4, 0xc9, 0x53, 0xb4, 0xfc, 0x4a, 0x1b, 0x4d, 0xb2, 0xff, 0xba, 0xd7, 0xbd, 0x20, 0xa9, 0x0e, 0x40, 0x2d, 0x12, 0x9f, 0x69, 0x54, 0x7c, + /* (2^ 62)P */ 0xc8, 0x4b, 0xa9, 0x4f, 0xe1, 0xc8, 0x46, 0xef, 0x5e, 0xed, 0x52, 0x29, 0xce, 0x74, 0xb0, 0xe0, 0xd5, 0x85, 0xd8, 0xdb, 0xe1, 0x50, 0xa4, 0xbe, 0x2c, 0x71, 0x0f, 0x32, 0x49, 0x86, 0xb6, 0x61, + /* (2^ 63)P */ 0xd1, 0xbd, 0xcc, 0x09, 0x73, 0x5f, 0x48, 0x8a, 0x2d, 0x1a, 0x4d, 0x7d, 0x0d, 0x32, 0x06, 0xbd, 0xf4, 0xbe, 0x2d, 0x32, 0x73, 0x29, 0x23, 0x25, 0x70, 0xf7, 0x17, 0x8c, 0x75, 0xc4, 0x5d, 0x44, + /* (2^ 64)P */ 0x3c, 0x93, 0xc8, 0x7c, 0x17, 0x34, 0x04, 0xdb, 0x9f, 0x05, 0xea, 0x75, 0x21, 0xe8, 0x6f, 0xed, 0x34, 0xdb, 0x53, 0xc0, 0xfd, 0xbe, 0xfe, 0x1e, 0x99, 0xaf, 0x5d, 0xc6, 0x67, 0xe8, 0xdb, 0x4a, + /* (2^ 65)P */ 0xdf, 0x09, 0x06, 0xa9, 0xa2, 0x71, 0xcd, 0x3a, 0x50, 0x40, 0xd0, 0x6d, 0x85, 0x91, 0xe9, 0xe5, 0x3c, 0xc2, 0x57, 0x81, 0x68, 0x9b, 0xc6, 0x1e, 0x4d, 0xfe, 0x5c, 0x88, 0xf6, 0x27, 0x74, 0x69, + /* (2^ 66)P */ 0x51, 0xa8, 0xe1, 0x65, 0x9b, 0x7b, 0xbe, 0xd7, 0xdd, 0x36, 0xc5, 0x22, 0xd5, 0x28, 0x3d, 0xa0, 0x45, 0xb6, 0xd2, 0x8f, 0x65, 0x9d, 0x39, 0x28, 0xe1, 0x41, 0x26, 0x7c, 0xe1, 0xb7, 0xe5, 0x49, + /* (2^ 67)P */ 0xa4, 0x57, 0x04, 0x70, 0x98, 0x3a, 0x8c, 0x6f, 0x78, 0x67, 0xbb, 0x5e, 0xa2, 0xf0, 0x78, 0x50, 0x0f, 0x96, 0x82, 0xc3, 0xcb, 0x3c, 0x3c, 0xd1, 0xb1, 0x84, 0xdf, 0xa7, 0x58, 0x32, 0x00, 0x2e, + /* (2^ 68)P */ 0x1c, 0x6a, 0x29, 0xe6, 0x9b, 0xf3, 0xd1, 0x8a, 0xb2, 0xbf, 0x5f, 0x2a, 0x65, 0xaa, 0xee, 0xc1, 0xcb, 0xf3, 0x26, 0xfd, 0x73, 0x06, 0xee, 0x33, 0xcc, 0x2c, 0x9d, 0xa6, 0x73, 0x61, 0x25, 0x59, + /* (2^ 69)P */ 0x41, 0xfc, 0x18, 0x4e, 0xaa, 0x07, 0xea, 0x41, 0x1e, 0xa5, 0x87, 0x7c, 0x52, 0x19, 0xfc, 0xd9, 0x6f, 0xca, 0x31, 0x58, 0x80, 0xcb, 0xaa, 0xbd, 0x4f, 0x69, 0x16, 0xc9, 0x2d, 0x65, 0x5b, 0x44, + /* (2^ 70)P */ 0x15, 0x23, 0x17, 0xf2, 0xa7, 0xa3, 0x92, 0xce, 0x64, 0x99, 0x1b, 0xe1, 0x2d, 0x28, 0xdc, 0x1e, 0x4a, 0x31, 0x4c, 0xe0, 0xaf, 0x3a, 0x82, 0xa1, 0x86, 0xf5, 0x7c, 0x43, 0x94, 0x2d, 0x0a, 0x79, + /* (2^ 71)P */ 0x09, 0xe0, 0xf6, 0x93, 0xfb, 0x47, 0xc4, 0x71, 0x76, 0x52, 0x84, 0x22, 0x67, 0xa5, 0x22, 0x89, 0x69, 0x51, 0x4f, 0x20, 0x3b, 0x90, 0x70, 0xbf, 0xfe, 0x19, 0xa3, 0x1b, 0x89, 0x89, 0x7a, 0x2f, + /* (2^ 72)P */ 0x0c, 0x14, 0xe2, 0x77, 0xb5, 0x8e, 0xa0, 0x02, 0xf4, 0xdc, 0x7b, 0x42, 0xd4, 0x4e, 0x9a, 0xed, 0xd1, 0x3c, 0x32, 0xe4, 0x44, 0xec, 0x53, 0x52, 0x5b, 0x35, 0xe9, 0x14, 0x3c, 0x36, 0x88, 0x3e, + /* (2^ 73)P */ 0x8c, 0x0b, 0x11, 0x77, 0x42, 0xc1, 0x66, 0xaa, 0x90, 0x33, 0xa2, 0x10, 0x16, 0x39, 0xe0, 0x1a, 0xa2, 0xc2, 0x3f, 0xc9, 0x12, 0xbd, 0x30, 0x20, 0xab, 0xc7, 0x55, 0x95, 0x57, 0x41, 0xe1, 0x3e, + /* (2^ 74)P */ 0x41, 0x7d, 0x6e, 0x6d, 0x3a, 0xde, 0x14, 0x92, 0xfe, 0x7e, 0xf1, 0x07, 0x86, 0xd8, 0xcd, 0x3c, 0x17, 0x12, 0xe1, 0xf8, 0x88, 0x12, 0x4f, 0x67, 0xd0, 0x93, 0x9f, 0x32, 0x0f, 0x25, 0x82, 0x56, + /* (2^ 75)P */ 0x6e, 0x39, 0x2e, 0x6d, 0x13, 0x0b, 0xf0, 0x6c, 0xbf, 0xde, 0x14, 0x10, 0x6f, 0xf8, 0x4c, 0x6e, 0x83, 0x4e, 0xcc, 0xbf, 0xb5, 0xb1, 0x30, 0x59, 0xb6, 0x16, 0xba, 0x8a, 0xb4, 0x69, 0x70, 0x04, + /* (2^ 76)P */ 0x93, 0x07, 0xb2, 0x69, 0xab, 0xe4, 0x4c, 0x0d, 0x9e, 0xfb, 0xd0, 0x97, 0x1a, 0xb9, 0x4d, 0xb2, 0x1d, 0xd0, 0x00, 0x4e, 0xf5, 0x50, 0xfa, 0xcd, 0xb5, 0xdd, 0x8b, 0x36, 0x85, 0x10, 0x1b, 0x22, + /* (2^ 77)P */ 0xd2, 0xd8, 0xe3, 0xb1, 0x68, 0x94, 0xe5, 0xe7, 0x93, 0x2f, 0x12, 0xbd, 0x63, 0x65, 0xc5, 0x53, 0x09, 0x3f, 0x66, 0xe0, 0x03, 0xa9, 0xe8, 0xee, 0x42, 0x3d, 0xbe, 0xcb, 0x62, 0xa6, 0xef, 0x61, + /* (2^ 78)P */ 0x2a, 0xab, 0x6e, 0xde, 0xdd, 0xdd, 0xf8, 0x2c, 0x31, 0xf2, 0x35, 0x14, 0xd5, 0x0a, 0xf8, 0x9b, 0x73, 0x49, 0xf0, 0xc9, 0xce, 0xda, 0xea, 0x5d, 0x27, 0x9b, 0xd2, 0x41, 0x5d, 0x5b, 0x27, 0x29, + /* (2^ 79)P */ 0x4f, 0xf1, 0xeb, 0x95, 0x08, 0x0f, 0xde, 0xcf, 0xa7, 0x05, 0x49, 0x05, 0x6b, 0xb9, 0xaa, 0xb9, 0xfd, 0x20, 0xc4, 0xa1, 0xd9, 0x0d, 0xe8, 0xca, 0xc7, 0xbb, 0x73, 0x16, 0x2f, 0xbf, 0x63, 0x0a, + /* (2^ 80)P */ 0x8c, 0xbc, 0x8f, 0x95, 0x11, 0x6e, 0x2f, 0x09, 0xad, 0x2f, 0x82, 0x04, 0xe8, 0x81, 0x2a, 0x67, 0x17, 0x25, 0xd5, 0x60, 0x15, 0x35, 0xc8, 0xca, 0xf8, 0x92, 0xf1, 0xc8, 0x22, 0x77, 0x3f, 0x6f, + /* (2^ 81)P */ 0xb7, 0x94, 0xe8, 0xc2, 0xcc, 0x90, 0xba, 0xf8, 0x0d, 0x9f, 0xff, 0x38, 0xa4, 0x57, 0x75, 0x2c, 0x59, 0x23, 0xe5, 0x5a, 0x85, 0x1d, 0x4d, 0x89, 0x69, 0x3d, 0x74, 0x7b, 0x15, 0x22, 0xe1, 0x68, + /* (2^ 82)P */ 0xf3, 0x19, 0xb9, 0xcf, 0x70, 0x55, 0x7e, 0xd8, 0xb9, 0x8d, 0x79, 0x95, 0xcd, 0xde, 0x2c, 0x3f, 0xce, 0xa2, 0xc0, 0x10, 0x47, 0x15, 0x21, 0x21, 0xb2, 0xc5, 0x6d, 0x24, 0x15, 0xa1, 0x66, 0x3c, + /* (2^ 83)P */ 0x72, 0xcb, 0x4e, 0x29, 0x62, 0xc5, 0xed, 0xcb, 0x16, 0x0b, 0x28, 0x6a, 0xc3, 0x43, 0x71, 0xba, 0x67, 0x8b, 0x07, 0xd4, 0xef, 0xc2, 0x10, 0x96, 0x1e, 0x4b, 0x6a, 0x94, 0x5d, 0x73, 0x44, 0x61, + /* (2^ 84)P */ 0x50, 0x33, 0x5b, 0xd7, 0x1e, 0x11, 0x6f, 0x53, 0x1b, 0xd8, 0x41, 0x20, 0x8c, 0xdb, 0x11, 0x02, 0x3c, 0x41, 0x10, 0x0e, 0x00, 0xb1, 0x3c, 0xf9, 0x76, 0x88, 0x9e, 0x03, 0x3c, 0xfd, 0x9d, 0x14, + /* (2^ 85)P */ 0x5b, 0x15, 0x63, 0x6b, 0xe4, 0xdd, 0x79, 0xd4, 0x76, 0x79, 0x83, 0x3c, 0xe9, 0x15, 0x6e, 0xb6, 0x38, 0xe0, 0x13, 0x1f, 0x3b, 0xe4, 0xfd, 0xda, 0x35, 0x0b, 0x4b, 0x2e, 0x1a, 0xda, 0xaf, 0x5f, + /* (2^ 86)P */ 0x81, 0x75, 0x19, 0x17, 0xdf, 0xbb, 0x00, 0x36, 0xc2, 0xd2, 0x3c, 0xbe, 0x0b, 0x05, 0x72, 0x39, 0x86, 0xbe, 0xd5, 0xbd, 0x6d, 0x90, 0x38, 0x59, 0x0f, 0x86, 0x9b, 0x3f, 0xe4, 0xe5, 0xfc, 0x34, + /* (2^ 87)P */ 0x02, 0x4d, 0xd1, 0x42, 0xcd, 0xa4, 0xa8, 0x75, 0x65, 0xdf, 0x41, 0x34, 0xc5, 0xab, 0x8d, 0x82, 0xd3, 0x31, 0xe1, 0xd2, 0xed, 0xab, 0xdc, 0x33, 0x5f, 0xd2, 0x14, 0xb8, 0x6f, 0xd7, 0xba, 0x3e, + /* (2^ 88)P */ 0x0f, 0xe1, 0x70, 0x6f, 0x56, 0x6f, 0x90, 0xd4, 0x5a, 0x0f, 0x69, 0x51, 0xaa, 0xf7, 0x12, 0x5d, 0xf2, 0xfc, 0xce, 0x76, 0x6e, 0xb1, 0xad, 0x45, 0x99, 0x29, 0x23, 0xad, 0xae, 0x68, 0xf7, 0x01, + /* (2^ 89)P */ 0xbd, 0xfe, 0x48, 0x62, 0x7b, 0xc7, 0x6c, 0x2b, 0xfd, 0xaf, 0x3a, 0xec, 0x28, 0x06, 0xd3, 0x3c, 0x6a, 0x48, 0xef, 0xd4, 0x80, 0x0b, 0x1c, 0xce, 0x23, 0x6c, 0xf6, 0xa6, 0x2e, 0xff, 0x3b, 0x4c, + /* (2^ 90)P */ 0x5f, 0xeb, 0xea, 0x4a, 0x09, 0xc4, 0x2e, 0x3f, 0xa7, 0x2c, 0x37, 0x6e, 0x28, 0x9b, 0xb1, 0x61, 0x1d, 0x70, 0x2a, 0xde, 0x66, 0xa9, 0xef, 0x5e, 0xef, 0xe3, 0x55, 0xde, 0x65, 0x05, 0xb2, 0x23, + /* (2^ 91)P */ 0x57, 0x85, 0xd5, 0x79, 0x52, 0xca, 0x01, 0xe3, 0x4f, 0x87, 0xc2, 0x27, 0xce, 0xd4, 0xb2, 0x07, 0x67, 0x1d, 0xcf, 0x9d, 0x8a, 0xcd, 0x32, 0xa5, 0x56, 0xff, 0x2b, 0x3f, 0xe2, 0xfe, 0x52, 0x2a, + /* (2^ 92)P */ 0x3d, 0x66, 0xd8, 0x7c, 0xb3, 0xef, 0x24, 0x86, 0x94, 0x75, 0xbd, 0xff, 0x20, 0xac, 0xc7, 0xbb, 0x45, 0x74, 0xd3, 0x82, 0x9c, 0x5e, 0xb8, 0x57, 0x66, 0xec, 0xa6, 0x86, 0xcb, 0x52, 0x30, 0x7b, + /* (2^ 93)P */ 0x1e, 0xe9, 0x25, 0x25, 0xad, 0xf0, 0x82, 0x34, 0xa0, 0xdc, 0x8e, 0xd2, 0x43, 0x80, 0xb6, 0x2c, 0x3a, 0x00, 0x1b, 0x2e, 0x05, 0x6d, 0x4f, 0xaf, 0x0a, 0x1b, 0x78, 0x29, 0x25, 0x8c, 0x5f, 0x18, + /* (2^ 94)P */ 0xd6, 0xe0, 0x0c, 0xd8, 0x5b, 0xde, 0x41, 0xaa, 0xd6, 0xe9, 0x53, 0x68, 0x41, 0xb2, 0x07, 0x94, 0x3a, 0x4c, 0x7f, 0x35, 0x6e, 0xc3, 0x3e, 0x56, 0xce, 0x7b, 0x29, 0x0e, 0xdd, 0xb8, 0xc4, 0x4c, + /* (2^ 95)P */ 0x0e, 0x73, 0xb8, 0xff, 0x52, 0x1a, 0xfc, 0xa2, 0x37, 0x8e, 0x05, 0x67, 0x6e, 0xf1, 0x11, 0x18, 0xe1, 0x4e, 0xdf, 0xcd, 0x66, 0xa3, 0xf9, 0x10, 0x99, 0xf0, 0xb9, 0xa0, 0xc4, 0xa0, 0xf4, 0x72, + /* (2^ 96)P */ 0xa7, 0x4e, 0x3f, 0x66, 0x6f, 0xc0, 0x16, 0x8c, 0xba, 0x0f, 0x97, 0x4e, 0xf7, 0x3a, 0x3b, 0x69, 0x45, 0xc3, 0x9e, 0xd6, 0xf1, 0xe7, 0x02, 0x21, 0x89, 0x80, 0x8a, 0x96, 0xbc, 0x3c, 0xa5, 0x0b, + /* (2^ 97)P */ 0x37, 0x55, 0xa1, 0xfe, 0xc7, 0x9d, 0x3d, 0xca, 0x93, 0x64, 0x53, 0x51, 0xbb, 0x24, 0x68, 0x4c, 0xb1, 0x06, 0x40, 0x84, 0x14, 0x63, 0x88, 0xb9, 0x60, 0xcc, 0x54, 0xb4, 0x2a, 0xa7, 0xd2, 0x40, + /* (2^ 98)P */ 0x75, 0x09, 0x57, 0x12, 0xb7, 0xa1, 0x36, 0x59, 0x57, 0xa6, 0xbd, 0xde, 0x48, 0xd6, 0xb9, 0x91, 0xea, 0x30, 0x43, 0xb6, 0x4b, 0x09, 0x44, 0x33, 0xd0, 0x51, 0xee, 0x12, 0x0d, 0xa1, 0x6b, 0x00, + /* (2^ 99)P */ 0x58, 0x5d, 0xde, 0xf5, 0x68, 0x84, 0x22, 0x19, 0xb0, 0x05, 0xcc, 0x38, 0x4c, 0x2f, 0xb1, 0x0e, 0x90, 0x19, 0x60, 0xd5, 0x9d, 0x9f, 0x03, 0xa1, 0x0b, 0x0e, 0xff, 0x4f, 0xce, 0xd4, 0x02, 0x45, + /* (2^100)P */ 0x89, 0xc1, 0x37, 0x68, 0x10, 0x54, 0x20, 0xeb, 0x3c, 0xb9, 0xd3, 0x6d, 0x4c, 0x54, 0xf6, 0xd0, 0x4f, 0xd7, 0x16, 0xc4, 0x64, 0x70, 0x72, 0x40, 0xf0, 0x2e, 0x50, 0x4b, 0x11, 0xc6, 0x15, 0x6e, + /* (2^101)P */ 0x6b, 0xa7, 0xb1, 0xcf, 0x98, 0xa3, 0xf2, 0x4d, 0xb1, 0xf6, 0xf2, 0x19, 0x74, 0x6c, 0x25, 0x11, 0x43, 0x60, 0x6e, 0x06, 0x62, 0x79, 0x49, 0x4a, 0x44, 0x5b, 0x35, 0x41, 0xab, 0x3a, 0x5b, 0x70, + /* (2^102)P */ 0xd8, 0xb1, 0x97, 0xd7, 0x36, 0xf5, 0x5e, 0x36, 0xdb, 0xf0, 0xdd, 0x22, 0xd6, 0x6b, 0x07, 0x00, 0x88, 0x5a, 0x57, 0xe0, 0xb0, 0x33, 0xbf, 0x3b, 0x4d, 0xca, 0xe4, 0xc8, 0x05, 0xaa, 0x77, 0x37, + /* (2^103)P */ 0x5f, 0xdb, 0x78, 0x55, 0xc8, 0x45, 0x27, 0x39, 0xe2, 0x5a, 0xae, 0xdb, 0x49, 0x41, 0xda, 0x6f, 0x67, 0x98, 0xdc, 0x8a, 0x0b, 0xb0, 0xf0, 0xb1, 0xa3, 0x1d, 0x6f, 0xd3, 0x37, 0x34, 0x96, 0x09, + /* (2^104)P */ 0x53, 0x38, 0xdc, 0xa5, 0x90, 0x4e, 0x82, 0x7e, 0xbd, 0x5c, 0x13, 0x1f, 0x64, 0xf6, 0xb5, 0xcc, 0xcc, 0x8f, 0xce, 0x87, 0x6c, 0xd8, 0x36, 0x67, 0x9f, 0x24, 0x04, 0x66, 0xe2, 0x3c, 0x5f, 0x62, + /* (2^105)P */ 0x3f, 0xf6, 0x02, 0x95, 0x05, 0xc8, 0x8a, 0xaf, 0x69, 0x14, 0x35, 0x2e, 0x0a, 0xe7, 0x05, 0x0c, 0x05, 0x63, 0x4b, 0x76, 0x9c, 0x2e, 0x29, 0x35, 0xc3, 0x3a, 0xe2, 0xc7, 0x60, 0x43, 0x39, 0x1a, + /* (2^106)P */ 0x64, 0x32, 0x18, 0x51, 0x32, 0xd5, 0xc6, 0xd5, 0x4f, 0xb7, 0xc2, 0x43, 0xbd, 0x5a, 0x06, 0x62, 0x9b, 0x3f, 0x97, 0x3b, 0xd0, 0xf5, 0xfb, 0xb5, 0x5e, 0x6e, 0x20, 0x61, 0x36, 0xda, 0xa3, 0x13, + /* (2^107)P */ 0xe5, 0x94, 0x5d, 0x72, 0x37, 0x58, 0xbd, 0xc6, 0xc5, 0x16, 0x50, 0x20, 0x12, 0x09, 0xe3, 0x18, 0x68, 0x3c, 0x03, 0x70, 0x15, 0xce, 0x88, 0x20, 0x87, 0x79, 0x83, 0x5c, 0x49, 0x1f, 0xba, 0x7f, + /* (2^108)P */ 0x9d, 0x07, 0xf9, 0xf2, 0x23, 0x74, 0x8c, 0x5a, 0xc5, 0x3f, 0x02, 0x34, 0x7b, 0x15, 0x35, 0x17, 0x51, 0xb3, 0xfa, 0xd2, 0x9a, 0xb4, 0xf9, 0xe4, 0x3c, 0xe3, 0x78, 0xc8, 0x72, 0xff, 0x91, 0x66, + /* (2^109)P */ 0x3e, 0xff, 0x5e, 0xdc, 0xde, 0x2a, 0x2c, 0x12, 0xf4, 0x6c, 0x95, 0xd8, 0xf1, 0x4b, 0xdd, 0xf8, 0xda, 0x5b, 0x9e, 0x9e, 0x5d, 0x20, 0x86, 0xeb, 0x43, 0xc7, 0x75, 0xd9, 0xb9, 0x92, 0x9b, 0x04, + /* (2^110)P */ 0x5a, 0xc0, 0xf6, 0xb0, 0x30, 0x97, 0x37, 0xa5, 0x53, 0xa5, 0xf3, 0xc6, 0xac, 0xff, 0xa0, 0x72, 0x6d, 0xcd, 0x0d, 0xb2, 0x34, 0x2c, 0x03, 0xb0, 0x4a, 0x16, 0xd5, 0x88, 0xbc, 0x9d, 0x0e, 0x47, + /* (2^111)P */ 0x47, 0xc0, 0x37, 0xa2, 0x0c, 0xf1, 0x9c, 0xb1, 0xa2, 0x81, 0x6c, 0x1f, 0x71, 0x66, 0x54, 0xb6, 0x43, 0x0b, 0xd8, 0x6d, 0xd1, 0x1b, 0x32, 0xb3, 0x8e, 0xbe, 0x5f, 0x0c, 0x60, 0x4f, 0xc1, 0x48, + /* (2^112)P */ 0x03, 0xc8, 0xa6, 0x4a, 0x26, 0x1c, 0x45, 0x66, 0xa6, 0x7d, 0xfa, 0xa4, 0x04, 0x39, 0x6e, 0xb6, 0x95, 0x83, 0x12, 0xb3, 0xb0, 0x19, 0x5f, 0xd4, 0x10, 0xbc, 0xc9, 0xc3, 0x27, 0x26, 0x60, 0x31, + /* (2^113)P */ 0x0d, 0xe1, 0xe4, 0x32, 0x48, 0xdc, 0x20, 0x31, 0xf7, 0x17, 0xc7, 0x56, 0x67, 0xc4, 0x20, 0xeb, 0x94, 0x02, 0x28, 0x67, 0x3f, 0x2e, 0xf5, 0x00, 0x09, 0xc5, 0x30, 0x47, 0xc1, 0x4f, 0x6d, 0x56, + /* (2^114)P */ 0x06, 0x72, 0x83, 0xfd, 0x40, 0x5d, 0x3a, 0x7e, 0x7a, 0x54, 0x59, 0x71, 0xdc, 0x26, 0xe9, 0xc1, 0x95, 0x60, 0x8d, 0xa6, 0xfb, 0x30, 0x67, 0x21, 0xa7, 0xce, 0x69, 0x3f, 0x84, 0xc3, 0xe8, 0x22, + /* (2^115)P */ 0x2b, 0x4b, 0x0e, 0x93, 0xe8, 0x74, 0xd0, 0x33, 0x16, 0x58, 0xd1, 0x84, 0x0e, 0x35, 0xe4, 0xb6, 0x65, 0x23, 0xba, 0xd6, 0x6a, 0xc2, 0x34, 0x55, 0xf3, 0xf3, 0xf1, 0x89, 0x2f, 0xc1, 0x73, 0x77, + /* (2^116)P */ 0xaa, 0x62, 0x79, 0xa5, 0x4d, 0x40, 0xba, 0x8c, 0x56, 0xce, 0x99, 0x19, 0xa8, 0x97, 0x98, 0x5b, 0xfc, 0x92, 0x16, 0x12, 0x2f, 0x86, 0x8e, 0x50, 0x91, 0xc2, 0x93, 0xa0, 0x7f, 0x90, 0x81, 0x3a, + /* (2^117)P */ 0x10, 0xa5, 0x25, 0x47, 0xff, 0xd0, 0xde, 0x0d, 0x03, 0xc5, 0x3f, 0x67, 0x10, 0xcc, 0xd8, 0x10, 0x89, 0x4e, 0x1f, 0x9f, 0x1c, 0x15, 0x9d, 0x5b, 0x4c, 0xa4, 0x09, 0xcb, 0xd5, 0xc1, 0xa5, 0x32, + /* (2^118)P */ 0xfb, 0x41, 0x05, 0xb9, 0x42, 0xa4, 0x0a, 0x1e, 0xdb, 0x85, 0xb4, 0xc1, 0x7c, 0xeb, 0x85, 0x5f, 0xe5, 0xf2, 0x9d, 0x8a, 0xce, 0x95, 0xe5, 0xbe, 0x36, 0x22, 0x42, 0x22, 0xc7, 0x96, 0xe4, 0x25, + /* (2^119)P */ 0xb9, 0xe5, 0x0f, 0xcd, 0x46, 0x3c, 0xdf, 0x5e, 0x88, 0x33, 0xa4, 0xd2, 0x7e, 0x5a, 0xe7, 0x34, 0x52, 0xe3, 0x61, 0xd7, 0x11, 0xde, 0x88, 0xe4, 0x5c, 0x54, 0x85, 0xa0, 0x01, 0x8a, 0x87, 0x0e, + /* (2^120)P */ 0x04, 0xbb, 0x21, 0xe0, 0x77, 0x3c, 0x49, 0xba, 0x9a, 0x89, 0xdf, 0xc7, 0x43, 0x18, 0x4d, 0x2b, 0x67, 0x0d, 0xe8, 0x7a, 0x48, 0x7a, 0xa3, 0x9e, 0x94, 0x17, 0xe4, 0x11, 0x80, 0x95, 0xa9, 0x67, + /* (2^121)P */ 0x65, 0xb0, 0x97, 0x66, 0x1a, 0x05, 0x58, 0x4b, 0xd4, 0xa6, 0x6b, 0x8d, 0x7d, 0x3f, 0xe3, 0x47, 0xc1, 0x46, 0xca, 0x83, 0xd4, 0xa8, 0x4d, 0xbb, 0x0d, 0xdb, 0xc2, 0x81, 0xa1, 0xca, 0xbe, 0x68, + /* (2^122)P */ 0xa5, 0x9a, 0x98, 0x0b, 0xe9, 0x80, 0x89, 0x8d, 0x9b, 0xc9, 0x93, 0x2c, 0x4a, 0xb1, 0x5e, 0xf9, 0xa2, 0x73, 0x6e, 0x79, 0xc4, 0xc7, 0xc6, 0x51, 0x69, 0xb5, 0xef, 0xb5, 0x63, 0x83, 0x22, 0x6e, + /* (2^123)P */ 0xc8, 0x24, 0xd6, 0x2d, 0xb0, 0xc0, 0xbb, 0xc6, 0xee, 0x70, 0x81, 0xec, 0x7d, 0xb4, 0x7e, 0x77, 0xa9, 0xaf, 0xcf, 0x04, 0xa0, 0x15, 0xde, 0x3c, 0x9b, 0xbf, 0x60, 0x71, 0x08, 0xbc, 0xc6, 0x1d, + /* (2^124)P */ 0x02, 0x40, 0xc3, 0xee, 0x43, 0xe0, 0x07, 0x2e, 0x7f, 0xdc, 0x68, 0x7a, 0x67, 0xfc, 0xe9, 0x18, 0x9a, 0x5b, 0xd1, 0x8b, 0x18, 0x03, 0xda, 0xd8, 0x53, 0x82, 0x56, 0x00, 0xbb, 0xc3, 0xfb, 0x48, + /* (2^125)P */ 0xe1, 0x4c, 0x65, 0xfb, 0x4c, 0x7d, 0x54, 0x57, 0xad, 0xe2, 0x58, 0xa0, 0x82, 0x5b, 0x56, 0xd3, 0x78, 0x44, 0x15, 0xbf, 0x0b, 0xaf, 0x3e, 0xf6, 0x18, 0xbb, 0xdf, 0x14, 0xf1, 0x1e, 0x53, 0x47, + /* (2^126)P */ 0x87, 0xc5, 0x78, 0x42, 0x0a, 0x63, 0xec, 0xe1, 0xf3, 0x83, 0x8e, 0xca, 0x46, 0xd5, 0x07, 0x55, 0x2b, 0x0c, 0xdc, 0x3a, 0xc6, 0x35, 0xe1, 0x85, 0x4e, 0x84, 0x82, 0x56, 0xa8, 0xef, 0xa7, 0x0a, + /* (2^127)P */ 0x15, 0xf6, 0xe1, 0xb3, 0xa8, 0x1b, 0x69, 0x72, 0xfa, 0x3f, 0xbe, 0x1f, 0x70, 0xe9, 0xb4, 0x32, 0x68, 0x78, 0xbb, 0x39, 0x2e, 0xd9, 0xb6, 0x97, 0xe8, 0x39, 0x2e, 0xa0, 0xde, 0x53, 0xfe, 0x2c, + /* (2^128)P */ 0xb0, 0x52, 0xcd, 0x85, 0xcd, 0x92, 0x73, 0x68, 0x31, 0x98, 0xe2, 0x10, 0xc9, 0x66, 0xff, 0x27, 0x06, 0x2d, 0x83, 0xa9, 0x56, 0x45, 0x13, 0x97, 0xa0, 0xf8, 0x84, 0x0a, 0x36, 0xb0, 0x9b, 0x26, + /* (2^129)P */ 0x5c, 0xf8, 0x43, 0x76, 0x45, 0x55, 0x6e, 0x70, 0x1b, 0x7d, 0x59, 0x9b, 0x8c, 0xa4, 0x34, 0x37, 0x72, 0xa4, 0xef, 0xc6, 0xe8, 0x91, 0xee, 0x7a, 0xe0, 0xd9, 0xa9, 0x98, 0xc1, 0xab, 0xd6, 0x5c, + /* (2^130)P */ 0x1a, 0xe4, 0x3c, 0xcb, 0x06, 0xde, 0x04, 0x0e, 0x38, 0xe1, 0x02, 0x34, 0x89, 0xeb, 0xc6, 0xd8, 0x72, 0x37, 0x6e, 0x68, 0xbb, 0x59, 0x46, 0x90, 0xc8, 0xa8, 0x6b, 0x74, 0x71, 0xc3, 0x15, 0x72, + /* (2^131)P */ 0xd9, 0xa2, 0xe4, 0xea, 0x7e, 0xa9, 0x12, 0xfd, 0xc5, 0xf2, 0x94, 0x63, 0x51, 0xb7, 0x14, 0x95, 0x94, 0xf2, 0x08, 0x92, 0x80, 0xd5, 0x6f, 0x26, 0xb9, 0x26, 0x9a, 0x61, 0x85, 0x70, 0x84, 0x5c, + /* (2^132)P */ 0xea, 0x94, 0xd6, 0xfe, 0x10, 0x54, 0x98, 0x52, 0x54, 0xd2, 0x2e, 0x4a, 0x93, 0x5b, 0x90, 0x3c, 0x67, 0xe4, 0x3b, 0x2d, 0x69, 0x47, 0xbb, 0x10, 0xe1, 0xe9, 0xe5, 0x69, 0x2d, 0x3d, 0x3b, 0x06, + /* (2^133)P */ 0xeb, 0x7d, 0xa5, 0xdd, 0xee, 0x26, 0x27, 0x47, 0x91, 0x18, 0xf4, 0x10, 0xae, 0xc4, 0xb6, 0xef, 0x14, 0x76, 0x30, 0x7b, 0x91, 0x41, 0x16, 0x2b, 0x7c, 0x5b, 0xf4, 0xc4, 0x4f, 0x55, 0x7c, 0x11, + /* (2^134)P */ 0x12, 0x88, 0x9d, 0x8f, 0x11, 0xf3, 0x7c, 0xc0, 0x39, 0x79, 0x01, 0x50, 0x20, 0xd8, 0xdb, 0x01, 0x27, 0x28, 0x1b, 0x17, 0xf4, 0x03, 0xe8, 0xd7, 0xea, 0x25, 0xd2, 0x87, 0x74, 0xe8, 0x15, 0x10, + /* (2^135)P */ 0x4d, 0xcc, 0x3a, 0xd2, 0xfe, 0xe3, 0x8d, 0xc5, 0x2d, 0xbe, 0xa7, 0x94, 0xc2, 0x91, 0xdb, 0x50, 0x57, 0xf4, 0x9c, 0x1c, 0x3d, 0xd4, 0x94, 0x0b, 0x4a, 0x52, 0x37, 0x6e, 0xfa, 0x40, 0x16, 0x6b, + /* (2^136)P */ 0x09, 0x0d, 0xda, 0x5f, 0x6c, 0x34, 0x2f, 0x69, 0x51, 0x31, 0x4d, 0xfa, 0x59, 0x1c, 0x0b, 0x20, 0x96, 0xa2, 0x77, 0x07, 0x76, 0x6f, 0xc4, 0xb8, 0xcf, 0xfb, 0xfd, 0x3f, 0x5f, 0x39, 0x38, 0x4b, + /* (2^137)P */ 0x71, 0xd6, 0x54, 0xbe, 0x00, 0x5e, 0xd2, 0x18, 0xa6, 0xab, 0xc8, 0xbe, 0x82, 0x05, 0xd5, 0x60, 0x82, 0xb9, 0x78, 0x3b, 0x26, 0x8f, 0xad, 0x87, 0x32, 0x04, 0xda, 0x9c, 0x4e, 0xf6, 0xfd, 0x50, + /* (2^138)P */ 0xf0, 0xdc, 0x78, 0xc5, 0xaa, 0x67, 0xf5, 0x90, 0x3b, 0x13, 0xa3, 0xf2, 0x0e, 0x9b, 0x1e, 0xef, 0x71, 0xde, 0xd9, 0x42, 0x92, 0xba, 0xeb, 0x0e, 0xc7, 0x01, 0x31, 0xf0, 0x9b, 0x3c, 0x47, 0x15, + /* (2^139)P */ 0x95, 0x80, 0xb7, 0x56, 0xae, 0xe8, 0x77, 0x7c, 0x8e, 0x07, 0x6f, 0x6e, 0x66, 0xe7, 0x78, 0xb6, 0x1f, 0xba, 0x48, 0x53, 0x61, 0xb9, 0xa0, 0x2d, 0x0b, 0x3f, 0x73, 0xff, 0xc1, 0x31, 0xf9, 0x7c, + /* (2^140)P */ 0x6c, 0x36, 0x0a, 0x0a, 0xf5, 0x57, 0xb3, 0x26, 0x32, 0xd7, 0x87, 0x2b, 0xf4, 0x8c, 0x70, 0xe9, 0xc0, 0xb2, 0x1c, 0xf9, 0xa5, 0xee, 0x3a, 0xc1, 0x4c, 0xbb, 0x43, 0x11, 0x99, 0x0c, 0xd9, 0x35, + /* (2^141)P */ 0xdc, 0xd9, 0xa0, 0xa9, 0x04, 0xc4, 0xc1, 0x47, 0x51, 0xd2, 0x72, 0x19, 0x45, 0x58, 0x9e, 0x65, 0x31, 0x8c, 0xb3, 0x73, 0xc4, 0xa8, 0x75, 0x38, 0x24, 0x1f, 0x56, 0x79, 0xd3, 0x9e, 0xbd, 0x1f, + /* (2^142)P */ 0x8d, 0xc2, 0x1e, 0xd4, 0x6f, 0xbc, 0xfa, 0x11, 0xca, 0x2d, 0x2a, 0xcd, 0xe3, 0xdf, 0xf8, 0x7e, 0x95, 0x45, 0x40, 0x8c, 0x5d, 0x3b, 0xe7, 0x72, 0x27, 0x2f, 0xb7, 0x54, 0x49, 0xfa, 0x35, 0x61, + /* (2^143)P */ 0x9c, 0xb6, 0x24, 0xde, 0xa2, 0x32, 0xfc, 0xcc, 0x88, 0x5d, 0x09, 0x1f, 0x8c, 0x69, 0x55, 0x3f, 0x29, 0xf9, 0xc3, 0x5a, 0xed, 0x50, 0x33, 0xbe, 0xeb, 0x7e, 0x47, 0xca, 0x06, 0xf8, 0x9b, 0x5e, + /* (2^144)P */ 0x68, 0x9f, 0x30, 0x3c, 0xb6, 0x8f, 0xce, 0xe9, 0xf4, 0xf9, 0xe1, 0x65, 0x35, 0xf6, 0x76, 0x53, 0xf1, 0x93, 0x63, 0x5a, 0xb3, 0xcf, 0xaf, 0xd1, 0x06, 0x35, 0x62, 0xe5, 0xed, 0xa1, 0x32, 0x66, + /* (2^145)P */ 0x4c, 0xed, 0x2d, 0x0c, 0x39, 0x6c, 0x7d, 0x0b, 0x1f, 0xcb, 0x04, 0xdf, 0x81, 0x32, 0xcb, 0x56, 0xc7, 0xc3, 0xec, 0x49, 0x12, 0x5a, 0x30, 0x66, 0x2a, 0xa7, 0x8c, 0xa3, 0x60, 0x8b, 0x58, 0x5d, + /* (2^146)P */ 0x2d, 0xf4, 0xe5, 0xe8, 0x78, 0xbf, 0xec, 0xa6, 0xec, 0x3e, 0x8a, 0x3c, 0x4b, 0xb4, 0xee, 0x86, 0x04, 0x16, 0xd2, 0xfb, 0x48, 0x9c, 0x21, 0xec, 0x31, 0x67, 0xc3, 0x17, 0xf5, 0x1a, 0xaf, 0x1a, + /* (2^147)P */ 0xe7, 0xbd, 0x69, 0x67, 0x83, 0xa2, 0x06, 0xc3, 0xdb, 0x2a, 0x1e, 0x2b, 0x62, 0x80, 0x82, 0x20, 0xa6, 0x94, 0xff, 0xfb, 0x1f, 0xf5, 0x27, 0x80, 0x6b, 0xf2, 0x24, 0x11, 0xce, 0xa1, 0xcf, 0x76, + /* (2^148)P */ 0xb6, 0xab, 0x22, 0x24, 0x56, 0x00, 0xeb, 0x18, 0xc3, 0x29, 0x8c, 0x8f, 0xd5, 0xc4, 0x77, 0xf3, 0x1a, 0x56, 0x31, 0xf5, 0x07, 0xc2, 0xbb, 0x4d, 0x27, 0x8a, 0x12, 0x82, 0xf0, 0xb7, 0x53, 0x02, + /* (2^149)P */ 0xe0, 0x17, 0x2c, 0xb6, 0x1c, 0x09, 0x1f, 0x3d, 0xa9, 0x28, 0x46, 0xd6, 0xab, 0xe1, 0x60, 0x48, 0x53, 0x42, 0x9d, 0x30, 0x36, 0x74, 0xd1, 0x52, 0x76, 0xe5, 0xfa, 0x3e, 0xe1, 0x97, 0x6f, 0x35, + /* (2^150)P */ 0x5b, 0x53, 0x50, 0xa1, 0x1a, 0xe1, 0x51, 0xd3, 0xcc, 0x78, 0xd8, 0x1d, 0xbb, 0x45, 0x6b, 0x3e, 0x98, 0x2c, 0xd9, 0xbe, 0x28, 0x61, 0x77, 0x0c, 0xb8, 0x85, 0x28, 0x03, 0x93, 0xae, 0x34, 0x1d, + /* (2^151)P */ 0xc3, 0xa4, 0x5b, 0xa8, 0x8c, 0x48, 0xa0, 0x4b, 0xce, 0xe6, 0x9c, 0x3c, 0xc3, 0x48, 0x53, 0x98, 0x70, 0xa7, 0xbd, 0x97, 0x6f, 0x4c, 0x12, 0x66, 0x4a, 0x12, 0x54, 0x06, 0x29, 0xa0, 0x81, 0x0f, + /* (2^152)P */ 0xfd, 0x86, 0x9b, 0x56, 0xa6, 0x9c, 0xd0, 0x9e, 0x2d, 0x9a, 0xaf, 0x18, 0xfd, 0x09, 0x10, 0x81, 0x0a, 0xc2, 0xd8, 0x93, 0x3f, 0xd0, 0x08, 0xff, 0x6b, 0xf2, 0xae, 0x9f, 0x19, 0x48, 0xa1, 0x52, + /* (2^153)P */ 0x73, 0x1b, 0x8d, 0x2d, 0xdc, 0xf9, 0x03, 0x3e, 0x70, 0x1a, 0x96, 0x73, 0x18, 0x80, 0x05, 0x42, 0x70, 0x59, 0xa3, 0x41, 0xf0, 0x87, 0xd9, 0xc0, 0x49, 0xd5, 0xc0, 0xa1, 0x15, 0x1f, 0xaa, 0x07, + /* (2^154)P */ 0x24, 0x72, 0xd2, 0x8c, 0xe0, 0x6c, 0xd4, 0xdf, 0x39, 0x42, 0x4e, 0x93, 0x4f, 0x02, 0x0a, 0x6d, 0x59, 0x7b, 0x89, 0x99, 0x63, 0x7a, 0x8a, 0x80, 0xa2, 0x95, 0x3d, 0xe1, 0xe9, 0x56, 0x45, 0x0a, + /* (2^155)P */ 0x45, 0x30, 0xc1, 0xe9, 0x1f, 0x99, 0x1a, 0xd2, 0xb8, 0x51, 0x77, 0xfe, 0x48, 0x85, 0x0e, 0x9b, 0x35, 0x00, 0xf3, 0x4b, 0xcb, 0x43, 0xa6, 0x5d, 0x21, 0xf7, 0x40, 0x39, 0xd6, 0x28, 0xdb, 0x77, + /* (2^156)P */ 0x11, 0x90, 0xdc, 0x4a, 0x61, 0xeb, 0x5e, 0xfc, 0xeb, 0x11, 0xc4, 0xe8, 0x9a, 0x41, 0x29, 0x52, 0x74, 0xcf, 0x1d, 0x7d, 0x78, 0xe7, 0xc3, 0x9e, 0xb5, 0x4c, 0x6e, 0x21, 0x3e, 0x05, 0x0d, 0x34, + /* (2^157)P */ 0xb4, 0xf2, 0x8d, 0xb4, 0x39, 0xaf, 0xc7, 0xca, 0x94, 0x0a, 0xa1, 0x71, 0x28, 0xec, 0xfa, 0xc0, 0xed, 0x75, 0xa5, 0x5c, 0x24, 0x69, 0x0a, 0x14, 0x4c, 0x3a, 0x27, 0x34, 0x71, 0xc3, 0xf1, 0x0c, + /* (2^158)P */ 0xa5, 0xb8, 0x24, 0xc2, 0x6a, 0x30, 0xee, 0xc8, 0xb0, 0x30, 0x49, 0xcb, 0x7c, 0xee, 0xea, 0x57, 0x4f, 0xe7, 0xcb, 0xaa, 0xbd, 0x06, 0xe8, 0xa1, 0x7d, 0x65, 0xeb, 0x2e, 0x74, 0x62, 0x9a, 0x7d, + /* (2^159)P */ 0x30, 0x48, 0x6c, 0x54, 0xef, 0xb6, 0xb6, 0x9e, 0x2e, 0x6e, 0xb3, 0xdd, 0x1f, 0xca, 0x5c, 0x88, 0x05, 0x71, 0x0d, 0xef, 0x83, 0xf3, 0xb9, 0xe6, 0x12, 0x04, 0x2e, 0x9d, 0xef, 0x4f, 0x65, 0x58, + /* (2^160)P */ 0x26, 0x8e, 0x0e, 0xbe, 0xff, 0xc4, 0x05, 0xa9, 0x6e, 0x81, 0x31, 0x9b, 0xdf, 0xe5, 0x2d, 0x94, 0xe1, 0x88, 0x2e, 0x80, 0x3f, 0x72, 0x7d, 0x49, 0x8d, 0x40, 0x2f, 0x60, 0xea, 0x4d, 0x68, 0x30, + /* (2^161)P */ 0x34, 0xcb, 0xe6, 0xa3, 0x78, 0xa2, 0xe5, 0x21, 0xc4, 0x1d, 0x15, 0x5b, 0x6f, 0x6e, 0xfb, 0xae, 0x15, 0xca, 0x77, 0x9d, 0x04, 0x8e, 0x0b, 0xb3, 0x81, 0x89, 0xb9, 0x53, 0xcf, 0xc9, 0xc3, 0x28, + /* (2^162)P */ 0x2a, 0xdd, 0x6c, 0x55, 0x21, 0xb7, 0x7f, 0x28, 0x74, 0x22, 0x02, 0x97, 0xa8, 0x7c, 0x31, 0x0d, 0x58, 0x32, 0x54, 0x3a, 0x42, 0xc7, 0x68, 0x74, 0x2f, 0x64, 0xb5, 0x4e, 0x46, 0x11, 0x7f, 0x4a, + /* (2^163)P */ 0xa6, 0x3a, 0x19, 0x4d, 0x77, 0xa4, 0x37, 0xa2, 0xa1, 0x29, 0x21, 0xa9, 0x6e, 0x98, 0x65, 0xd8, 0x88, 0x1a, 0x7c, 0xf8, 0xec, 0x15, 0xc5, 0x24, 0xeb, 0xf5, 0x39, 0x5f, 0x57, 0x03, 0x40, 0x60, + /* (2^164)P */ 0x27, 0x9b, 0x0a, 0x57, 0x89, 0xf1, 0xb9, 0x47, 0x78, 0x4b, 0x5e, 0x46, 0xde, 0xce, 0x98, 0x2b, 0x20, 0x5c, 0xb8, 0xdb, 0x51, 0xf5, 0x6d, 0x02, 0x01, 0x19, 0xe2, 0x47, 0x10, 0xd9, 0xfc, 0x74, + /* (2^165)P */ 0xa3, 0xbf, 0xc1, 0x23, 0x0a, 0xa9, 0xe2, 0x13, 0xf6, 0x19, 0x85, 0x47, 0x4e, 0x07, 0xb0, 0x0c, 0x44, 0xcf, 0xf6, 0x3a, 0xbe, 0xcb, 0xf1, 0x5f, 0xbe, 0x2d, 0x81, 0xbe, 0x38, 0x54, 0xfe, 0x67, + /* (2^166)P */ 0xb0, 0x05, 0x0f, 0xa4, 0x4f, 0xf6, 0x3c, 0xd1, 0x87, 0x37, 0x28, 0x32, 0x2f, 0xfb, 0x4d, 0x05, 0xea, 0x2a, 0x0d, 0x7f, 0x5b, 0x91, 0x73, 0x41, 0x4e, 0x0d, 0x61, 0x1f, 0x4f, 0x14, 0x2f, 0x48, + /* (2^167)P */ 0x34, 0x82, 0x7f, 0xb4, 0x01, 0x02, 0x21, 0xf6, 0x90, 0xb9, 0x70, 0x9e, 0x92, 0xe1, 0x0a, 0x5d, 0x7c, 0x56, 0x49, 0xb0, 0x55, 0xf4, 0xd7, 0xdc, 0x01, 0x6f, 0x91, 0xf0, 0xf1, 0xd0, 0x93, 0x7e, + /* (2^168)P */ 0xfa, 0xb4, 0x7d, 0x8a, 0xf1, 0xcb, 0x79, 0xdd, 0x2f, 0xc6, 0x74, 0x6f, 0xbf, 0x91, 0x83, 0xbe, 0xbd, 0x91, 0x82, 0x4b, 0xd1, 0x45, 0x71, 0x02, 0x05, 0x17, 0xbf, 0x2c, 0xea, 0x73, 0x5a, 0x58, + /* (2^169)P */ 0xb2, 0x0d, 0x8a, 0x92, 0x3e, 0xa0, 0x5c, 0x48, 0xe7, 0x57, 0x28, 0x74, 0xa5, 0x01, 0xfc, 0x10, 0xa7, 0x51, 0xd5, 0xd6, 0xdb, 0x2e, 0x48, 0x2f, 0x8a, 0xdb, 0x8f, 0x04, 0xb5, 0x33, 0x04, 0x0f, + /* (2^170)P */ 0x47, 0x62, 0xdc, 0xd7, 0x8d, 0x2e, 0xda, 0x60, 0x9a, 0x81, 0xd4, 0x8c, 0xd3, 0xc9, 0xb4, 0x88, 0x97, 0x66, 0xf6, 0x01, 0xc0, 0x3a, 0x03, 0x13, 0x75, 0x7d, 0x36, 0x3b, 0xfe, 0x24, 0x3b, 0x27, + /* (2^171)P */ 0xd4, 0xb9, 0xb3, 0x31, 0x6a, 0xf6, 0xe8, 0xc6, 0xd5, 0x49, 0xdf, 0x94, 0xa4, 0x14, 0x15, 0x28, 0xa7, 0x3d, 0xb2, 0xc8, 0xdf, 0x6f, 0x72, 0xd1, 0x48, 0xe5, 0xde, 0x03, 0xd1, 0xe7, 0x3a, 0x4b, + /* (2^172)P */ 0x7e, 0x9d, 0x4b, 0xce, 0x19, 0x6e, 0x25, 0xc6, 0x1c, 0xc6, 0xe3, 0x86, 0xf1, 0x5c, 0x5c, 0xff, 0x45, 0xc1, 0x8e, 0x4b, 0xa3, 0x3c, 0xc6, 0xac, 0x74, 0x65, 0xe6, 0xfe, 0x88, 0x18, 0x62, 0x74, + /* (2^173)P */ 0x1e, 0x0a, 0x29, 0x45, 0x96, 0x40, 0x6f, 0x95, 0x2e, 0x96, 0x3a, 0x26, 0xe3, 0xf8, 0x0b, 0xef, 0x7b, 0x64, 0xc2, 0x5e, 0xeb, 0x50, 0x6a, 0xed, 0x02, 0x75, 0xca, 0x9d, 0x3a, 0x28, 0x94, 0x06, + /* (2^174)P */ 0xd1, 0xdc, 0xa2, 0x43, 0x36, 0x96, 0x9b, 0x76, 0x53, 0x53, 0xfc, 0x09, 0xea, 0xc8, 0xb7, 0x42, 0xab, 0x7e, 0x39, 0x13, 0xee, 0x2a, 0x00, 0x4f, 0x3a, 0xd6, 0xb7, 0x19, 0x2c, 0x5e, 0x00, 0x63, + /* (2^175)P */ 0xea, 0x3b, 0x02, 0x63, 0xda, 0x36, 0x67, 0xca, 0xb7, 0x99, 0x2a, 0xb1, 0x6d, 0x7f, 0x6c, 0x96, 0xe1, 0xc5, 0x37, 0xc5, 0x90, 0x93, 0xe0, 0xac, 0xee, 0x89, 0xaa, 0xa1, 0x63, 0x60, 0x69, 0x0b, + /* (2^176)P */ 0xe5, 0x56, 0x8c, 0x28, 0x97, 0x3e, 0xb0, 0xeb, 0xe8, 0x8b, 0x8c, 0x93, 0x9f, 0x9f, 0x2a, 0x43, 0x71, 0x7f, 0x71, 0x5b, 0x3d, 0xa9, 0xa5, 0xa6, 0x97, 0x9d, 0x8f, 0xe1, 0xc3, 0xb4, 0x5f, 0x1a, + /* (2^177)P */ 0xce, 0xcd, 0x60, 0x1c, 0xad, 0xe7, 0x94, 0x1c, 0xa0, 0xc4, 0x02, 0xfc, 0x43, 0x2a, 0x20, 0xee, 0x20, 0x6a, 0xc4, 0x67, 0xd8, 0xe4, 0xaf, 0x8d, 0x58, 0x7b, 0xc2, 0x8a, 0x3c, 0x26, 0x10, 0x0a, + /* (2^178)P */ 0x4a, 0x2a, 0x43, 0xe4, 0xdf, 0xa9, 0xde, 0xd0, 0xc5, 0x77, 0x92, 0xbe, 0x7b, 0xf8, 0x6a, 0x85, 0x1a, 0xc7, 0x12, 0xc2, 0xac, 0x72, 0x84, 0xce, 0x91, 0x1e, 0xbb, 0x9b, 0x6d, 0x1b, 0x15, 0x6f, + /* (2^179)P */ 0x6a, 0xd5, 0xee, 0x7c, 0x52, 0x6c, 0x77, 0x26, 0xec, 0xfa, 0xf8, 0xfb, 0xb7, 0x1c, 0x21, 0x7d, 0xcc, 0x09, 0x46, 0xfd, 0xa6, 0x66, 0xae, 0x37, 0x42, 0x0c, 0x77, 0xd2, 0x02, 0xb7, 0x81, 0x1f, + /* (2^180)P */ 0x92, 0x83, 0xc5, 0xea, 0x57, 0xb0, 0xb0, 0x2f, 0x9d, 0x4e, 0x74, 0x29, 0xfe, 0x89, 0xdd, 0xe1, 0xf8, 0xb4, 0xbe, 0x17, 0xeb, 0xf8, 0x64, 0xc9, 0x1e, 0xd4, 0xa2, 0xc9, 0x73, 0x10, 0x57, 0x29, + /* (2^181)P */ 0x54, 0xe2, 0xc0, 0x81, 0x89, 0xa1, 0x48, 0xa9, 0x30, 0x28, 0xb2, 0x65, 0x9b, 0x36, 0xf6, 0x2d, 0xc6, 0xd3, 0xcf, 0x5f, 0xd7, 0xb2, 0x3e, 0xa3, 0x1f, 0xa0, 0x99, 0x41, 0xec, 0xd6, 0x8c, 0x07, + /* (2^182)P */ 0x2f, 0x0d, 0x90, 0xad, 0x41, 0x4a, 0x58, 0x4a, 0x52, 0x4c, 0xc7, 0xe2, 0x78, 0x2b, 0x14, 0x32, 0x78, 0xc9, 0x31, 0x84, 0x33, 0xe8, 0xc4, 0x68, 0xc2, 0x9f, 0x68, 0x08, 0x90, 0xea, 0x69, 0x7f, + /* (2^183)P */ 0x65, 0x82, 0xa3, 0x46, 0x1e, 0xc8, 0xf2, 0x52, 0xfd, 0x32, 0xa8, 0x04, 0x2d, 0x07, 0x78, 0xfd, 0x94, 0x9e, 0x35, 0x25, 0xfa, 0xd5, 0xd7, 0x8c, 0xd2, 0x29, 0xcc, 0x54, 0x74, 0x1b, 0xe7, 0x4d, + /* (2^184)P */ 0xc9, 0x6a, 0xda, 0x1e, 0xad, 0x60, 0xeb, 0x42, 0x3a, 0x9c, 0xc0, 0xdb, 0xdf, 0x37, 0xad, 0x0a, 0x91, 0xc1, 0x3c, 0xe3, 0x71, 0x4b, 0x00, 0x81, 0x3c, 0x80, 0x22, 0x51, 0x34, 0xbe, 0xe6, 0x44, + /* (2^185)P */ 0xdb, 0x20, 0x19, 0xba, 0x88, 0x83, 0xfe, 0x03, 0x08, 0xb0, 0x0d, 0x15, 0x32, 0x7c, 0xd5, 0xf5, 0x29, 0x0c, 0xf6, 0x1a, 0x28, 0xc4, 0xc8, 0x49, 0xee, 0x1a, 0x70, 0xde, 0x18, 0xb5, 0xed, 0x21, + /* (2^186)P */ 0x99, 0xdc, 0x06, 0x8f, 0x41, 0x3e, 0xb6, 0x7f, 0xb8, 0xd7, 0x66, 0xc1, 0x99, 0x0d, 0x46, 0xa4, 0x83, 0x0a, 0x52, 0xce, 0x48, 0x52, 0xdd, 0x24, 0x58, 0x83, 0x92, 0x2b, 0x71, 0xad, 0xc3, 0x5e, + /* (2^187)P */ 0x0f, 0x93, 0x17, 0xbd, 0x5f, 0x2a, 0x02, 0x15, 0xe3, 0x70, 0x25, 0xd8, 0x77, 0x4a, 0xf6, 0xa4, 0x12, 0x37, 0x78, 0x15, 0x69, 0x8d, 0xbc, 0x12, 0xbb, 0x0a, 0x62, 0xfc, 0xc0, 0x94, 0x81, 0x49, + /* (2^188)P */ 0x82, 0x6c, 0x68, 0x55, 0xd2, 0xd9, 0xa2, 0x38, 0xf0, 0x21, 0x3e, 0x19, 0xd9, 0x6b, 0x5c, 0x78, 0x84, 0x54, 0x4a, 0xb2, 0x1a, 0xc8, 0xd5, 0xe4, 0x89, 0x09, 0xe2, 0xb2, 0x60, 0x78, 0x30, 0x56, + /* (2^189)P */ 0xc4, 0x74, 0x4d, 0x8b, 0xf7, 0x55, 0x9d, 0x42, 0x31, 0x01, 0x35, 0x43, 0x46, 0x83, 0xf1, 0x22, 0xff, 0x1f, 0xc7, 0x98, 0x45, 0xc2, 0x60, 0x1e, 0xef, 0x83, 0x99, 0x97, 0x14, 0xf0, 0xf2, 0x59, + /* (2^190)P */ 0x44, 0x4a, 0x49, 0xeb, 0x56, 0x7d, 0xa4, 0x46, 0x8e, 0xa1, 0x36, 0xd6, 0x54, 0xa8, 0x22, 0x3e, 0x3b, 0x1c, 0x49, 0x74, 0x52, 0xe1, 0x46, 0xb3, 0xe7, 0xcd, 0x90, 0x53, 0x4e, 0xfd, 0xea, 0x2c, + /* (2^191)P */ 0x75, 0x66, 0x0d, 0xbe, 0x38, 0x85, 0x8a, 0xba, 0x23, 0x8e, 0x81, 0x50, 0xbb, 0x74, 0x90, 0x4b, 0xc3, 0x04, 0xd3, 0x85, 0x90, 0xb8, 0xda, 0xcb, 0xc4, 0x92, 0x61, 0xe5, 0xe0, 0x4f, 0xa2, 0x61, + /* (2^192)P */ 0xcb, 0x5b, 0x52, 0xdb, 0xe6, 0x15, 0x76, 0xcb, 0xca, 0xe4, 0x67, 0xa5, 0x35, 0x8c, 0x7d, 0xdd, 0x69, 0xdd, 0xfc, 0xca, 0x3a, 0x15, 0xb4, 0xe6, 0x66, 0x97, 0x3c, 0x7f, 0x09, 0x8e, 0x66, 0x2d, + /* (2^193)P */ 0xf0, 0x5e, 0xe5, 0x5c, 0x26, 0x7e, 0x7e, 0xa5, 0x67, 0xb9, 0xd4, 0x7c, 0x52, 0x4e, 0x9f, 0x5d, 0xe5, 0xd1, 0x2f, 0x49, 0x06, 0x36, 0xc8, 0xfb, 0xae, 0xf7, 0xc3, 0xb7, 0xbe, 0x52, 0x0d, 0x09, + /* (2^194)P */ 0x7c, 0x4d, 0x7b, 0x1e, 0x5a, 0x51, 0xb9, 0x09, 0xc0, 0x44, 0xda, 0x99, 0x25, 0x6a, 0x26, 0x1f, 0x04, 0x55, 0xc5, 0xe2, 0x48, 0x95, 0xc4, 0xa1, 0xcc, 0x15, 0x6f, 0x12, 0x87, 0x42, 0xf0, 0x7e, + /* (2^195)P */ 0x15, 0xef, 0x30, 0xbd, 0x9d, 0x65, 0xd1, 0xfe, 0x7b, 0x27, 0xe0, 0xc4, 0xee, 0xb9, 0x4a, 0x8b, 0x91, 0x32, 0xdf, 0xa5, 0x36, 0x62, 0x4d, 0x88, 0x88, 0xf7, 0x5c, 0xbf, 0xa6, 0x6e, 0xd9, 0x1f, + /* (2^196)P */ 0x9a, 0x0d, 0x19, 0x1f, 0x98, 0x61, 0xa1, 0x42, 0xc1, 0x52, 0x60, 0x7e, 0x50, 0x49, 0xd8, 0x61, 0xd5, 0x2c, 0x5a, 0x28, 0xbf, 0x13, 0xe1, 0x9f, 0xd8, 0x85, 0xad, 0xdb, 0x76, 0xd6, 0x22, 0x7c, + /* (2^197)P */ 0x7d, 0xd2, 0xfb, 0x2b, 0xed, 0x70, 0xe7, 0x82, 0xa5, 0xf5, 0x96, 0xe9, 0xec, 0xb2, 0x05, 0x4c, 0x50, 0x01, 0x90, 0xb0, 0xc2, 0xa9, 0x40, 0xcd, 0x64, 0xbf, 0xd9, 0x13, 0x92, 0x31, 0x95, 0x58, + /* (2^198)P */ 0x08, 0x2e, 0xea, 0x3f, 0x70, 0x5d, 0xcc, 0xe7, 0x8c, 0x18, 0xe2, 0x58, 0x12, 0x49, 0x0c, 0xb5, 0xf0, 0x5b, 0x20, 0x48, 0xaa, 0x0b, 0xe3, 0xcc, 0x62, 0x2d, 0xa3, 0xcf, 0x9c, 0x65, 0x7c, 0x53, + /* (2^199)P */ 0x88, 0xc0, 0xcf, 0x98, 0x3a, 0x62, 0xb6, 0x37, 0xa4, 0xac, 0xd6, 0xa4, 0x1f, 0xed, 0x9b, 0xfe, 0xb0, 0xd1, 0xa8, 0x56, 0x8e, 0x9b, 0xd2, 0x04, 0x75, 0x95, 0x51, 0x0b, 0xc4, 0x71, 0x5f, 0x72, + /* (2^200)P */ 0xe6, 0x9c, 0x33, 0xd0, 0x9c, 0xf8, 0xc7, 0x28, 0x8b, 0xc1, 0xdd, 0x69, 0x44, 0xb1, 0x67, 0x83, 0x2c, 0x65, 0xa1, 0xa6, 0x83, 0xda, 0x3a, 0x88, 0x17, 0x6c, 0x4d, 0x03, 0x74, 0x19, 0x5f, 0x58, + /* (2^201)P */ 0x88, 0x91, 0xb1, 0xf1, 0x66, 0xb2, 0xcf, 0x89, 0x17, 0x52, 0xc3, 0xe7, 0x63, 0x48, 0x3b, 0xe6, 0x6a, 0x52, 0xc0, 0xb4, 0xa6, 0x9d, 0x8c, 0xd8, 0x35, 0x46, 0x95, 0xf0, 0x9d, 0x5c, 0x03, 0x3e, + /* (2^202)P */ 0x9d, 0xde, 0x45, 0xfb, 0x12, 0x54, 0x9d, 0xdd, 0x0d, 0xf4, 0xcf, 0xe4, 0x32, 0x45, 0x68, 0xdd, 0x1c, 0x67, 0x1d, 0x15, 0x9b, 0x99, 0x5c, 0x4b, 0x90, 0xf6, 0xe7, 0x11, 0xc8, 0x2c, 0x8c, 0x2d, + /* (2^203)P */ 0x40, 0x5d, 0x05, 0x90, 0x1d, 0xbe, 0x54, 0x7f, 0x40, 0xaf, 0x4a, 0x46, 0xdf, 0xc5, 0x64, 0xa4, 0xbe, 0x17, 0xe9, 0xf0, 0x24, 0x96, 0x97, 0x33, 0x30, 0x6b, 0x35, 0x27, 0xc5, 0x8d, 0x01, 0x2c, + /* (2^204)P */ 0xd4, 0xb3, 0x30, 0xe3, 0x24, 0x50, 0x41, 0xa5, 0xd3, 0x52, 0x16, 0x69, 0x96, 0x3d, 0xff, 0x73, 0xf1, 0x59, 0x9b, 0xef, 0xc4, 0x42, 0xec, 0x94, 0x5a, 0x8e, 0xd0, 0x18, 0x16, 0x20, 0x47, 0x07, + /* (2^205)P */ 0x53, 0x1c, 0x41, 0xca, 0x8a, 0xa4, 0x6c, 0x4d, 0x19, 0x61, 0xa6, 0xcf, 0x2f, 0x5f, 0x41, 0x66, 0xff, 0x27, 0xe2, 0x51, 0x00, 0xd4, 0x4d, 0x9c, 0xeb, 0xf7, 0x02, 0x9a, 0xc0, 0x0b, 0x81, 0x59, + /* (2^206)P */ 0x1d, 0x10, 0xdc, 0xb3, 0x71, 0xb1, 0x7e, 0x2a, 0x8e, 0xf6, 0xfe, 0x9f, 0xb9, 0x5a, 0x1c, 0x44, 0xea, 0x59, 0xb3, 0x93, 0x9b, 0x5c, 0x02, 0x32, 0x2f, 0x11, 0x9d, 0x1e, 0xa7, 0xe0, 0x8c, 0x5e, + /* (2^207)P */ 0xfd, 0x03, 0x95, 0x42, 0x92, 0xcb, 0xcc, 0xbf, 0x55, 0x5d, 0x09, 0x2f, 0x75, 0xba, 0x71, 0xd2, 0x1e, 0x09, 0x2d, 0x97, 0x5e, 0xad, 0x5e, 0x34, 0xba, 0x03, 0x31, 0xa8, 0x11, 0xdf, 0xc8, 0x18, + /* (2^208)P */ 0x4c, 0x0f, 0xed, 0x9a, 0x9a, 0x94, 0xcd, 0x90, 0x7e, 0xe3, 0x60, 0x66, 0xcb, 0xf4, 0xd1, 0xc5, 0x0b, 0x2e, 0xc5, 0x56, 0x2d, 0xc5, 0xca, 0xb8, 0x0d, 0x8e, 0x80, 0xc5, 0x00, 0xe4, 0x42, 0x6e, + /* (2^209)P */ 0x23, 0xfd, 0xae, 0xee, 0x66, 0x69, 0xb4, 0xa3, 0xca, 0xcd, 0x9e, 0xe3, 0x0b, 0x1f, 0x4f, 0x0c, 0x1d, 0xa5, 0x83, 0xd6, 0xc9, 0xc8, 0x9d, 0x18, 0x1b, 0x35, 0x09, 0x4c, 0x05, 0x7f, 0xf2, 0x51, + /* (2^210)P */ 0x82, 0x06, 0x32, 0x2a, 0xcd, 0x7c, 0x48, 0x4c, 0x96, 0x1c, 0xdf, 0xb3, 0x5b, 0xa9, 0x7e, 0x58, 0xe8, 0xb8, 0x5c, 0x55, 0x9e, 0xf7, 0xcc, 0xc8, 0x3d, 0xd7, 0x06, 0xa2, 0x29, 0xc8, 0x7d, 0x54, + /* (2^211)P */ 0x06, 0x9b, 0xc3, 0x80, 0xcd, 0xa6, 0x22, 0xb8, 0xc6, 0xd4, 0x00, 0x20, 0x73, 0x54, 0x6d, 0xe9, 0x4d, 0x3b, 0x46, 0x91, 0x6f, 0x5b, 0x53, 0x28, 0x1d, 0x6e, 0x48, 0xe2, 0x60, 0x46, 0x8f, 0x22, + /* (2^212)P */ 0xbf, 0x3a, 0x8d, 0xde, 0x38, 0x95, 0x79, 0x98, 0x6e, 0xca, 0xeb, 0x45, 0x00, 0x33, 0xd8, 0x8c, 0x38, 0xe7, 0x21, 0x82, 0x00, 0x2a, 0x95, 0x79, 0xbb, 0xd2, 0x5c, 0x53, 0xa7, 0xe1, 0x22, 0x43, + /* (2^213)P */ 0x1c, 0x80, 0xd1, 0x19, 0x18, 0xc1, 0x14, 0xb1, 0xc7, 0x5e, 0x3f, 0x4f, 0xd8, 0xe4, 0x16, 0x20, 0x4c, 0x0f, 0x26, 0x09, 0xf4, 0x2d, 0x0e, 0xdd, 0x66, 0x72, 0x5f, 0xae, 0xc0, 0x62, 0xc3, 0x5e, + /* (2^214)P */ 0xee, 0xb4, 0xb2, 0xb8, 0x18, 0x2b, 0x46, 0xc0, 0xfb, 0x1a, 0x4d, 0x27, 0x50, 0xd9, 0xc8, 0x7c, 0xd2, 0x02, 0x6b, 0x43, 0x05, 0x71, 0x5f, 0xf2, 0xd3, 0xcc, 0xf9, 0xbf, 0xdc, 0xf8, 0xbb, 0x43, + /* (2^215)P */ 0xdf, 0xe9, 0x39, 0xa0, 0x67, 0x17, 0xad, 0xb6, 0x83, 0x35, 0x9d, 0xf6, 0xa8, 0x4d, 0x71, 0xb0, 0xf5, 0x31, 0x29, 0xb4, 0x18, 0xfa, 0x55, 0x5e, 0x61, 0x09, 0xc6, 0x33, 0x8f, 0x55, 0xd5, 0x4e, + /* (2^216)P */ 0xdd, 0xa5, 0x47, 0xc6, 0x01, 0x79, 0xe3, 0x1f, 0x57, 0xd3, 0x81, 0x80, 0x1f, 0xdf, 0x3d, 0x59, 0xa6, 0xd7, 0x3f, 0x81, 0xfd, 0xa4, 0x49, 0x02, 0x61, 0xaf, 0x9c, 0x4e, 0x27, 0xca, 0xac, 0x69, + /* (2^217)P */ 0xc9, 0x21, 0x07, 0x33, 0xea, 0xa3, 0x7b, 0x04, 0xa0, 0x1e, 0x7e, 0x0e, 0xc2, 0x3f, 0x42, 0x83, 0x60, 0x4a, 0x31, 0x01, 0xaf, 0xc0, 0xf4, 0x1d, 0x27, 0x95, 0x28, 0x89, 0xab, 0x2d, 0xa6, 0x09, + /* (2^218)P */ 0x00, 0xcb, 0xc6, 0x9c, 0xa4, 0x25, 0xb3, 0xa5, 0xb6, 0x6c, 0xb5, 0x54, 0xc6, 0x5d, 0x4b, 0xe9, 0xa0, 0x94, 0xc9, 0xad, 0x79, 0x87, 0xe2, 0x3b, 0xad, 0x4a, 0x3a, 0xba, 0xf8, 0xe8, 0x96, 0x42, + /* (2^219)P */ 0xab, 0x1e, 0x45, 0x1e, 0x76, 0x89, 0x86, 0x32, 0x4a, 0x59, 0x59, 0xff, 0x8b, 0x59, 0x4d, 0x2e, 0x4a, 0x08, 0xa7, 0xd7, 0x53, 0x68, 0xb9, 0x49, 0xa8, 0x20, 0x14, 0x60, 0x19, 0xa3, 0x80, 0x49, + /* (2^220)P */ 0x42, 0x2c, 0x55, 0x2f, 0xe1, 0xb9, 0x65, 0x95, 0x96, 0xfe, 0x00, 0x71, 0xdb, 0x18, 0x53, 0x8a, 0xd7, 0xd0, 0xad, 0x43, 0x4d, 0x0b, 0xc9, 0x05, 0xda, 0x4e, 0x5d, 0x6a, 0xd6, 0x4c, 0x8b, 0x53, + /* (2^221)P */ 0x9f, 0x03, 0x9f, 0xe8, 0xc3, 0x4f, 0xe9, 0xf4, 0x45, 0x80, 0x61, 0x6f, 0xf2, 0x9a, 0x2c, 0x59, 0x50, 0x95, 0x4b, 0xfd, 0xb5, 0x6e, 0xa3, 0x08, 0x19, 0x14, 0xed, 0xc2, 0xf6, 0xfa, 0xff, 0x25, + /* (2^222)P */ 0x54, 0xd3, 0x79, 0xcc, 0x59, 0x44, 0x43, 0x34, 0x6b, 0x47, 0xd5, 0xb1, 0xb4, 0xbf, 0xec, 0xee, 0x99, 0x5d, 0x61, 0x61, 0xa0, 0x34, 0xeb, 0xdd, 0x73, 0xb7, 0x64, 0xeb, 0xcc, 0xce, 0x29, 0x51, + /* (2^223)P */ 0x20, 0x35, 0x99, 0x94, 0x58, 0x21, 0x43, 0xee, 0x3b, 0x0b, 0x4c, 0xf1, 0x7c, 0x9c, 0x2f, 0x77, 0xd5, 0xda, 0xbe, 0x06, 0xe3, 0xfc, 0xe2, 0xd2, 0x97, 0x6a, 0xf0, 0x46, 0xb5, 0x42, 0x5f, 0x71, + /* (2^224)P */ 0x1a, 0x5f, 0x5b, 0xda, 0xce, 0xcd, 0x4e, 0x43, 0xa9, 0x41, 0x97, 0xa4, 0x15, 0x71, 0xa1, 0x0d, 0x2e, 0xad, 0xed, 0x73, 0x7c, 0xd7, 0x0b, 0x68, 0x41, 0x90, 0xdd, 0x4e, 0x35, 0x02, 0x7c, 0x48, + /* (2^225)P */ 0xc4, 0xd9, 0x0e, 0xa7, 0xf3, 0xef, 0xef, 0xb8, 0x02, 0xe3, 0x57, 0xe8, 0xa3, 0x2a, 0xa3, 0x56, 0xa0, 0xa5, 0xa2, 0x48, 0xbd, 0x68, 0x3a, 0xdf, 0x44, 0xc4, 0x76, 0x31, 0xb7, 0x50, 0xf6, 0x07, + /* (2^226)P */ 0xb1, 0xcc, 0xe0, 0x26, 0x16, 0x9b, 0x8b, 0xe3, 0x36, 0xfb, 0x09, 0x8b, 0xc1, 0x53, 0xe0, 0x79, 0x64, 0x49, 0xf9, 0xc9, 0x19, 0x03, 0xd9, 0x56, 0xc4, 0xf5, 0x9f, 0xac, 0xe7, 0x41, 0xa9, 0x1c, + /* (2^227)P */ 0xbb, 0xa0, 0x2f, 0x16, 0x29, 0xdf, 0xc4, 0x49, 0x05, 0x33, 0xb3, 0x82, 0x32, 0xcf, 0x88, 0x84, 0x7d, 0x43, 0xbb, 0xca, 0x14, 0xda, 0xdf, 0x95, 0x86, 0xad, 0xd5, 0x64, 0x82, 0xf7, 0x91, 0x33, + /* (2^228)P */ 0x5d, 0x09, 0xb5, 0xe2, 0x6a, 0xe0, 0x9a, 0x72, 0x46, 0xa9, 0x59, 0x32, 0xd7, 0x58, 0x8a, 0xd5, 0xed, 0x21, 0x39, 0xd1, 0x62, 0x42, 0x83, 0xe9, 0x92, 0xb5, 0x4b, 0xa5, 0xfa, 0xda, 0xfe, 0x27, + /* (2^229)P */ 0xbb, 0x48, 0xad, 0x29, 0xb8, 0xc5, 0x9d, 0xa9, 0x60, 0xe2, 0x9e, 0x49, 0x42, 0x57, 0x02, 0x5f, 0xfd, 0x13, 0x75, 0x5d, 0xcd, 0x8e, 0x2c, 0x80, 0x38, 0xd9, 0x6d, 0x3f, 0xef, 0xb3, 0xce, 0x78, + /* (2^230)P */ 0x94, 0x5d, 0x13, 0x8a, 0x4f, 0xf4, 0x42, 0xc3, 0xa3, 0xdd, 0x8c, 0x82, 0x44, 0xdb, 0x9e, 0x7b, 0xe7, 0xcf, 0x37, 0x05, 0x1a, 0xd1, 0x36, 0x94, 0xc8, 0xb4, 0x1a, 0xec, 0x64, 0xb1, 0x64, 0x50, + /* (2^231)P */ 0xfc, 0xb2, 0x7e, 0xd3, 0xcf, 0xec, 0x20, 0x70, 0xfc, 0x25, 0x0d, 0xd9, 0x3e, 0xea, 0x31, 0x1f, 0x34, 0xbb, 0xa1, 0xdf, 0x7b, 0x0d, 0x93, 0x1b, 0x44, 0x30, 0x11, 0x48, 0x7a, 0x46, 0x44, 0x53, + /* (2^232)P */ 0xfb, 0x6d, 0x5e, 0xf2, 0x70, 0x31, 0x07, 0x70, 0xc8, 0x4c, 0x11, 0x50, 0x1a, 0xdc, 0x85, 0xe3, 0x00, 0x4f, 0xfc, 0xc8, 0x8a, 0x69, 0x48, 0x23, 0xd8, 0x40, 0xdd, 0x84, 0x52, 0xa5, 0x77, 0x2a, + /* (2^233)P */ 0xe4, 0x6c, 0x8c, 0xc9, 0xe0, 0xaf, 0x06, 0xfe, 0xe4, 0xd6, 0xdf, 0xdd, 0x96, 0xdf, 0x35, 0xc2, 0xd3, 0x1e, 0xbf, 0x33, 0x1e, 0xd0, 0x28, 0x14, 0xaf, 0xbd, 0x00, 0x93, 0xec, 0x68, 0x57, 0x78, + /* (2^234)P */ 0x3b, 0xb6, 0xde, 0x91, 0x7a, 0xe5, 0x02, 0x97, 0x80, 0x8b, 0xce, 0xe5, 0xbf, 0xb8, 0xbd, 0x61, 0xac, 0x58, 0x1d, 0x3d, 0x6f, 0x42, 0x5b, 0x64, 0xbc, 0x57, 0xa5, 0x27, 0x22, 0xa8, 0x04, 0x48, + /* (2^235)P */ 0x01, 0x26, 0x4d, 0xb4, 0x8a, 0x04, 0x57, 0x8e, 0x35, 0x69, 0x3a, 0x4b, 0x1a, 0x50, 0xd6, 0x68, 0x93, 0xc2, 0xe1, 0xf9, 0xc3, 0x9e, 0x9c, 0xc3, 0xe2, 0x63, 0xde, 0xd4, 0x57, 0xf2, 0x72, 0x41, + /* (2^236)P */ 0x01, 0x64, 0x0c, 0x33, 0x50, 0xb4, 0x68, 0xd3, 0x91, 0x23, 0x8f, 0x41, 0x17, 0x30, 0x0d, 0x04, 0x0d, 0xd9, 0xb7, 0x90, 0x60, 0xbb, 0x34, 0x2c, 0x1f, 0xd5, 0xdf, 0x8f, 0x22, 0x49, 0xf6, 0x16, + /* (2^237)P */ 0xf5, 0x8e, 0x92, 0x2b, 0x8e, 0x81, 0xa6, 0xbe, 0x72, 0x1e, 0xc1, 0xcd, 0x91, 0xcf, 0x8c, 0xe2, 0xcd, 0x36, 0x7a, 0xe7, 0x68, 0xaa, 0x4a, 0x59, 0x0f, 0xfd, 0x7f, 0x6c, 0x80, 0x34, 0x30, 0x31, + /* (2^238)P */ 0x65, 0xbd, 0x49, 0x22, 0xac, 0x27, 0x9d, 0x8a, 0x12, 0x95, 0x8e, 0x01, 0x64, 0xb4, 0xa3, 0x19, 0xc7, 0x7e, 0xb3, 0x52, 0xf3, 0xcf, 0x6c, 0xc2, 0x21, 0x7b, 0x79, 0x1d, 0x34, 0x68, 0x6f, 0x05, + /* (2^239)P */ 0x27, 0x23, 0xfd, 0x7e, 0x75, 0xd6, 0x79, 0x5e, 0x15, 0xfe, 0x3a, 0x55, 0xb6, 0xbc, 0xbd, 0xfa, 0x60, 0x5a, 0xaf, 0x6e, 0x2c, 0x22, 0xe7, 0xd3, 0x3b, 0x74, 0xae, 0x4d, 0x6d, 0xc7, 0x46, 0x70, + /* (2^240)P */ 0x55, 0x4a, 0x8d, 0xb1, 0x72, 0xe8, 0x0b, 0x66, 0x96, 0x14, 0x4e, 0x57, 0x18, 0x25, 0x99, 0x19, 0xbb, 0xdc, 0x2b, 0x30, 0x3a, 0x05, 0x03, 0xc1, 0x8e, 0x8e, 0x21, 0x0b, 0x80, 0xe9, 0xd8, 0x3e, + /* (2^241)P */ 0x3e, 0xe0, 0x75, 0xfa, 0x39, 0x92, 0x0b, 0x7b, 0x83, 0xc0, 0x33, 0x46, 0x68, 0xfb, 0xe9, 0xef, 0x93, 0x77, 0x1a, 0x39, 0xbe, 0x5f, 0xa3, 0x98, 0x34, 0xfe, 0xd0, 0xe2, 0x0f, 0x51, 0x65, 0x60, + /* (2^242)P */ 0x0c, 0xad, 0xab, 0x48, 0x85, 0x66, 0xcb, 0x55, 0x27, 0xe5, 0x87, 0xda, 0x48, 0x45, 0x58, 0xb4, 0xdd, 0xc1, 0x07, 0x01, 0xea, 0xec, 0x43, 0x2c, 0x35, 0xde, 0x72, 0x93, 0x80, 0x28, 0x60, 0x52, + /* (2^243)P */ 0x1f, 0x3b, 0x21, 0xf9, 0x6a, 0xc5, 0x15, 0x34, 0xdb, 0x98, 0x7e, 0x01, 0x4d, 0x1a, 0xee, 0x5b, 0x9b, 0x70, 0xcf, 0xb5, 0x05, 0xb1, 0xf6, 0x13, 0xb6, 0x9a, 0xb2, 0x82, 0x34, 0x0e, 0xf2, 0x5f, + /* (2^244)P */ 0x90, 0x6c, 0x2e, 0xcc, 0x75, 0x9c, 0xa2, 0x0a, 0x06, 0xe2, 0x70, 0x3a, 0xca, 0x73, 0x7d, 0xfc, 0x15, 0xc5, 0xb5, 0xc4, 0x8f, 0xc3, 0x9f, 0x89, 0x07, 0xc2, 0xff, 0x24, 0xb1, 0x86, 0x03, 0x25, + /* (2^245)P */ 0x56, 0x2b, 0x3d, 0xae, 0xd5, 0x28, 0xea, 0x54, 0xce, 0x60, 0xde, 0xd6, 0x9d, 0x14, 0x13, 0x99, 0xc1, 0xd6, 0x06, 0x8f, 0xc5, 0x4f, 0x69, 0x16, 0xc7, 0x8f, 0x01, 0xeb, 0x75, 0x39, 0xb2, 0x46, + /* (2^246)P */ 0xe2, 0xb4, 0xb7, 0xb4, 0x0f, 0x6a, 0x0a, 0x47, 0xde, 0x53, 0x72, 0x8f, 0x5a, 0x47, 0x92, 0x5d, 0xdb, 0x3a, 0xbd, 0x2f, 0xb5, 0xe5, 0xee, 0xab, 0x68, 0x69, 0x80, 0xa0, 0x01, 0x08, 0xa2, 0x7f, + /* (2^247)P */ 0xd2, 0x14, 0x77, 0x9f, 0xf1, 0xfa, 0xf3, 0x76, 0xc3, 0x60, 0x46, 0x2f, 0xc1, 0x40, 0xe8, 0xb3, 0x4e, 0x74, 0x12, 0xf2, 0x8d, 0xcd, 0xb4, 0x0f, 0xd2, 0x2d, 0x3a, 0x1d, 0x25, 0x5a, 0x06, 0x4b, + /* (2^248)P */ 0x4a, 0xcd, 0x77, 0x3d, 0x38, 0xde, 0xeb, 0x5c, 0xb1, 0x9c, 0x2c, 0x88, 0xdf, 0x39, 0xdf, 0x6a, 0x59, 0xf7, 0x9a, 0xb0, 0x2e, 0x24, 0xdd, 0xa2, 0x22, 0x64, 0x5f, 0x0e, 0xe5, 0xc0, 0x47, 0x31, + /* (2^249)P */ 0xdb, 0x50, 0x13, 0x1d, 0x10, 0xa5, 0x4c, 0x16, 0x62, 0xc9, 0x3f, 0xc3, 0x79, 0x34, 0xd1, 0xf8, 0x08, 0xda, 0xe5, 0x13, 0x4d, 0xce, 0x40, 0xe6, 0xba, 0xf8, 0x61, 0x50, 0xc4, 0xe0, 0xde, 0x4b, + /* (2^250)P */ 0xc9, 0xb1, 0xed, 0xa4, 0xc1, 0x6d, 0xc4, 0xd7, 0x8a, 0xd9, 0x7f, 0x43, 0xb6, 0xd7, 0x14, 0x55, 0x0b, 0xc0, 0xa1, 0xb2, 0x6b, 0x2f, 0x94, 0x58, 0x0e, 0x71, 0x70, 0x1d, 0xab, 0xb2, 0xff, 0x2d, + /* (2^251)P */ 0x68, 0x6d, 0x8b, 0xc1, 0x2f, 0xcf, 0xdf, 0xcc, 0x67, 0x61, 0x80, 0xb7, 0xa8, 0xcb, 0xeb, 0xa8, 0xe3, 0x37, 0x29, 0x5e, 0xf9, 0x97, 0x06, 0x98, 0x8c, 0x6e, 0x12, 0xd0, 0x1c, 0xba, 0xfb, 0x02, + /* (2^252)P */ 0x65, 0x45, 0xff, 0xad, 0x60, 0xc3, 0x98, 0xcb, 0x19, 0x15, 0xdb, 0x4b, 0xd2, 0x01, 0x71, 0x44, 0xd5, 0x15, 0xfb, 0x75, 0x74, 0xc8, 0xc4, 0x98, 0x7d, 0xa2, 0x22, 0x6e, 0x6d, 0xc7, 0xf8, 0x05, + /* (2^253)P */ 0x94, 0xf4, 0xb9, 0xfe, 0xdf, 0xe5, 0x69, 0xab, 0x75, 0x6b, 0x40, 0x18, 0x9d, 0xc7, 0x09, 0xae, 0x1d, 0x2d, 0xa4, 0x94, 0xfb, 0x45, 0x9b, 0x19, 0x84, 0xfa, 0x2a, 0xae, 0xeb, 0x0a, 0x71, 0x79, + /* (2^254)P */ 0xdf, 0xd2, 0x34, 0xf3, 0xa7, 0xed, 0xad, 0xa6, 0xb4, 0x57, 0x2a, 0xaf, 0x51, 0x9c, 0xde, 0x7b, 0xa8, 0xea, 0xdc, 0x86, 0x4f, 0xc6, 0x8f, 0xa9, 0x7b, 0xd0, 0x0e, 0xc2, 0x35, 0x03, 0xbe, 0x6b, + /* (2^255)P */ 0x44, 0x43, 0x98, 0x53, 0xbe, 0xdc, 0x7f, 0x66, 0xa8, 0x49, 0x59, 0x00, 0x1c, 0xbc, 0x72, 0x07, 0x8e, 0xd6, 0xbe, 0x4e, 0x9f, 0xa4, 0x07, 0xba, 0xbf, 0x30, 0xdf, 0xba, 0x85, 0xb0, 0xa7, 0x1f, +} diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/curve.go b/src/vendor/github.com/cloudflare/circl/dh/x448/curve.go new file mode 100644 index 00000000000..d59564e4b42 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve.go @@ -0,0 +1,104 @@ +package x448 + +import ( + fp "github.com/cloudflare/circl/math/fp448" +) + +// ladderJoye calculates a fixed-point multiplication with the generator point. +// The algorithm is the right-to-left Joye's ladder as described +// in "How to precompute a ladder" in SAC'2017. +func ladderJoye(k *Key) { + w := [5]fp.Elt{} // [mu,x1,z1,x2,z2] order must be preserved. + w[1] = fp.Elt{ // x1 = S + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + } + fp.SetOne(&w[2]) // z1 = 1 + w[3] = fp.Elt{ // x2 = G-S + 0x20, 0x27, 0x9d, 0xc9, 0x7d, 0x19, 0xb1, 0xac, + 0xf8, 0xba, 0x69, 0x1c, 0xff, 0x33, 0xac, 0x23, + 0x51, 0x1b, 0xce, 0x3a, 0x64, 0x65, 0xbd, 0xf1, + 0x23, 0xf8, 0xc1, 0x84, 0x9d, 0x45, 0x54, 0x29, + 0x67, 0xb9, 0x81, 0x1c, 0x03, 0xd1, 0xcd, 0xda, + 0x7b, 0xeb, 0xff, 0x1a, 0x88, 0x03, 0xcf, 0x3a, + 0x42, 0x44, 0x32, 0x01, 0x25, 0xb7, 0xfa, 0xf0, + } + fp.SetOne(&w[4]) // z2 = 1 + + const n = 448 + const h = 2 + swap := uint(1) + for s := 0; s < n-h; s++ { + i := (s + h) / 8 + j := (s + h) % 8 + bit := uint((k[i] >> uint(j)) & 1) + copy(w[0][:], tableGenerator[s*Size:(s+1)*Size]) + diffAdd(&w, swap^bit) + swap = bit + } + for s := 0; s < h; s++ { + double(&w[1], &w[2]) + } + toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) +} + +// ladderMontgomery calculates a generic scalar point multiplication +// The algorithm implemented is the left-to-right Montgomery's ladder. +func ladderMontgomery(k, xP *Key) { + w := [5]fp.Elt{} // [x1, x2, z2, x3, z3] order must be preserved. + w[0] = *(*fp.Elt)(xP) // x1 = xP + fp.SetOne(&w[1]) // x2 = 1 + w[3] = *(*fp.Elt)(xP) // x3 = xP + fp.SetOne(&w[4]) // z3 = 1 + + move := uint(0) + for s := 448 - 1; s >= 0; s-- { + i := s / 8 + j := s % 8 + bit := uint((k[i] >> uint(j)) & 1) + ladderStep(&w, move^bit) + move = bit + } + toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) +} + +func toAffine(k *[fp.Size]byte, x, z *fp.Elt) { + fp.Inv(z, z) + fp.Mul(x, x, z) + _ = fp.ToBytes(k[:], x) +} + +var lowOrderPoints = [3]fp.Elt{ + { /* (0,_,1) point of order 2 on Curve448 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + { /* (1,_,1) a point of order 4 on the twist of Curve448 */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + { /* (-1,_,1) point of order 4 on Curve448 */ + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, +} diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go new file mode 100644 index 00000000000..a0622666136 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go @@ -0,0 +1,30 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package x448 + +import ( + fp "github.com/cloudflare/circl/math/fp448" + "golang.org/x/sys/cpu" +) + +var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX + +var _ = hasBmi2Adx + +func double(x, z *fp.Elt) { doubleAmd64(x, z) } +func diffAdd(w *[5]fp.Elt, b uint) { diffAddAmd64(w, b) } +func ladderStep(w *[5]fp.Elt, b uint) { ladderStepAmd64(w, b) } +func mulA24(z, x *fp.Elt) { mulA24Amd64(z, x) } + +//go:noescape +func doubleAmd64(x, z *fp.Elt) + +//go:noescape +func diffAddAmd64(w *[5]fp.Elt, b uint) + +//go:noescape +func ladderStepAmd64(w *[5]fp.Elt, b uint) + +//go:noescape +func mulA24Amd64(z, x *fp.Elt) diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h new file mode 100644 index 00000000000..8c1ae4d0fbb --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h @@ -0,0 +1,111 @@ +#define ladderStepLeg \ + addSub(x2,z2) \ + addSub(x3,z3) \ + integerMulLeg(b0,x2,z3) \ + integerMulLeg(b1,x3,z2) \ + reduceFromDoubleLeg(t0,b0) \ + reduceFromDoubleLeg(t1,b1) \ + addSub(t0,t1) \ + cselect(x2,x3,regMove) \ + cselect(z2,z3,regMove) \ + integerSqrLeg(b0,t0) \ + integerSqrLeg(b1,t1) \ + reduceFromDoubleLeg(x3,b0) \ + reduceFromDoubleLeg(z3,b1) \ + integerMulLeg(b0,x1,z3) \ + reduceFromDoubleLeg(z3,b0) \ + integerSqrLeg(b0,x2) \ + integerSqrLeg(b1,z2) \ + reduceFromDoubleLeg(x2,b0) \ + reduceFromDoubleLeg(z2,b1) \ + subtraction(t0,x2,z2) \ + multiplyA24Leg(t1,t0) \ + additionLeg(t1,t1,z2) \ + integerMulLeg(b0,x2,z2) \ + integerMulLeg(b1,t0,t1) \ + reduceFromDoubleLeg(x2,b0) \ + reduceFromDoubleLeg(z2,b1) + +#define ladderStepBmi2Adx \ + addSub(x2,z2) \ + addSub(x3,z3) \ + integerMulAdx(b0,x2,z3) \ + integerMulAdx(b1,x3,z2) \ + reduceFromDoubleAdx(t0,b0) \ + reduceFromDoubleAdx(t1,b1) \ + addSub(t0,t1) \ + cselect(x2,x3,regMove) \ + cselect(z2,z3,regMove) \ + integerSqrAdx(b0,t0) \ + integerSqrAdx(b1,t1) \ + reduceFromDoubleAdx(x3,b0) \ + reduceFromDoubleAdx(z3,b1) \ + integerMulAdx(b0,x1,z3) \ + reduceFromDoubleAdx(z3,b0) \ + integerSqrAdx(b0,x2) \ + integerSqrAdx(b1,z2) \ + reduceFromDoubleAdx(x2,b0) \ + reduceFromDoubleAdx(z2,b1) \ + subtraction(t0,x2,z2) \ + multiplyA24Adx(t1,t0) \ + additionAdx(t1,t1,z2) \ + integerMulAdx(b0,x2,z2) \ + integerMulAdx(b1,t0,t1) \ + reduceFromDoubleAdx(x2,b0) \ + reduceFromDoubleAdx(z2,b1) + +#define difAddLeg \ + addSub(x1,z1) \ + integerMulLeg(b0,z1,ui) \ + reduceFromDoubleLeg(z1,b0) \ + addSub(x1,z1) \ + integerSqrLeg(b0,x1) \ + integerSqrLeg(b1,z1) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) \ + integerMulLeg(b0,x1,z2) \ + integerMulLeg(b1,z1,x2) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) + +#define difAddBmi2Adx \ + addSub(x1,z1) \ + integerMulAdx(b0,z1,ui) \ + reduceFromDoubleAdx(z1,b0) \ + addSub(x1,z1) \ + integerSqrAdx(b0,x1) \ + integerSqrAdx(b1,z1) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) \ + integerMulAdx(b0,x1,z2) \ + integerMulAdx(b1,z1,x2) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) + +#define doubleLeg \ + addSub(x1,z1) \ + integerSqrLeg(b0,x1) \ + integerSqrLeg(b1,z1) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) \ + subtraction(t0,x1,z1) \ + multiplyA24Leg(t1,t0) \ + additionLeg(t1,t1,z1) \ + integerMulLeg(b0,x1,z1) \ + integerMulLeg(b1,t0,t1) \ + reduceFromDoubleLeg(x1,b0) \ + reduceFromDoubleLeg(z1,b1) + +#define doubleBmi2Adx \ + addSub(x1,z1) \ + integerSqrAdx(b0,x1) \ + integerSqrAdx(b1,z1) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) \ + subtraction(t0,x1,z1) \ + multiplyA24Adx(t1,t0) \ + additionAdx(t1,t1,z1) \ + integerMulAdx(b0,x1,z1) \ + integerMulAdx(b1,t0,t1) \ + reduceFromDoubleAdx(x1,b0) \ + reduceFromDoubleAdx(z1,b1) diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s new file mode 100644 index 00000000000..ed33ba3d032 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s @@ -0,0 +1,194 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +#include "textflag.h" + +// Depends on circl/math/fp448 package +#include "../../math/fp448/fp_amd64.h" +#include "curve_amd64.h" + +// CTE_A24 is (A+2)/4 from Curve448 +#define CTE_A24 39082 + +#define Size 56 + +// multiplyA24Leg multiplies x times CTE_A24 and stores in z +// Uses: AX, DX, R8-R15, FLAGS +// Instr: x86_64, cmov, adx +#define multiplyA24Leg(z,x) \ + MOVQ $CTE_A24, R15; \ + MOVQ 0+x, AX; MULQ R15; MOVQ AX, R8; ;;;;;;;;;;;; MOVQ DX, R9; \ + MOVQ 8+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \ + MOVQ 16+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \ + MOVQ 24+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \ + MOVQ 32+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \ + MOVQ 40+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \ + MOVQ 48+x, AX; MULQ R15; ADDQ AX, R14; ADCQ $0, DX; \ + MOVQ DX, AX; \ + SHLQ $32, AX; \ + ADDQ DX, R8; MOVQ $0, DX; \ + ADCQ $0, R9; \ + ADCQ $0, R10; \ + ADCQ AX, R11; \ + ADCQ $0, R12; \ + ADCQ $0, R13; \ + ADCQ $0, R14; \ + ADCQ $0, DX; \ + MOVQ DX, AX; \ + SHLQ $32, AX; \ + ADDQ DX, R8; \ + ADCQ $0, R9; \ + ADCQ $0, R10; \ + ADCQ AX, R11; \ + ADCQ $0, R12; \ + ADCQ $0, R13; \ + ADCQ $0, R14; \ + MOVQ R8, 0+z; \ + MOVQ R9, 8+z; \ + MOVQ R10, 16+z; \ + MOVQ R11, 24+z; \ + MOVQ R12, 32+z; \ + MOVQ R13, 40+z; \ + MOVQ R14, 48+z; + +// multiplyA24Adx multiplies x times CTE_A24 and stores in z +// Uses: AX, DX, R8-R14, FLAGS +// Instr: x86_64, bmi2 +#define multiplyA24Adx(z,x) \ + MOVQ $CTE_A24, DX; \ + MULXQ 0+x, R8, R9; \ + MULXQ 8+x, AX, R10; ADDQ AX, R9; \ + MULXQ 16+x, AX, R11; ADCQ AX, R10; \ + MULXQ 24+x, AX, R12; ADCQ AX, R11; \ + MULXQ 32+x, AX, R13; ADCQ AX, R12; \ + MULXQ 40+x, AX, R14; ADCQ AX, R13; \ + MULXQ 48+x, AX, DX; ADCQ AX, R14; \ + ;;;;;;;;;;;;;;;;;;;; ADCQ $0, DX; \ + MOVQ DX, AX; \ + SHLQ $32, AX; \ + ADDQ DX, R8; MOVQ $0, DX; \ + ADCQ $0, R9; \ + ADCQ $0, R10; \ + ADCQ AX, R11; \ + ADCQ $0, R12; \ + ADCQ $0, R13; \ + ADCQ $0, R14; \ + ADCQ $0, DX; \ + MOVQ DX, AX; \ + SHLQ $32, AX; \ + ADDQ DX, R8; \ + ADCQ $0, R9; \ + ADCQ $0, R10; \ + ADCQ AX, R11; \ + ADCQ $0, R12; \ + ADCQ $0, R13; \ + ADCQ $0, R14; \ + MOVQ R8, 0+z; \ + MOVQ R9, 8+z; \ + MOVQ R10, 16+z; \ + MOVQ R11, 24+z; \ + MOVQ R12, 32+z; \ + MOVQ R13, 40+z; \ + MOVQ R14, 48+z; + +#define mulA24Legacy \ + multiplyA24Leg(0(DI),0(SI)) +#define mulA24Bmi2Adx \ + multiplyA24Adx(0(DI),0(SI)) + +// func mulA24Amd64(z, x *fp448.Elt) +TEXT ·mulA24Amd64(SB),NOSPLIT,$0-16 + MOVQ z+0(FP), DI + MOVQ x+8(FP), SI + CHECK_BMI2ADX(LMA24, mulA24Legacy, mulA24Bmi2Adx) + +// func ladderStepAmd64(w *[5]fp448.Elt, b uint) +// ladderStepAmd64 calculates a point addition and doubling as follows: +// (x2,z2) = 2*(x2,z2) and (x3,z3) = (x2,z2)+(x3,z3) using as a difference (x1,-). +// w = {x1,x2,z2,x3,z4} are five fp255.Elt of 56 bytes. +// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and +// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. +TEXT ·ladderStepAmd64(SB),NOSPLIT,$336-16 + // Parameters + #define regWork DI + #define regMove SI + #define x1 0*Size(regWork) + #define x2 1*Size(regWork) + #define z2 2*Size(regWork) + #define x3 3*Size(regWork) + #define z3 4*Size(regWork) + // Local variables + #define t0 0*Size(SP) + #define t1 1*Size(SP) + #define b0 2*Size(SP) + #define b1 4*Size(SP) + MOVQ w+0(FP), regWork + MOVQ b+8(FP), regMove + CHECK_BMI2ADX(LLADSTEP, ladderStepLeg, ladderStepBmi2Adx) + #undef regWork + #undef regMove + #undef x1 + #undef x2 + #undef z2 + #undef x3 + #undef z3 + #undef t0 + #undef t1 + #undef b0 + #undef b1 + +// func diffAddAmd64(work *[5]fp.Elt, swap uint) +// diffAddAmd64 calculates a differential point addition using a precomputed point. +// (x1,z1) = (x1,z1)+(mu) using a difference point (x2,z2) +// work = {mu,x1,z1,x2,z2} are five fp448.Elt of 56 bytes, and +// stack = (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. +// This is Equation 7 at https://eprint.iacr.org/2017/264. +TEXT ·diffAddAmd64(SB),NOSPLIT,$224-16 + // Parameters + #define regWork DI + #define regSwap SI + #define ui 0*Size(regWork) + #define x1 1*Size(regWork) + #define z1 2*Size(regWork) + #define x2 3*Size(regWork) + #define z2 4*Size(regWork) + // Local variables + #define b0 0*Size(SP) + #define b1 2*Size(SP) + MOVQ w+0(FP), regWork + MOVQ b+8(FP), regSwap + cswap(x1,x2,regSwap) + cswap(z1,z2,regSwap) + CHECK_BMI2ADX(LDIFADD, difAddLeg, difAddBmi2Adx) + #undef regWork + #undef regSwap + #undef ui + #undef x1 + #undef z1 + #undef x2 + #undef z2 + #undef b0 + #undef b1 + +// func doubleAmd64(x, z *fp448.Elt) +// doubleAmd64 calculates a point doubling (x1,z1) = 2*(x1,z1). +// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and +// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. +TEXT ·doubleAmd64(SB),NOSPLIT,$336-16 + // Parameters + #define x1 0(DI) + #define z1 0(SI) + // Local variables + #define t0 0*Size(SP) + #define t1 1*Size(SP) + #define b0 2*Size(SP) + #define b1 4*Size(SP) + MOVQ x+0(FP), DI + MOVQ z+8(FP), SI + CHECK_BMI2ADX(LDOUB,doubleLeg,doubleBmi2Adx) + #undef x1 + #undef z1 + #undef t0 + #undef t1 + #undef b0 + #undef b1 diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go new file mode 100644 index 00000000000..b0b65ccf7eb --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go @@ -0,0 +1,100 @@ +package x448 + +import ( + "encoding/binary" + "math/bits" + + "github.com/cloudflare/circl/math/fp448" +) + +func doubleGeneric(x, z *fp448.Elt) { + t0, t1 := &fp448.Elt{}, &fp448.Elt{} + fp448.AddSub(x, z) + fp448.Sqr(x, x) + fp448.Sqr(z, z) + fp448.Sub(t0, x, z) + mulA24Generic(t1, t0) + fp448.Add(t1, t1, z) + fp448.Mul(x, x, z) + fp448.Mul(z, t0, t1) +} + +func diffAddGeneric(w *[5]fp448.Elt, b uint) { + mu, x1, z1, x2, z2 := &w[0], &w[1], &w[2], &w[3], &w[4] + fp448.Cswap(x1, x2, b) + fp448.Cswap(z1, z2, b) + fp448.AddSub(x1, z1) + fp448.Mul(z1, z1, mu) + fp448.AddSub(x1, z1) + fp448.Sqr(x1, x1) + fp448.Sqr(z1, z1) + fp448.Mul(x1, x1, z2) + fp448.Mul(z1, z1, x2) +} + +func ladderStepGeneric(w *[5]fp448.Elt, b uint) { + x1, x2, z2, x3, z3 := &w[0], &w[1], &w[2], &w[3], &w[4] + t0 := &fp448.Elt{} + t1 := &fp448.Elt{} + fp448.AddSub(x2, z2) + fp448.AddSub(x3, z3) + fp448.Mul(t0, x2, z3) + fp448.Mul(t1, x3, z2) + fp448.AddSub(t0, t1) + fp448.Cmov(x2, x3, b) + fp448.Cmov(z2, z3, b) + fp448.Sqr(x3, t0) + fp448.Sqr(z3, t1) + fp448.Mul(z3, x1, z3) + fp448.Sqr(x2, x2) + fp448.Sqr(z2, z2) + fp448.Sub(t0, x2, z2) + mulA24Generic(t1, t0) + fp448.Add(t1, t1, z2) + fp448.Mul(x2, x2, z2) + fp448.Mul(z2, t0, t1) +} + +func mulA24Generic(z, x *fp448.Elt) { + const A24 = 39082 + const n = 8 + var xx [7]uint64 + for i := range xx { + xx[i] = binary.LittleEndian.Uint64(x[i*n : (i+1)*n]) + } + h0, l0 := bits.Mul64(xx[0], A24) + h1, l1 := bits.Mul64(xx[1], A24) + h2, l2 := bits.Mul64(xx[2], A24) + h3, l3 := bits.Mul64(xx[3], A24) + h4, l4 := bits.Mul64(xx[4], A24) + h5, l5 := bits.Mul64(xx[5], A24) + h6, l6 := bits.Mul64(xx[6], A24) + + l1, c0 := bits.Add64(h0, l1, 0) + l2, c1 := bits.Add64(h1, l2, c0) + l3, c2 := bits.Add64(h2, l3, c1) + l4, c3 := bits.Add64(h3, l4, c2) + l5, c4 := bits.Add64(h4, l5, c3) + l6, c5 := bits.Add64(h5, l6, c4) + l7, _ := bits.Add64(h6, 0, c5) + + l0, c0 = bits.Add64(l0, l7, 0) + l1, c1 = bits.Add64(l1, 0, c0) + l2, c2 = bits.Add64(l2, 0, c1) + l3, c3 = bits.Add64(l3, l7<<32, c2) + l4, c4 = bits.Add64(l4, 0, c3) + l5, c5 = bits.Add64(l5, 0, c4) + l6, l7 = bits.Add64(l6, 0, c5) + + xx[0], c0 = bits.Add64(l0, l7, 0) + xx[1], c1 = bits.Add64(l1, 0, c0) + xx[2], c2 = bits.Add64(l2, 0, c1) + xx[3], c3 = bits.Add64(l3, l7<<32, c2) + xx[4], c4 = bits.Add64(l4, 0, c3) + xx[5], c5 = bits.Add64(l5, 0, c4) + xx[6], _ = bits.Add64(l6, 0, c5) + + for i := range xx { + binary.LittleEndian.PutUint64(z[i*n:(i+1)*n], xx[i]) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go new file mode 100644 index 00000000000..3755b7c83b3 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go @@ -0,0 +1,11 @@ +//go:build !amd64 || purego +// +build !amd64 purego + +package x448 + +import fp "github.com/cloudflare/circl/math/fp448" + +func double(x, z *fp.Elt) { doubleGeneric(x, z) } +func diffAdd(w *[5]fp.Elt, b uint) { diffAddGeneric(w, b) } +func ladderStep(w *[5]fp.Elt, b uint) { ladderStepGeneric(w, b) } +func mulA24(z, x *fp.Elt) { mulA24Generic(z, x) } diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/doc.go b/src/vendor/github.com/cloudflare/circl/dh/x448/doc.go new file mode 100644 index 00000000000..c02904fedae --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/doc.go @@ -0,0 +1,19 @@ +/* +Package x448 provides Diffie-Hellman functions as specified in RFC-7748. + +Validation of public keys. + +The Diffie-Hellman function, as described in RFC-7748 [1], works for any +public key. However, if a different protocol requires contributory +behaviour [2,3], then the public keys must be validated against low-order +points [3,4]. To do that, the Shared function performs this validation +internally and returns false when the public key is invalid (i.e., it +is a low-order point). + +References: + - [1] RFC7748 by Langley, Hamburg, Turner (https://rfc-editor.org/rfc/rfc7748.txt) + - [2] Curve25519 by Bernstein (https://cr.yp.to/ecdh.html) + - [3] Bernstein (https://cr.yp.to/ecdh.html#validate) + - [4] Cremers&Jackson (https://eprint.iacr.org/2019/526) +*/ +package x448 diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/key.go b/src/vendor/github.com/cloudflare/circl/dh/x448/key.go new file mode 100644 index 00000000000..2fdde51168a --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/key.go @@ -0,0 +1,46 @@ +package x448 + +import ( + "crypto/subtle" + + fp "github.com/cloudflare/circl/math/fp448" +) + +// Size is the length in bytes of a X448 key. +const Size = 56 + +// Key represents a X448 key. +type Key [Size]byte + +func (k *Key) clamp(in *Key) *Key { + *k = *in + k[0] &= 252 + k[55] |= 128 + return k +} + +// isValidPubKey verifies if the public key is not a low-order point. +func (k *Key) isValidPubKey() bool { + fp.Modp((*fp.Elt)(k)) + var isLowOrder int + for _, P := range lowOrderPoints { + isLowOrder |= subtle.ConstantTimeCompare(P[:], k[:]) + } + return isLowOrder == 0 +} + +// KeyGen obtains a public key given a secret key. +func KeyGen(public, secret *Key) { + ladderJoye(public.clamp(secret)) +} + +// Shared calculates Alice's shared key from Alice's secret key and Bob's +// public key returning true on success. A failure case happens when the public +// key is a low-order point, thus the shared key is all-zeros and the function +// returns false. +func Shared(shared, secret, public *Key) bool { + validPk := *public + ok := validPk.isValidPubKey() + ladderMontgomery(shared.clamp(secret), &validPk) + return ok +} diff --git a/src/vendor/github.com/cloudflare/circl/dh/x448/table.go b/src/vendor/github.com/cloudflare/circl/dh/x448/table.go new file mode 100644 index 00000000000..eef53c30f80 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/table.go @@ -0,0 +1,460 @@ +package x448 + +import fp "github.com/cloudflare/circl/math/fp448" + +// tableGenerator contains the set of points: +// +// t[i] = (xi+1)/(xi-1), +// +// where (xi,yi) = 2^iG and G is the generator point +// Size = (448)*(448/8) = 25088 bytes. +var tableGenerator = [448 * fp.Size]byte{ + /* (2^ 0)P */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + /* (2^ 1)P */ 0x37, 0xfa, 0xaa, 0x0d, 0x86, 0xa6, 0x24, 0xe9, 0x6c, 0x95, 0x08, 0x34, 0xba, 0x1a, 0x81, 0x3a, 0xae, 0x01, 0xa5, 0xa7, 0x05, 0x85, 0x96, 0x00, 0x06, 0x5a, 0xd7, 0xff, 0xee, 0x8e, 0x8f, 0x94, 0xd2, 0xdc, 0xd7, 0xfc, 0xe7, 0xe5, 0x99, 0x1d, 0x05, 0x46, 0x43, 0xe8, 0xbc, 0x12, 0xb7, 0xeb, 0x30, 0x5e, 0x7a, 0x85, 0x68, 0xed, 0x9d, 0x28, + /* (2^ 2)P */ 0xf1, 0x7d, 0x08, 0x2b, 0x32, 0x4a, 0x62, 0x80, 0x36, 0xe7, 0xa4, 0x76, 0x5a, 0x2a, 0x1e, 0xf7, 0x9e, 0x3c, 0x40, 0x46, 0x9a, 0x1b, 0x61, 0xc1, 0xbf, 0x1a, 0x1b, 0xae, 0x91, 0x80, 0xa3, 0x76, 0x6c, 0xd4, 0x8f, 0xa4, 0xee, 0x26, 0x39, 0x23, 0xa4, 0x80, 0xf4, 0x66, 0x92, 0xe4, 0xe1, 0x18, 0x76, 0xc5, 0xe2, 0x19, 0x87, 0xd5, 0xc3, 0xe8, + /* (2^ 3)P */ 0xfb, 0xc9, 0xf0, 0x07, 0xf2, 0x93, 0xd8, 0x50, 0x36, 0xed, 0xfb, 0xbd, 0xb2, 0xd3, 0xfc, 0xdf, 0xd5, 0x2a, 0x6e, 0x26, 0x09, 0xce, 0xd4, 0x07, 0x64, 0x9f, 0x40, 0x74, 0xad, 0x98, 0x2f, 0x1c, 0xb6, 0xdc, 0x2d, 0x42, 0xff, 0xbf, 0x97, 0xd8, 0xdb, 0xef, 0x99, 0xca, 0x73, 0x99, 0x1a, 0x04, 0x3b, 0x56, 0x2c, 0x1f, 0x87, 0x9d, 0x9f, 0x03, + /* (2^ 4)P */ 0x4c, 0x35, 0x97, 0xf7, 0x81, 0x2c, 0x84, 0xa6, 0xe0, 0xcb, 0xce, 0x37, 0x4c, 0x21, 0x1c, 0x67, 0xfa, 0xab, 0x18, 0x4d, 0xef, 0xd0, 0xf0, 0x44, 0xa9, 0xfb, 0xc0, 0x8e, 0xda, 0x57, 0xa1, 0xd8, 0xeb, 0x87, 0xf4, 0x17, 0xea, 0x66, 0x0f, 0x16, 0xea, 0xcd, 0x5f, 0x3e, 0x88, 0xea, 0x09, 0x68, 0x40, 0xdf, 0x43, 0xcc, 0x54, 0x61, 0x58, 0xaa, + /* (2^ 5)P */ 0x8d, 0xe7, 0x59, 0xd7, 0x5e, 0x63, 0x37, 0xa7, 0x3f, 0xd1, 0x49, 0x85, 0x01, 0xdd, 0x5e, 0xb3, 0xe6, 0x29, 0xcb, 0x25, 0x93, 0xdd, 0x08, 0x96, 0x83, 0x52, 0x76, 0x85, 0xf5, 0x5d, 0x02, 0xbf, 0xe9, 0x6d, 0x15, 0x27, 0xc1, 0x09, 0xd1, 0x14, 0x4d, 0x6e, 0xe8, 0xaf, 0x59, 0x58, 0x34, 0x9d, 0x2a, 0x99, 0x85, 0x26, 0xbe, 0x4b, 0x1e, 0xb9, + /* (2^ 6)P */ 0x8d, 0xce, 0x94, 0xe2, 0x18, 0x56, 0x0d, 0x82, 0x8e, 0xdf, 0x85, 0x01, 0x8f, 0x93, 0x3c, 0xc6, 0xbd, 0x61, 0xfb, 0xf4, 0x22, 0xc5, 0x16, 0x87, 0xd1, 0xb1, 0x9e, 0x09, 0xc5, 0x83, 0x2e, 0x4a, 0x07, 0x88, 0xee, 0xe0, 0x29, 0x8d, 0x2e, 0x1f, 0x88, 0xad, 0xfd, 0x18, 0x93, 0xb7, 0xed, 0x42, 0x86, 0x78, 0xf0, 0xb8, 0x70, 0xbe, 0x01, 0x67, + /* (2^ 7)P */ 0xdf, 0x62, 0x2d, 0x94, 0xc7, 0x35, 0x23, 0xda, 0x27, 0xbb, 0x2b, 0xdb, 0x30, 0x80, 0x68, 0x16, 0xa3, 0xae, 0xd7, 0xd2, 0xa7, 0x7c, 0xbf, 0x6a, 0x1d, 0x83, 0xde, 0x96, 0x0a, 0x43, 0xb6, 0x30, 0x37, 0xd6, 0xee, 0x63, 0x59, 0x9a, 0xbf, 0xa3, 0x30, 0x6c, 0xaf, 0x0c, 0xee, 0x3d, 0xcb, 0x35, 0x4b, 0x55, 0x5f, 0x84, 0x85, 0xcb, 0x4f, 0x1e, + /* (2^ 8)P */ 0x9d, 0x04, 0x68, 0x89, 0xa4, 0xa9, 0x0d, 0x87, 0xc1, 0x70, 0xf1, 0xeb, 0xfb, 0x47, 0x0a, 0xf0, 0xde, 0x67, 0xb7, 0x94, 0xcd, 0x36, 0x43, 0xa5, 0x49, 0x43, 0x67, 0xc3, 0xee, 0x3c, 0x6b, 0xec, 0xd0, 0x1a, 0xf4, 0xad, 0xef, 0x06, 0x4a, 0xe8, 0x46, 0x24, 0xd7, 0x93, 0xbf, 0xf0, 0xe3, 0x81, 0x61, 0xec, 0xea, 0x64, 0xfe, 0x67, 0xeb, 0xc7, + /* (2^ 9)P */ 0x95, 0x45, 0x79, 0xcf, 0x2c, 0xfd, 0x9b, 0xfe, 0x84, 0x46, 0x4b, 0x8f, 0xa1, 0xcf, 0xc3, 0x04, 0x94, 0x78, 0xdb, 0xc9, 0xa6, 0x01, 0x75, 0xa4, 0xb4, 0x93, 0x72, 0x43, 0xa7, 0x7d, 0xda, 0x31, 0x38, 0x54, 0xab, 0x4e, 0x3f, 0x89, 0xa6, 0xab, 0x57, 0xc0, 0x16, 0x65, 0xdb, 0x92, 0x96, 0xe4, 0xc8, 0xae, 0xe7, 0x4c, 0x7a, 0xeb, 0xbb, 0x5a, + /* (2^ 10)P */ 0xbe, 0xfe, 0x86, 0xc3, 0x97, 0xe0, 0x6a, 0x18, 0x20, 0x21, 0xca, 0x22, 0x55, 0xa1, 0xeb, 0xf5, 0x74, 0xe5, 0xc9, 0x59, 0xa7, 0x92, 0x65, 0x15, 0x08, 0x71, 0xd1, 0x09, 0x7e, 0x83, 0xfc, 0xbc, 0x5a, 0x93, 0x38, 0x0d, 0x43, 0x42, 0xfd, 0x76, 0x30, 0xe8, 0x63, 0x60, 0x09, 0x8d, 0x6c, 0xd3, 0xf8, 0x56, 0x3d, 0x68, 0x47, 0xab, 0xa0, 0x1d, + /* (2^ 11)P */ 0x38, 0x50, 0x1c, 0xb1, 0xac, 0x88, 0x8f, 0x38, 0xe3, 0x69, 0xe6, 0xfc, 0x4f, 0x8f, 0xe1, 0x9b, 0xb1, 0x1a, 0x09, 0x39, 0x19, 0xdf, 0xcd, 0x98, 0x7b, 0x64, 0x42, 0xf6, 0x11, 0xea, 0xc7, 0xe8, 0x92, 0x65, 0x00, 0x2c, 0x75, 0xb5, 0x94, 0x1e, 0x5b, 0xa6, 0x66, 0x81, 0x77, 0xf3, 0x39, 0x94, 0xac, 0xbd, 0xe4, 0x2a, 0x66, 0x84, 0x9c, 0x60, + /* (2^ 12)P */ 0xb5, 0xb6, 0xd9, 0x03, 0x67, 0xa4, 0xa8, 0x0a, 0x4a, 0x2b, 0x9d, 0xfa, 0x13, 0xe1, 0x99, 0x25, 0x4a, 0x5c, 0x67, 0xb9, 0xb2, 0xb7, 0xdd, 0x1e, 0xaf, 0xeb, 0x63, 0x41, 0xb6, 0xb9, 0xa0, 0x87, 0x0a, 0xe0, 0x06, 0x07, 0xaa, 0x97, 0xf8, 0xf9, 0x38, 0x4f, 0xdf, 0x0c, 0x40, 0x7c, 0xc3, 0x98, 0xa9, 0x74, 0xf1, 0x5d, 0xda, 0xd1, 0xc0, 0x0a, + /* (2^ 13)P */ 0xf2, 0x0a, 0xab, 0xab, 0x94, 0x50, 0xf0, 0xa3, 0x6f, 0xc6, 0x66, 0xba, 0xa6, 0xdc, 0x44, 0xdd, 0xd6, 0x08, 0xf4, 0xd3, 0xed, 0xb1, 0x40, 0x93, 0xee, 0xf6, 0xb8, 0x8e, 0xb4, 0x7c, 0xb9, 0x82, 0xc9, 0x9d, 0x45, 0x3b, 0x8e, 0x10, 0xcb, 0x70, 0x1e, 0xba, 0x3c, 0x62, 0x50, 0xda, 0xa9, 0x93, 0xb5, 0xd7, 0xd0, 0x6f, 0x29, 0x52, 0x95, 0xae, + /* (2^ 14)P */ 0x14, 0x68, 0x69, 0x23, 0xa8, 0x44, 0x87, 0x9e, 0x22, 0x91, 0xe8, 0x92, 0xdf, 0xf7, 0xae, 0xba, 0x1c, 0x96, 0xe1, 0xc3, 0x94, 0xed, 0x6c, 0x95, 0xae, 0x96, 0xa7, 0x15, 0x9f, 0xf1, 0x17, 0x11, 0x92, 0x42, 0xd5, 0xcd, 0x18, 0xe7, 0xa9, 0xb5, 0x2f, 0xcd, 0xde, 0x6c, 0xc9, 0x7d, 0xfc, 0x7e, 0xbd, 0x7f, 0x10, 0x3d, 0x01, 0x00, 0x8d, 0x95, + /* (2^ 15)P */ 0x3b, 0x76, 0x72, 0xae, 0xaf, 0x84, 0xf2, 0xf7, 0xd1, 0x6d, 0x13, 0x9c, 0x47, 0xe1, 0xb7, 0xa3, 0x19, 0x16, 0xee, 0x75, 0x45, 0xf6, 0x1a, 0x7b, 0x78, 0x49, 0x79, 0x05, 0x86, 0xf0, 0x7f, 0x9f, 0xfc, 0xc4, 0xbd, 0x86, 0xf3, 0x41, 0xa7, 0xfe, 0x01, 0xd5, 0x67, 0x16, 0x10, 0x5b, 0xa5, 0x16, 0xf3, 0x7f, 0x60, 0xce, 0xd2, 0x0c, 0x8e, 0x4b, + /* (2^ 16)P */ 0x4a, 0x07, 0x99, 0x4a, 0x0f, 0x74, 0x91, 0x14, 0x68, 0xb9, 0x48, 0xb7, 0x44, 0x77, 0x9b, 0x4a, 0xe0, 0x68, 0x0e, 0x43, 0x4d, 0x98, 0x98, 0xbf, 0xa8, 0x3a, 0xb7, 0x6d, 0x2a, 0x9a, 0x77, 0x5f, 0x62, 0xf5, 0x6b, 0x4a, 0xb7, 0x7d, 0xe5, 0x09, 0x6b, 0xc0, 0x8b, 0x9c, 0x88, 0x37, 0x33, 0xf2, 0x41, 0xac, 0x22, 0x1f, 0xcf, 0x3b, 0x82, 0x34, + /* (2^ 17)P */ 0x00, 0xc3, 0x78, 0x42, 0x32, 0x2e, 0xdc, 0xda, 0xb1, 0x96, 0x21, 0xa4, 0xe4, 0xbb, 0xe9, 0x9d, 0xbb, 0x0f, 0x93, 0xed, 0x26, 0x3d, 0xb5, 0xdb, 0x94, 0x31, 0x37, 0x07, 0xa2, 0xb2, 0xd5, 0x99, 0x0d, 0x93, 0xe1, 0xce, 0x3f, 0x0b, 0x96, 0x82, 0x47, 0xfe, 0x60, 0x6f, 0x8f, 0x61, 0x88, 0xd7, 0x05, 0x95, 0x0b, 0x46, 0x06, 0xb7, 0x32, 0x06, + /* (2^ 18)P */ 0x44, 0xf5, 0x34, 0xdf, 0x2f, 0x9c, 0x5d, 0x9f, 0x53, 0x5c, 0x42, 0x8f, 0xc9, 0xdc, 0xd8, 0x40, 0xa2, 0xe7, 0x6a, 0x4a, 0x05, 0xf7, 0x86, 0x77, 0x2b, 0xae, 0x37, 0xed, 0x48, 0xfb, 0xf7, 0x62, 0x7c, 0x17, 0x59, 0x92, 0x41, 0x61, 0x93, 0x38, 0x30, 0xd1, 0xef, 0x54, 0x54, 0x03, 0x17, 0x57, 0x91, 0x15, 0x11, 0x33, 0xb5, 0xfa, 0xfb, 0x17, + /* (2^ 19)P */ 0x29, 0xbb, 0xd4, 0xb4, 0x9c, 0xf1, 0x72, 0x94, 0xce, 0x6a, 0x29, 0xa8, 0x89, 0x18, 0x19, 0xf7, 0xb7, 0xcc, 0xee, 0x9a, 0x02, 0xe3, 0xc0, 0xb1, 0xe0, 0xee, 0x83, 0x78, 0xb4, 0x9e, 0x07, 0x87, 0xdf, 0xb0, 0x82, 0x26, 0x4e, 0xa4, 0x0c, 0x33, 0xaf, 0x40, 0x59, 0xb6, 0xdd, 0x52, 0x45, 0xf0, 0xb4, 0xf6, 0xe8, 0x4e, 0x4e, 0x79, 0x1a, 0x5d, + /* (2^ 20)P */ 0x27, 0x33, 0x4d, 0x4c, 0x6b, 0x4f, 0x75, 0xb1, 0xbc, 0x1f, 0xab, 0x5b, 0x2b, 0xf0, 0x1c, 0x57, 0x86, 0xdd, 0xfd, 0x60, 0xb0, 0x8c, 0xe7, 0x9a, 0xe5, 0x5c, 0xeb, 0x11, 0x3a, 0xda, 0x22, 0x25, 0x99, 0x06, 0x8d, 0xf4, 0xaf, 0x29, 0x7a, 0xc9, 0xe5, 0xd2, 0x16, 0x9e, 0xd4, 0x63, 0x1d, 0x64, 0xa6, 0x47, 0x96, 0x37, 0x6f, 0x93, 0x2c, 0xcc, + /* (2^ 21)P */ 0xc1, 0x94, 0x74, 0x86, 0x75, 0xf2, 0x91, 0x58, 0x23, 0x85, 0x63, 0x76, 0x54, 0xc7, 0xb4, 0x8c, 0xbc, 0x4e, 0xc4, 0xa7, 0xba, 0xa0, 0x55, 0x26, 0x71, 0xd5, 0x33, 0x72, 0xc9, 0xad, 0x1e, 0xf9, 0x5d, 0x78, 0x70, 0x93, 0x4e, 0x85, 0xfc, 0x39, 0x06, 0x73, 0x76, 0xff, 0xe8, 0x64, 0x69, 0x42, 0x45, 0xb2, 0x69, 0xb5, 0x32, 0xe7, 0x2c, 0xde, + /* (2^ 22)P */ 0xde, 0x16, 0xd8, 0x33, 0x49, 0x32, 0xe9, 0x0e, 0x3a, 0x60, 0xee, 0x2e, 0x24, 0x75, 0xe3, 0x9c, 0x92, 0x07, 0xdb, 0xad, 0x92, 0xf5, 0x11, 0xdf, 0xdb, 0xb0, 0x17, 0x5c, 0xd6, 0x1a, 0x70, 0x00, 0xb7, 0xe2, 0x18, 0xec, 0xdc, 0xc2, 0x02, 0x93, 0xb3, 0xc8, 0x3f, 0x4f, 0x1b, 0x96, 0xe6, 0x33, 0x8c, 0xfb, 0xcc, 0xa5, 0x4e, 0xe8, 0xe7, 0x11, + /* (2^ 23)P */ 0x05, 0x7a, 0x74, 0x52, 0xf8, 0xdf, 0x0d, 0x7c, 0x6a, 0x1a, 0x4e, 0x9a, 0x02, 0x1d, 0xae, 0x77, 0xf8, 0x8e, 0xf9, 0xa2, 0x38, 0x54, 0x50, 0xb2, 0x2c, 0x08, 0x9d, 0x9b, 0x9f, 0xfb, 0x2b, 0x06, 0xde, 0x9d, 0xc2, 0x03, 0x0b, 0x22, 0x2b, 0x10, 0x5b, 0x3a, 0x73, 0x29, 0x8e, 0x3e, 0x37, 0x08, 0x2c, 0x3b, 0xf8, 0x80, 0xc1, 0x66, 0x1e, 0x98, + /* (2^ 24)P */ 0xd8, 0xd6, 0x3e, 0xcd, 0x63, 0x8c, 0x2b, 0x41, 0x81, 0xc0, 0x0c, 0x06, 0x87, 0xd6, 0xe7, 0x92, 0xfe, 0xf1, 0x0c, 0x4a, 0x84, 0x5b, 0xaf, 0x40, 0x53, 0x6f, 0x60, 0xd6, 0x6b, 0x76, 0x4b, 0xc2, 0xad, 0xc9, 0xb6, 0xb6, 0x6a, 0xa2, 0xb3, 0xf5, 0xf5, 0xc2, 0x55, 0x83, 0xb2, 0xd3, 0xe9, 0x41, 0x6c, 0x63, 0x51, 0xb8, 0x81, 0x74, 0xc8, 0x2c, + /* (2^ 25)P */ 0xb2, 0xaf, 0x1c, 0xee, 0x07, 0xb0, 0x58, 0xa8, 0x2c, 0x6a, 0xc9, 0x2d, 0x62, 0x28, 0x75, 0x0c, 0x40, 0xb6, 0x11, 0x33, 0x96, 0x80, 0x28, 0x6d, 0xd5, 0x9e, 0x87, 0x90, 0x01, 0x66, 0x1d, 0x1c, 0xf8, 0xb4, 0x92, 0xac, 0x38, 0x18, 0x05, 0xc2, 0x4c, 0x4b, 0x54, 0x7d, 0x80, 0x46, 0x87, 0x2d, 0x99, 0x8e, 0x70, 0x80, 0x69, 0x71, 0x8b, 0xed, + /* (2^ 26)P */ 0x37, 0xa7, 0x6b, 0x71, 0x36, 0x75, 0x8e, 0xff, 0x0f, 0x42, 0xda, 0x5a, 0x46, 0xa6, 0x97, 0x79, 0x7e, 0x30, 0xb3, 0x8f, 0xc7, 0x3a, 0xa0, 0xcb, 0x1d, 0x9c, 0x78, 0x77, 0x36, 0xc2, 0xe7, 0xf4, 0x2f, 0x29, 0x07, 0xb1, 0x07, 0xfd, 0xed, 0x1b, 0x39, 0x77, 0x06, 0x38, 0x77, 0x0f, 0x50, 0x31, 0x12, 0xbf, 0x92, 0xbf, 0x72, 0x79, 0x54, 0xa9, + /* (2^ 27)P */ 0xbd, 0x4d, 0x46, 0x6b, 0x1a, 0x80, 0x46, 0x2d, 0xed, 0xfd, 0x64, 0x6d, 0x94, 0xbc, 0x4a, 0x6e, 0x0c, 0x12, 0xf6, 0x12, 0xab, 0x54, 0x88, 0xd3, 0x85, 0xac, 0x51, 0xae, 0x6f, 0xca, 0xc4, 0xb7, 0xec, 0x22, 0x54, 0x6d, 0x80, 0xb2, 0x1c, 0x63, 0x33, 0x76, 0x6b, 0x8e, 0x6d, 0x59, 0xcd, 0x73, 0x92, 0x5f, 0xff, 0xad, 0x10, 0x35, 0x70, 0x5f, + /* (2^ 28)P */ 0xb3, 0x84, 0xde, 0xc8, 0x04, 0x43, 0x63, 0xfa, 0x29, 0xd9, 0xf0, 0x69, 0x65, 0x5a, 0x0c, 0xe8, 0x2e, 0x0b, 0xfe, 0xb0, 0x7a, 0x42, 0xb3, 0xc3, 0xfc, 0xe6, 0xb8, 0x92, 0x29, 0xae, 0xed, 0xec, 0xd5, 0xe8, 0x4a, 0xa1, 0xbd, 0x3b, 0xd3, 0xc0, 0x07, 0xab, 0x65, 0x65, 0x35, 0x9a, 0xa6, 0x5e, 0x78, 0x18, 0x76, 0x1c, 0x15, 0x49, 0xe6, 0x75, + /* (2^ 29)P */ 0x45, 0xb3, 0x92, 0xa9, 0xc3, 0xb8, 0x11, 0x68, 0x64, 0x3a, 0x83, 0x5d, 0xa8, 0x94, 0x6a, 0x9d, 0xaa, 0x27, 0x9f, 0x98, 0x5d, 0xc0, 0x29, 0xf0, 0xc0, 0x4b, 0x14, 0x3c, 0x05, 0xe7, 0xf8, 0xbd, 0x38, 0x22, 0x96, 0x75, 0x65, 0x5e, 0x0d, 0x3f, 0xbb, 0x6f, 0xe8, 0x3f, 0x96, 0x76, 0x9f, 0xba, 0xd9, 0x44, 0x92, 0x96, 0x22, 0xe7, 0x52, 0xe7, + /* (2^ 30)P */ 0xf4, 0xa3, 0x95, 0x90, 0x47, 0xdf, 0x7d, 0xdc, 0xf4, 0x13, 0x87, 0x67, 0x7d, 0x4f, 0x9d, 0xa0, 0x00, 0x46, 0x72, 0x08, 0xc3, 0xa2, 0x7a, 0x3e, 0xe7, 0x6d, 0x52, 0x7c, 0x11, 0x36, 0x50, 0x83, 0x89, 0x64, 0xcb, 0x1f, 0x08, 0x83, 0x46, 0xcb, 0xac, 0xa6, 0xd8, 0x9c, 0x1b, 0xe8, 0x05, 0x47, 0xc7, 0x26, 0x06, 0x83, 0x39, 0xe9, 0xb1, 0x1c, + /* (2^ 31)P */ 0x11, 0xe8, 0xc8, 0x42, 0xbf, 0x30, 0x9c, 0xa3, 0xf1, 0x85, 0x96, 0x95, 0x4f, 0x4f, 0x52, 0xa2, 0xf5, 0x8b, 0x68, 0x24, 0x16, 0xac, 0x9b, 0xa9, 0x27, 0x28, 0x0e, 0x84, 0x03, 0x46, 0x22, 0x5f, 0xf7, 0x0d, 0xa6, 0x85, 0x88, 0xc1, 0x45, 0x4b, 0x85, 0x1a, 0x10, 0x7f, 0xc9, 0x94, 0x20, 0xb0, 0x04, 0x28, 0x12, 0x30, 0xb9, 0xe6, 0x40, 0x6b, + /* (2^ 32)P */ 0xac, 0x1b, 0x57, 0xb6, 0x42, 0xdb, 0x81, 0x8d, 0x76, 0xfd, 0x9b, 0x1c, 0x29, 0x30, 0xd5, 0x3a, 0xcc, 0x53, 0xd9, 0x26, 0x7a, 0x0f, 0x9c, 0x2e, 0x79, 0xf5, 0x62, 0xeb, 0x61, 0x9d, 0x9b, 0x80, 0x39, 0xcd, 0x60, 0x2e, 0x1f, 0x08, 0x22, 0xbc, 0x19, 0xb3, 0x2a, 0x43, 0x44, 0xf2, 0x4e, 0x66, 0xf4, 0x36, 0xa6, 0xa7, 0xbc, 0xa4, 0x15, 0x7e, + /* (2^ 33)P */ 0xc1, 0x90, 0x8a, 0xde, 0xff, 0x78, 0xc3, 0x73, 0x16, 0xee, 0x76, 0xa0, 0x84, 0x60, 0x8d, 0xe6, 0x82, 0x0f, 0xde, 0x4e, 0xc5, 0x99, 0x34, 0x06, 0x90, 0x44, 0x55, 0xf8, 0x91, 0xd8, 0xe1, 0xe4, 0x2c, 0x8a, 0xde, 0x94, 0x1e, 0x78, 0x25, 0x3d, 0xfd, 0xd8, 0x59, 0x7d, 0xaf, 0x6e, 0xbe, 0x96, 0xbe, 0x3c, 0x16, 0x23, 0x0f, 0x4c, 0xa4, 0x28, + /* (2^ 34)P */ 0xba, 0x11, 0x35, 0x57, 0x03, 0xb6, 0xf4, 0x24, 0x89, 0xb8, 0x5a, 0x0d, 0x50, 0x9c, 0xaa, 0x51, 0x7f, 0xa4, 0x0e, 0xfc, 0x71, 0xb3, 0x3b, 0xf1, 0x96, 0x50, 0x23, 0x15, 0xf5, 0xf5, 0xd4, 0x23, 0xdc, 0x8b, 0x26, 0x9e, 0xae, 0xb7, 0x50, 0xcd, 0xc4, 0x25, 0xf6, 0x75, 0x40, 0x9c, 0x37, 0x79, 0x33, 0x60, 0xd4, 0x4b, 0x13, 0x32, 0xee, 0xe2, + /* (2^ 35)P */ 0x43, 0xb8, 0x56, 0x59, 0xf0, 0x68, 0x23, 0xb3, 0xea, 0x70, 0x58, 0x4c, 0x1e, 0x5a, 0x16, 0x54, 0x03, 0xb2, 0xf4, 0x73, 0xb6, 0xd9, 0x5c, 0x9c, 0x6f, 0xcf, 0x82, 0x2e, 0x54, 0x15, 0x46, 0x2c, 0xa3, 0xda, 0x4e, 0x87, 0xf5, 0x2b, 0xba, 0x91, 0xa3, 0xa0, 0x89, 0xba, 0x48, 0x2b, 0xfa, 0x64, 0x02, 0x7f, 0x78, 0x03, 0xd1, 0xe8, 0x3b, 0xe9, + /* (2^ 36)P */ 0x15, 0xa4, 0x71, 0xd4, 0x0c, 0x24, 0xe9, 0x07, 0xa1, 0x43, 0xf4, 0x7f, 0xbb, 0xa2, 0xa6, 0x6b, 0xfa, 0xb7, 0xea, 0x58, 0xd1, 0x96, 0xb0, 0x24, 0x5c, 0xc7, 0x37, 0x4e, 0x60, 0x0f, 0x40, 0xf2, 0x2f, 0x44, 0x70, 0xea, 0x80, 0x63, 0xfe, 0xfc, 0x46, 0x59, 0x12, 0x27, 0xb5, 0x27, 0xfd, 0xb7, 0x73, 0x0b, 0xca, 0x8b, 0xc2, 0xd3, 0x71, 0x08, + /* (2^ 37)P */ 0x26, 0x0e, 0xd7, 0x52, 0x6f, 0xf1, 0xf2, 0x9d, 0xb8, 0x3d, 0xbd, 0xd4, 0x75, 0x97, 0xd8, 0xbf, 0xa8, 0x86, 0x96, 0xa5, 0x80, 0xa0, 0x45, 0x75, 0xf6, 0x77, 0x71, 0xdb, 0x77, 0x96, 0x55, 0x99, 0x31, 0xd0, 0x4f, 0x34, 0xf4, 0x35, 0x39, 0x41, 0xd3, 0x7d, 0xf7, 0xe2, 0x74, 0xde, 0xbe, 0x5b, 0x1f, 0x39, 0x10, 0x21, 0xa3, 0x4d, 0x3b, 0xc8, + /* (2^ 38)P */ 0x04, 0x00, 0x2a, 0x45, 0xb2, 0xaf, 0x9b, 0x18, 0x6a, 0xeb, 0x96, 0x28, 0xa4, 0x77, 0xd0, 0x13, 0xcf, 0x17, 0x65, 0xe8, 0xc5, 0x81, 0x28, 0xad, 0x39, 0x7a, 0x0b, 0xaa, 0x55, 0x2b, 0xf3, 0xfc, 0x86, 0x40, 0xad, 0x0d, 0x1e, 0x28, 0xa2, 0x2d, 0xc5, 0xd6, 0x04, 0x15, 0xa2, 0x30, 0x3d, 0x12, 0x8e, 0xd6, 0xb5, 0xf7, 0x69, 0xbb, 0x84, 0x20, + /* (2^ 39)P */ 0xd7, 0x7a, 0x77, 0x2c, 0xfb, 0x81, 0x80, 0xe9, 0x1e, 0xc6, 0x36, 0x31, 0x79, 0xc3, 0x7c, 0xa9, 0x57, 0x6b, 0xb5, 0x70, 0xfb, 0xe4, 0xa1, 0xff, 0xfd, 0x21, 0xa5, 0x7c, 0xfa, 0x44, 0xba, 0x0d, 0x96, 0x3d, 0xc4, 0x5c, 0x39, 0x52, 0x87, 0xd7, 0x22, 0x0f, 0x52, 0x88, 0x91, 0x87, 0x96, 0xac, 0xfa, 0x3b, 0xdf, 0xdc, 0x83, 0x8c, 0x99, 0x29, + /* (2^ 40)P */ 0x98, 0x6b, 0x3a, 0x8d, 0x83, 0x17, 0xe1, 0x62, 0xd8, 0x80, 0x4c, 0x97, 0xce, 0x6b, 0xaa, 0x10, 0xa7, 0xc4, 0xe9, 0xeb, 0xa5, 0xfb, 0xc9, 0xdd, 0x2d, 0xeb, 0xfc, 0x9a, 0x71, 0xcd, 0x68, 0x6e, 0xc0, 0x35, 0x64, 0x62, 0x1b, 0x95, 0x12, 0xe8, 0x53, 0xec, 0xf0, 0xf4, 0x86, 0x86, 0x78, 0x18, 0xc4, 0xc6, 0xbc, 0x5a, 0x59, 0x8f, 0x7c, 0x7e, + /* (2^ 41)P */ 0x7f, 0xd7, 0x1e, 0xc5, 0x83, 0xdc, 0x1f, 0xbe, 0x0b, 0xcf, 0x2e, 0x01, 0x01, 0xed, 0xac, 0x17, 0x3b, 0xed, 0xa4, 0x30, 0x96, 0x0e, 0x14, 0x7e, 0x19, 0x2b, 0xa5, 0x67, 0x1e, 0xb3, 0x34, 0x03, 0xa8, 0xbb, 0x0a, 0x7d, 0x08, 0x2d, 0xd5, 0x53, 0x19, 0x6f, 0x13, 0xd5, 0xc0, 0x90, 0x8a, 0xcc, 0xc9, 0x5c, 0xab, 0x24, 0xd7, 0x03, 0xf6, 0x57, + /* (2^ 42)P */ 0x49, 0xcb, 0xb4, 0x96, 0x5f, 0xa6, 0xf8, 0x71, 0x6f, 0x59, 0xad, 0x05, 0x24, 0x2d, 0xaf, 0x67, 0xa8, 0xbe, 0x95, 0xdf, 0x0d, 0x28, 0x5a, 0x7f, 0x6e, 0x87, 0x8c, 0x6e, 0x67, 0x0c, 0xf4, 0xe0, 0x1c, 0x30, 0xc2, 0x66, 0xae, 0x20, 0xa1, 0x34, 0xec, 0x9c, 0xbc, 0xae, 0x3d, 0xa1, 0x28, 0x28, 0x95, 0x1d, 0xc9, 0x3a, 0xa8, 0xfd, 0xfc, 0xa1, + /* (2^ 43)P */ 0xe2, 0x2b, 0x9d, 0xed, 0x02, 0x99, 0x67, 0xbb, 0x2e, 0x16, 0x62, 0x05, 0x70, 0xc7, 0x27, 0xb9, 0x1c, 0x3f, 0xf2, 0x11, 0x01, 0xd8, 0x51, 0xa4, 0x18, 0x92, 0xa9, 0x5d, 0xfb, 0xa9, 0xe4, 0x42, 0xba, 0x38, 0x34, 0x1a, 0x4a, 0xc5, 0x6a, 0x37, 0xde, 0xa7, 0x0c, 0xb4, 0x7e, 0x7f, 0xde, 0xa6, 0xee, 0xcd, 0x55, 0x57, 0x05, 0x06, 0xfd, 0x5d, + /* (2^ 44)P */ 0x2f, 0x32, 0xcf, 0x2e, 0x2c, 0x7b, 0xbe, 0x9a, 0x0c, 0x57, 0x35, 0xf8, 0x87, 0xda, 0x9c, 0xec, 0x48, 0xf2, 0xbb, 0xe2, 0xda, 0x10, 0x58, 0x20, 0xc6, 0xd3, 0x87, 0xe9, 0xc7, 0x26, 0xd1, 0x9a, 0x46, 0x87, 0x90, 0xda, 0xdc, 0xde, 0xc3, 0xb3, 0xf2, 0xe8, 0x6f, 0x4a, 0xe6, 0xe8, 0x9d, 0x98, 0x36, 0x20, 0x03, 0x47, 0x15, 0x3f, 0x64, 0x59, + /* (2^ 45)P */ 0xd4, 0x71, 0x49, 0x0a, 0x67, 0x97, 0xaa, 0x3f, 0xf4, 0x1b, 0x3a, 0x6e, 0x5e, 0x17, 0xcc, 0x0a, 0x8f, 0x81, 0x6a, 0x41, 0x38, 0x77, 0x40, 0x8a, 0x11, 0x42, 0x62, 0xd2, 0x50, 0x32, 0x79, 0x78, 0x28, 0xc2, 0x2e, 0x10, 0x01, 0x94, 0x30, 0x4f, 0x7f, 0x18, 0x17, 0x56, 0x85, 0x4e, 0xad, 0xf7, 0xcb, 0x87, 0x3c, 0x3f, 0x50, 0x2c, 0xc0, 0xba, + /* (2^ 46)P */ 0xbc, 0x30, 0x8e, 0x65, 0x8e, 0x57, 0x5b, 0x38, 0x7a, 0xd4, 0x95, 0x52, 0x7a, 0x32, 0x59, 0x69, 0xcd, 0x9d, 0x47, 0x34, 0x5b, 0x55, 0xa5, 0x24, 0x60, 0xdd, 0xc0, 0xc1, 0x62, 0x73, 0x44, 0xae, 0x4c, 0x9c, 0x65, 0x55, 0x1b, 0x9d, 0x8a, 0x29, 0xb0, 0x1a, 0x52, 0xa8, 0xf1, 0xe6, 0x9a, 0xb3, 0xf6, 0xa3, 0xc9, 0x0a, 0x70, 0x7d, 0x0f, 0xee, + /* (2^ 47)P */ 0x77, 0xd3, 0xe5, 0x8e, 0xfa, 0x00, 0xeb, 0x1b, 0x7f, 0xdc, 0x68, 0x3f, 0x92, 0xbd, 0xb7, 0x0b, 0xb7, 0xb5, 0x24, 0xdf, 0xc5, 0x67, 0x53, 0xd4, 0x36, 0x79, 0xc4, 0x7b, 0x57, 0xbc, 0x99, 0x97, 0x60, 0xef, 0xe4, 0x01, 0xa1, 0xa7, 0xaa, 0x12, 0x36, 0x29, 0xb1, 0x03, 0xc2, 0x83, 0x1c, 0x2b, 0x83, 0xef, 0x2e, 0x2c, 0x23, 0x92, 0xfd, 0xd1, + /* (2^ 48)P */ 0x94, 0xef, 0x03, 0x59, 0xfa, 0x8a, 0x18, 0x76, 0xee, 0x58, 0x08, 0x4d, 0x44, 0xce, 0xf1, 0x52, 0x33, 0x49, 0xf6, 0x69, 0x71, 0xe3, 0xa9, 0xbc, 0x86, 0xe3, 0x43, 0xde, 0x33, 0x7b, 0x90, 0x8b, 0x3e, 0x7d, 0xd5, 0x4a, 0xf0, 0x23, 0x99, 0xa6, 0xea, 0x5f, 0x08, 0xe5, 0xb9, 0x49, 0x8b, 0x0d, 0x6a, 0x21, 0xab, 0x07, 0x62, 0xcd, 0xc4, 0xbe, + /* (2^ 49)P */ 0x61, 0xbf, 0x70, 0x14, 0xfa, 0x4e, 0x9e, 0x7c, 0x0c, 0xf8, 0xb2, 0x48, 0x71, 0x62, 0x83, 0xd6, 0xd1, 0xdc, 0x9c, 0x29, 0x66, 0xb1, 0x34, 0x9c, 0x8d, 0xe6, 0x88, 0xaf, 0xbe, 0xdc, 0x4d, 0xeb, 0xb0, 0xe7, 0x28, 0xae, 0xb2, 0x05, 0x56, 0xc6, 0x0e, 0x10, 0x26, 0xab, 0x2c, 0x59, 0x72, 0x03, 0x66, 0xfe, 0x8f, 0x2c, 0x51, 0x2d, 0xdc, 0xae, + /* (2^ 50)P */ 0xdc, 0x63, 0xf1, 0x8b, 0x5c, 0x65, 0x0b, 0xf1, 0xa6, 0x22, 0xe2, 0xd9, 0xdb, 0x49, 0xb1, 0x3c, 0x47, 0xc2, 0xfe, 0xac, 0x86, 0x07, 0x52, 0xec, 0xb0, 0x08, 0x69, 0xfb, 0xd1, 0x06, 0xdc, 0x48, 0x5c, 0x3d, 0xb2, 0x4d, 0xb8, 0x1a, 0x4e, 0xda, 0xb9, 0xc1, 0x2b, 0xab, 0x4b, 0x62, 0x81, 0x21, 0x9a, 0xfc, 0x3d, 0x39, 0x83, 0x11, 0x36, 0xeb, + /* (2^ 51)P */ 0x94, 0xf3, 0x17, 0xef, 0xf9, 0x60, 0x54, 0xc3, 0xd7, 0x27, 0x35, 0xc5, 0x98, 0x5e, 0xf6, 0x63, 0x6c, 0xa0, 0x4a, 0xd3, 0xa3, 0x98, 0xd9, 0x42, 0xe3, 0xf1, 0xf8, 0x81, 0x96, 0xa9, 0xea, 0x6d, 0x4b, 0x8e, 0x33, 0xca, 0x94, 0x0d, 0xa0, 0xf7, 0xbb, 0x64, 0xa3, 0x36, 0x6f, 0xdc, 0x5a, 0x94, 0x42, 0xca, 0x06, 0xb2, 0x2b, 0x9a, 0x9f, 0x71, + /* (2^ 52)P */ 0xec, 0xdb, 0xa6, 0x1f, 0xdf, 0x15, 0x36, 0xa3, 0xda, 0x8a, 0x7a, 0xb6, 0xa7, 0xe3, 0xaf, 0x52, 0xe0, 0x8d, 0xe8, 0xf2, 0x44, 0x20, 0xeb, 0xa1, 0x20, 0xc4, 0x65, 0x3c, 0x7c, 0x6c, 0x49, 0xed, 0x2f, 0x66, 0x23, 0x68, 0x61, 0x91, 0x40, 0x9f, 0x50, 0x19, 0xd1, 0x84, 0xa7, 0xe2, 0xed, 0x34, 0x37, 0xe3, 0xe4, 0x11, 0x7f, 0x87, 0x55, 0x0f, + /* (2^ 53)P */ 0xb3, 0xa1, 0x0f, 0xb0, 0x48, 0xc0, 0x4d, 0x96, 0xa7, 0xcf, 0x5a, 0x81, 0xb8, 0x4a, 0x46, 0xef, 0x0a, 0xd3, 0x40, 0x7e, 0x02, 0xe3, 0x63, 0xaa, 0x50, 0xd1, 0x2a, 0x37, 0x22, 0x4a, 0x7f, 0x4f, 0xb6, 0xf9, 0x01, 0x82, 0x78, 0x3d, 0x93, 0x14, 0x11, 0x8a, 0x90, 0x60, 0xcd, 0x45, 0x4e, 0x7b, 0x42, 0xb9, 0x3e, 0x6e, 0x68, 0x1f, 0x36, 0x41, + /* (2^ 54)P */ 0x13, 0x73, 0x0e, 0x4f, 0x79, 0x93, 0x9e, 0x29, 0x70, 0x7b, 0x4a, 0x59, 0x1a, 0x9a, 0xf4, 0x55, 0x08, 0xf0, 0xdb, 0x17, 0x58, 0xec, 0x64, 0xad, 0x7f, 0x29, 0xeb, 0x3f, 0x85, 0x4e, 0x60, 0x28, 0x98, 0x1f, 0x73, 0x4e, 0xe6, 0xa8, 0xab, 0xd5, 0xd6, 0xfc, 0xa1, 0x36, 0x6d, 0x15, 0xc6, 0x13, 0x83, 0xa0, 0xc2, 0x6e, 0xd9, 0xdb, 0xc9, 0xcc, + /* (2^ 55)P */ 0xff, 0xd8, 0x52, 0xa3, 0xdc, 0x99, 0xcf, 0x3e, 0x19, 0xb3, 0x68, 0xd0, 0xb5, 0x0d, 0xb8, 0xee, 0x3f, 0xef, 0x6e, 0xc0, 0x38, 0x28, 0x44, 0x92, 0x78, 0x91, 0x1a, 0x08, 0x78, 0x6c, 0x65, 0x24, 0xf3, 0xa2, 0x3d, 0xf2, 0xe5, 0x79, 0x62, 0x69, 0x29, 0xf4, 0x22, 0xc5, 0xdb, 0x6a, 0xae, 0xf4, 0x44, 0xa3, 0x6f, 0xc7, 0x86, 0xab, 0xef, 0xef, + /* (2^ 56)P */ 0xbf, 0x54, 0x9a, 0x09, 0x5d, 0x17, 0xd0, 0xde, 0xfb, 0xf5, 0xca, 0xff, 0x13, 0x20, 0x88, 0x82, 0x3a, 0xe2, 0xd0, 0x3b, 0xfb, 0x05, 0x76, 0xd1, 0xc0, 0x02, 0x71, 0x3b, 0x94, 0xe8, 0xc9, 0x84, 0xcf, 0xa4, 0xe9, 0x28, 0x7b, 0xf5, 0x09, 0xc3, 0x2b, 0x22, 0x40, 0xf1, 0x68, 0x24, 0x24, 0x7d, 0x9f, 0x6e, 0xcd, 0xfe, 0xb0, 0x19, 0x61, 0xf5, + /* (2^ 57)P */ 0xe8, 0x63, 0x51, 0xb3, 0x95, 0x6b, 0x7b, 0x74, 0x92, 0x52, 0x45, 0xa4, 0xed, 0xea, 0x0e, 0x0d, 0x2b, 0x01, 0x1e, 0x2c, 0xbc, 0x91, 0x06, 0x69, 0xdb, 0x1f, 0xb5, 0x77, 0x1d, 0x56, 0xf5, 0xb4, 0x02, 0x80, 0x49, 0x56, 0x12, 0xce, 0x86, 0x05, 0xc9, 0xd9, 0xae, 0xf3, 0x6d, 0xe6, 0x3f, 0x40, 0x52, 0xe9, 0x49, 0x2b, 0x31, 0x06, 0x86, 0x14, + /* (2^ 58)P */ 0xf5, 0x09, 0x3b, 0xd2, 0xff, 0xdf, 0x11, 0xa5, 0x1c, 0x99, 0xe8, 0x1b, 0xa4, 0x2c, 0x7d, 0x8e, 0xc8, 0xf7, 0x03, 0x46, 0xfa, 0xb6, 0xde, 0x73, 0x91, 0x7e, 0x5a, 0x7a, 0xd7, 0x9a, 0x5b, 0x80, 0x24, 0x62, 0x5e, 0x92, 0xf1, 0xa3, 0x45, 0xa3, 0x43, 0x92, 0x8a, 0x2a, 0x5b, 0x0c, 0xb4, 0xc8, 0xad, 0x1c, 0xb6, 0x6c, 0x5e, 0x81, 0x18, 0x91, + /* (2^ 59)P */ 0x96, 0xb3, 0xca, 0x2b, 0xe3, 0x7a, 0x59, 0x72, 0x17, 0x74, 0x29, 0x21, 0xe7, 0x78, 0x07, 0xad, 0xda, 0xb6, 0xcd, 0xf9, 0x27, 0x4d, 0xc8, 0xf2, 0x98, 0x22, 0xca, 0xf2, 0x33, 0x74, 0x7a, 0xdd, 0x1e, 0x71, 0xec, 0xe3, 0x3f, 0xe2, 0xa2, 0xd2, 0x38, 0x75, 0xb0, 0xd0, 0x0a, 0xcf, 0x7d, 0x36, 0xdc, 0x49, 0x38, 0x25, 0x34, 0x4f, 0x20, 0x9a, + /* (2^ 60)P */ 0x2b, 0x6e, 0x04, 0x0d, 0x4f, 0x3d, 0x3b, 0x24, 0xf6, 0x4e, 0x5e, 0x0a, 0xbd, 0x48, 0x96, 0xba, 0x81, 0x8f, 0x39, 0x82, 0x13, 0xe6, 0x72, 0xf3, 0x0f, 0xb6, 0x94, 0xf4, 0xc5, 0x90, 0x74, 0x91, 0xa8, 0xf2, 0xc9, 0xca, 0x9a, 0x4d, 0x98, 0xf2, 0xdf, 0x52, 0x4e, 0x97, 0x2f, 0xeb, 0x84, 0xd3, 0xaf, 0xc2, 0xcc, 0xfb, 0x4c, 0x26, 0x4b, 0xe4, + /* (2^ 61)P */ 0x12, 0x9e, 0xfb, 0x9d, 0x78, 0x79, 0x99, 0xdd, 0xb3, 0x0b, 0x2e, 0x56, 0x41, 0x8e, 0x3f, 0x39, 0xb8, 0x97, 0x89, 0x53, 0x9b, 0x8a, 0x3c, 0x40, 0x9d, 0xa4, 0x6c, 0x2e, 0x31, 0x71, 0xc6, 0x0a, 0x41, 0xd4, 0x95, 0x06, 0x5e, 0xc1, 0xab, 0xc2, 0x14, 0xc4, 0xc7, 0x15, 0x08, 0x3a, 0xad, 0x7a, 0xb4, 0x62, 0xa3, 0x0c, 0x90, 0xf4, 0x47, 0x08, + /* (2^ 62)P */ 0x7f, 0xec, 0x09, 0x82, 0xf5, 0x94, 0x09, 0x93, 0x32, 0xd3, 0xdc, 0x56, 0x80, 0x7b, 0x5b, 0x22, 0x80, 0x6a, 0x96, 0x72, 0xb1, 0xc2, 0xd9, 0xa1, 0x8b, 0x66, 0x42, 0x16, 0xe2, 0x07, 0xb3, 0x2d, 0xf1, 0x75, 0x35, 0x72, 0xc7, 0x98, 0xbe, 0x63, 0x3b, 0x20, 0x75, 0x05, 0xc1, 0x3e, 0x31, 0x5a, 0xf7, 0xaa, 0xae, 0x4b, 0xdb, 0x1d, 0xd0, 0x74, + /* (2^ 63)P */ 0x36, 0x5c, 0x74, 0xe6, 0x5d, 0x59, 0x3f, 0x15, 0x4b, 0x4d, 0x4e, 0x67, 0x41, 0xfe, 0x98, 0x1f, 0x49, 0x76, 0x91, 0x0f, 0x9b, 0xf4, 0xaf, 0x86, 0xaf, 0x66, 0x19, 0xed, 0x46, 0xf1, 0x05, 0x9a, 0xcc, 0xd1, 0x14, 0x1f, 0x82, 0x12, 0x8e, 0xe6, 0xf4, 0xc3, 0x42, 0x5c, 0x4e, 0x33, 0x93, 0xbe, 0x30, 0xe7, 0x64, 0xa9, 0x35, 0x00, 0x4d, 0xf9, + /* (2^ 64)P */ 0x1f, 0xc1, 0x1e, 0xb7, 0xe3, 0x7c, 0xfa, 0xa3, 0x6b, 0x76, 0xaf, 0x9c, 0x05, 0x85, 0x4a, 0xa9, 0xfb, 0xe3, 0x7e, 0xf2, 0x49, 0x56, 0xdc, 0x2f, 0x57, 0x10, 0xba, 0x37, 0xb2, 0x62, 0xf5, 0x6b, 0xe5, 0x8f, 0x0a, 0x87, 0xd1, 0x6a, 0xcb, 0x9d, 0x07, 0xd0, 0xf6, 0x38, 0x99, 0x2c, 0x61, 0x4a, 0x4e, 0xd8, 0xd2, 0x88, 0x29, 0x99, 0x11, 0x95, + /* (2^ 65)P */ 0x6f, 0xdc, 0xd5, 0xd6, 0xd6, 0xa7, 0x4c, 0x46, 0x93, 0x65, 0x62, 0x23, 0x95, 0x32, 0x9c, 0xde, 0x40, 0x41, 0x68, 0x2c, 0x18, 0x4e, 0x5a, 0x8c, 0xc0, 0xc5, 0xc5, 0xea, 0x5c, 0x45, 0x0f, 0x60, 0x78, 0x39, 0xb6, 0x36, 0x23, 0x12, 0xbc, 0x21, 0x9a, 0xf8, 0x91, 0xac, 0xc4, 0x70, 0xdf, 0x85, 0x8e, 0x3c, 0xec, 0x22, 0x04, 0x98, 0xa8, 0xaa, + /* (2^ 66)P */ 0xcc, 0x52, 0x10, 0x5b, 0x4b, 0x6c, 0xc5, 0xfa, 0x3e, 0xd4, 0xf8, 0x1c, 0x04, 0x14, 0x48, 0x33, 0xd9, 0xfc, 0x5f, 0xb0, 0xa5, 0x48, 0x8c, 0x45, 0x8a, 0xee, 0x3e, 0xa7, 0xc1, 0x2e, 0x34, 0xca, 0xf6, 0xc9, 0xeb, 0x10, 0xbb, 0xe1, 0x59, 0x84, 0x25, 0xe8, 0x81, 0x70, 0xc0, 0x09, 0x42, 0xa7, 0x3b, 0x0d, 0x33, 0x00, 0xb5, 0x77, 0xbe, 0x25, + /* (2^ 67)P */ 0xcd, 0x1f, 0xbc, 0x7d, 0xef, 0xe5, 0xca, 0x91, 0xaf, 0xa9, 0x59, 0x6a, 0x09, 0xca, 0xd6, 0x1b, 0x3d, 0x55, 0xde, 0xa2, 0x6a, 0x80, 0xd6, 0x95, 0x47, 0xe4, 0x5f, 0x68, 0x54, 0x08, 0xdf, 0x29, 0xba, 0x2a, 0x02, 0x84, 0xe8, 0xe9, 0x00, 0x77, 0x99, 0x36, 0x03, 0xf6, 0x4a, 0x3e, 0x21, 0x81, 0x7d, 0xb8, 0xa4, 0x8a, 0xa2, 0x05, 0xef, 0xbc, + /* (2^ 68)P */ 0x7c, 0x59, 0x5f, 0x66, 0xd9, 0xb7, 0x83, 0x43, 0x8a, 0xa1, 0x8d, 0x51, 0x70, 0xba, 0xf2, 0x9b, 0x95, 0xc0, 0x4b, 0x4c, 0xa0, 0x14, 0xd3, 0xa4, 0x5d, 0x4a, 0x37, 0x36, 0x97, 0x31, 0x1e, 0x12, 0xe7, 0xbb, 0x08, 0x67, 0xa5, 0x23, 0xd7, 0xfb, 0x97, 0xd8, 0x6a, 0x03, 0xb1, 0xf8, 0x7f, 0xda, 0x58, 0xd9, 0x3f, 0x73, 0x4a, 0x53, 0xe1, 0x7b, + /* (2^ 69)P */ 0x55, 0x83, 0x98, 0x78, 0x6c, 0x56, 0x5e, 0xed, 0xf7, 0x23, 0x3e, 0x4c, 0x7d, 0x09, 0x2d, 0x09, 0x9c, 0x58, 0x8b, 0x32, 0xca, 0xfe, 0xbf, 0x47, 0x03, 0xeb, 0x4d, 0xe7, 0xeb, 0x9c, 0x83, 0x05, 0x68, 0xaa, 0x80, 0x89, 0x44, 0xf9, 0xd4, 0xdc, 0xdb, 0xb1, 0xdb, 0x77, 0xac, 0xf9, 0x2a, 0xae, 0x35, 0xac, 0x74, 0xb5, 0x95, 0x62, 0x18, 0x85, + /* (2^ 70)P */ 0xab, 0x82, 0x7e, 0x10, 0xd7, 0xe6, 0x57, 0xd1, 0x66, 0x12, 0x31, 0x9c, 0x9c, 0xa6, 0x27, 0x59, 0x71, 0x2e, 0xeb, 0xa0, 0x68, 0xc5, 0x87, 0x51, 0xf4, 0xca, 0x3f, 0x98, 0x56, 0xb0, 0x89, 0xb1, 0xc7, 0x7b, 0x46, 0xb3, 0xae, 0x36, 0xf2, 0xee, 0x15, 0x1a, 0x60, 0xf4, 0x50, 0x76, 0x4f, 0xc4, 0x53, 0x0d, 0x36, 0x4d, 0x31, 0xb1, 0x20, 0x51, + /* (2^ 71)P */ 0xf7, 0x1d, 0x8c, 0x1b, 0x5e, 0xe5, 0x02, 0x6f, 0xc5, 0xa5, 0xe0, 0x5f, 0xc6, 0xb6, 0x63, 0x43, 0xaf, 0x3c, 0x19, 0x6c, 0xf4, 0xaf, 0xa4, 0x33, 0xb1, 0x0a, 0x37, 0x3d, 0xd9, 0x4d, 0xe2, 0x29, 0x24, 0x26, 0x94, 0x7c, 0x02, 0xe4, 0xe2, 0xf2, 0xbe, 0xbd, 0xac, 0x1b, 0x48, 0xb8, 0xdd, 0xe9, 0x0d, 0x9a, 0x50, 0x1a, 0x98, 0x71, 0x6e, 0xdc, + /* (2^ 72)P */ 0x9f, 0x40, 0xb1, 0xb3, 0x66, 0x28, 0x6c, 0xfe, 0xa6, 0x7d, 0xf8, 0x3e, 0xb8, 0xf3, 0xde, 0x52, 0x76, 0x52, 0xa3, 0x92, 0x98, 0x23, 0xab, 0x4f, 0x88, 0x97, 0xfc, 0x22, 0xe1, 0x6b, 0x67, 0xcd, 0x13, 0x95, 0xda, 0x65, 0xdd, 0x3b, 0x67, 0x3f, 0x5f, 0x4c, 0xf2, 0x8a, 0xad, 0x98, 0xa7, 0x94, 0x24, 0x45, 0x87, 0x11, 0x7c, 0x75, 0x79, 0x85, + /* (2^ 73)P */ 0x70, 0xbf, 0xf9, 0x3b, 0xa9, 0x44, 0x57, 0x72, 0x96, 0xc9, 0xa4, 0x98, 0x65, 0xbf, 0x87, 0xb3, 0x3a, 0x39, 0x12, 0xde, 0xe5, 0x39, 0x01, 0x4f, 0xf7, 0xc0, 0x71, 0x52, 0x36, 0x85, 0xb3, 0x18, 0xf8, 0x14, 0xc0, 0x6d, 0xae, 0x9e, 0x4f, 0xb0, 0x72, 0x87, 0xac, 0x5c, 0xd1, 0x6c, 0x41, 0x6c, 0x90, 0x9d, 0x22, 0x81, 0xe4, 0x2b, 0xea, 0xe5, + /* (2^ 74)P */ 0xfc, 0xea, 0x1a, 0x65, 0xd9, 0x49, 0x6a, 0x39, 0xb5, 0x96, 0x72, 0x7b, 0x32, 0xf1, 0xd0, 0xe9, 0x45, 0xd9, 0x31, 0x55, 0xc7, 0x34, 0xe9, 0x5a, 0xec, 0x73, 0x0b, 0x03, 0xc4, 0xb3, 0xe6, 0xc9, 0x5e, 0x0a, 0x17, 0xfe, 0x53, 0x66, 0x7f, 0x21, 0x18, 0x74, 0x54, 0x1b, 0xc9, 0x49, 0x16, 0xd2, 0x48, 0xaf, 0x5b, 0x47, 0x7b, 0xeb, 0xaa, 0xc9, + /* (2^ 75)P */ 0x47, 0x04, 0xf5, 0x5a, 0x87, 0x77, 0x9e, 0x21, 0x34, 0x4e, 0x83, 0x88, 0xaf, 0x02, 0x1d, 0xb0, 0x5a, 0x1d, 0x1d, 0x7d, 0x8d, 0x2c, 0xd3, 0x8d, 0x63, 0xa9, 0x45, 0xfb, 0x15, 0x6d, 0x86, 0x45, 0xcd, 0x38, 0x0e, 0xf7, 0x37, 0x79, 0xed, 0x6d, 0x5a, 0xbc, 0x32, 0xcc, 0x66, 0xf1, 0x3a, 0xb2, 0x87, 0x6f, 0x70, 0x71, 0xd9, 0xf2, 0xfa, 0x7b, + /* (2^ 76)P */ 0x68, 0x07, 0xdc, 0x61, 0x40, 0xe4, 0xec, 0x32, 0xc8, 0xbe, 0x66, 0x30, 0x54, 0x80, 0xfd, 0x13, 0x7a, 0xef, 0xae, 0xed, 0x2e, 0x00, 0x6d, 0x3f, 0xbd, 0xfc, 0x91, 0x24, 0x53, 0x7f, 0x63, 0x9d, 0x2e, 0xe3, 0x76, 0xe0, 0xf3, 0xe1, 0x8f, 0x7a, 0xc4, 0x77, 0x0c, 0x91, 0xc0, 0xc2, 0x18, 0x6b, 0x04, 0xad, 0xb6, 0x70, 0x9a, 0x64, 0xc5, 0x82, + /* (2^ 77)P */ 0x7f, 0xea, 0x13, 0xd8, 0x9e, 0xfc, 0x5b, 0x06, 0xb5, 0x4f, 0xda, 0x38, 0xe0, 0x9c, 0xd2, 0x3a, 0xc1, 0x1c, 0x62, 0x70, 0x7f, 0xc6, 0x24, 0x0a, 0x47, 0x04, 0x01, 0xc4, 0x55, 0x09, 0xd1, 0x7a, 0x07, 0xba, 0xa3, 0x80, 0x4f, 0xc1, 0x65, 0x36, 0x6d, 0xc0, 0x10, 0xcf, 0x94, 0xa9, 0xa2, 0x01, 0x44, 0xd1, 0xf9, 0x1c, 0x4c, 0xfb, 0xf8, 0x99, + /* (2^ 78)P */ 0x6c, 0xb9, 0x6b, 0xee, 0x43, 0x5b, 0xb9, 0xbb, 0xee, 0x2e, 0x52, 0xc1, 0xc6, 0xb9, 0x61, 0xd2, 0x93, 0xa5, 0xaf, 0x52, 0xf4, 0xa4, 0x1a, 0x51, 0x61, 0xa7, 0xcb, 0x9e, 0xbb, 0x56, 0x65, 0xe2, 0xbf, 0x75, 0xb9, 0x9c, 0x50, 0x96, 0x60, 0x81, 0x74, 0x47, 0xc0, 0x04, 0x88, 0x71, 0x76, 0x39, 0x9a, 0xa7, 0xb1, 0x4e, 0x43, 0x15, 0xe0, 0xbb, + /* (2^ 79)P */ 0xbb, 0xce, 0xe2, 0xbb, 0xf9, 0x17, 0x0f, 0x82, 0x40, 0xad, 0x73, 0xe3, 0xeb, 0x3b, 0x06, 0x1a, 0xcf, 0x8e, 0x6e, 0x28, 0xb8, 0x26, 0xd9, 0x5b, 0xb7, 0xb3, 0xcf, 0xb4, 0x6a, 0x1c, 0xbf, 0x7f, 0xb8, 0xb5, 0x79, 0xcf, 0x45, 0x68, 0x7d, 0xc5, 0xeb, 0xf3, 0xbe, 0x39, 0x40, 0xfc, 0x07, 0x90, 0x7a, 0x62, 0xad, 0x86, 0x08, 0x71, 0x25, 0xe1, + /* (2^ 80)P */ 0x9b, 0x46, 0xac, 0xef, 0xc1, 0x4e, 0xa1, 0x97, 0x95, 0x76, 0xf9, 0x1b, 0xc2, 0xb2, 0x6a, 0x41, 0xea, 0x80, 0x3d, 0xe9, 0x08, 0x52, 0x5a, 0xe3, 0xf2, 0x08, 0xc5, 0xea, 0x39, 0x3f, 0x44, 0x71, 0x4d, 0xea, 0x0d, 0x05, 0x23, 0xe4, 0x2e, 0x3c, 0x89, 0xfe, 0x12, 0x8a, 0x95, 0x42, 0x0a, 0x68, 0xea, 0x5a, 0x28, 0x06, 0x9e, 0xe3, 0x5f, 0xe0, + /* (2^ 81)P */ 0x00, 0x61, 0x6c, 0x98, 0x9b, 0xe7, 0xb9, 0x06, 0x1c, 0xc5, 0x1b, 0xed, 0xbe, 0xc8, 0xb3, 0xea, 0x87, 0xf0, 0xc4, 0x24, 0x7d, 0xbb, 0x5d, 0xa4, 0x1d, 0x7a, 0x16, 0x00, 0x55, 0x94, 0x67, 0x78, 0xbd, 0x58, 0x02, 0x82, 0x90, 0x53, 0x76, 0xd4, 0x72, 0x99, 0x51, 0x6f, 0x7b, 0xcf, 0x80, 0x30, 0x31, 0x3b, 0x01, 0xc7, 0xc1, 0xef, 0xe6, 0x42, + /* (2^ 82)P */ 0xe2, 0x35, 0xaf, 0x4b, 0x79, 0xc6, 0x12, 0x24, 0x99, 0xc0, 0x68, 0xb0, 0x43, 0x3e, 0xe5, 0xef, 0xe2, 0x29, 0xea, 0xb8, 0xb3, 0xbc, 0x6a, 0x53, 0x2c, 0x69, 0x18, 0x5a, 0xf9, 0x15, 0xae, 0x66, 0x58, 0x18, 0xd3, 0x2d, 0x4b, 0x00, 0xfd, 0x84, 0xab, 0x4f, 0xae, 0x70, 0x6b, 0x9e, 0x9a, 0xdf, 0x83, 0xfd, 0x2e, 0x3c, 0xcf, 0xf8, 0x88, 0x5b, + /* (2^ 83)P */ 0xa4, 0x90, 0x31, 0x85, 0x13, 0xcd, 0xdf, 0x64, 0xc9, 0xa1, 0x0b, 0xe7, 0xb6, 0x73, 0x8a, 0x1b, 0x22, 0x78, 0x4c, 0xd4, 0xae, 0x48, 0x18, 0x00, 0x00, 0xa8, 0x9f, 0x06, 0xf9, 0xfb, 0x2d, 0xc3, 0xb1, 0x2a, 0xbc, 0x13, 0x99, 0x57, 0xaf, 0xf0, 0x8d, 0x61, 0x54, 0x29, 0xd5, 0xf2, 0x72, 0x00, 0x96, 0xd1, 0x85, 0x12, 0x8a, 0xf0, 0x23, 0xfb, + /* (2^ 84)P */ 0x69, 0xc7, 0xdb, 0xd9, 0x92, 0x75, 0x08, 0x9b, 0xeb, 0xa5, 0x93, 0xd1, 0x1a, 0xf4, 0xf5, 0xaf, 0xe6, 0xc4, 0x4a, 0x0d, 0x35, 0x26, 0x39, 0x9d, 0xd3, 0x17, 0x3e, 0xae, 0x2d, 0xbf, 0x73, 0x9f, 0xb7, 0x74, 0x91, 0xd1, 0xd8, 0x5c, 0x14, 0xf9, 0x75, 0xdf, 0xeb, 0xc2, 0x22, 0xd8, 0x14, 0x8d, 0x86, 0x23, 0x4d, 0xd1, 0x2d, 0xdb, 0x6b, 0x42, + /* (2^ 85)P */ 0x8c, 0xda, 0xc6, 0xf8, 0x71, 0xba, 0x2b, 0x06, 0x78, 0xae, 0xcc, 0x3a, 0xe3, 0xe3, 0xa1, 0x8b, 0xe2, 0x34, 0x6d, 0x28, 0x9e, 0x46, 0x13, 0x4d, 0x9e, 0xa6, 0x73, 0x49, 0x65, 0x79, 0x88, 0xb9, 0x3a, 0xd1, 0x6d, 0x2f, 0x48, 0x2b, 0x0a, 0x7f, 0x58, 0x20, 0x37, 0xf4, 0x0e, 0xbb, 0x4a, 0x95, 0x58, 0x0c, 0x88, 0x30, 0xc4, 0x74, 0xdd, 0xfd, + /* (2^ 86)P */ 0x6d, 0x13, 0x4e, 0x89, 0x2d, 0xa9, 0xa3, 0xed, 0x09, 0xe3, 0x0e, 0x71, 0x3e, 0x4a, 0xab, 0x90, 0xde, 0x03, 0xeb, 0x56, 0x46, 0x60, 0x06, 0xf5, 0x71, 0xe5, 0xee, 0x9b, 0xef, 0xff, 0xc4, 0x2c, 0x9f, 0x37, 0x48, 0x45, 0x94, 0x12, 0x41, 0x81, 0x15, 0x70, 0x91, 0x99, 0x5e, 0x56, 0x6b, 0xf4, 0xa6, 0xc9, 0xf5, 0x69, 0x9d, 0x78, 0x37, 0x57, + /* (2^ 87)P */ 0xf3, 0x51, 0x57, 0x7e, 0x43, 0x6f, 0xc6, 0x67, 0x59, 0x0c, 0xcf, 0x94, 0xe6, 0x3d, 0xb5, 0x07, 0xc9, 0x77, 0x48, 0xc9, 0x68, 0x0d, 0x98, 0x36, 0x62, 0x35, 0x38, 0x1c, 0xf5, 0xc5, 0xec, 0x66, 0x78, 0xfe, 0x47, 0xab, 0x26, 0xd6, 0x44, 0xb6, 0x06, 0x0f, 0x89, 0xe3, 0x19, 0x40, 0x1a, 0xe7, 0xd8, 0x65, 0x55, 0xf7, 0x1a, 0xfc, 0xa3, 0x0e, + /* (2^ 88)P */ 0x0e, 0x30, 0xa6, 0xb7, 0x58, 0x60, 0x62, 0x2a, 0x6c, 0x13, 0xa8, 0x14, 0x9b, 0xb8, 0xf2, 0x70, 0xd8, 0xb1, 0x71, 0x88, 0x8c, 0x18, 0x31, 0x25, 0x93, 0x90, 0xb4, 0xc7, 0x49, 0xd8, 0xd4, 0xdb, 0x1e, 0x1e, 0x7f, 0xaa, 0xba, 0xc9, 0xf2, 0x5d, 0xa9, 0x3a, 0x43, 0xb4, 0x5c, 0xee, 0x7b, 0xc7, 0x97, 0xb7, 0x66, 0xd7, 0x23, 0xd9, 0x22, 0x59, + /* (2^ 89)P */ 0x28, 0x19, 0xa6, 0xf9, 0x89, 0x20, 0x78, 0xd4, 0x6d, 0xcb, 0x79, 0x8f, 0x61, 0x6f, 0xb2, 0x5c, 0x4f, 0xa6, 0x54, 0x84, 0x95, 0x24, 0x36, 0x64, 0xcb, 0x39, 0xe7, 0x8f, 0x97, 0x9c, 0x5c, 0x3c, 0xfb, 0x51, 0x11, 0x01, 0x17, 0xdb, 0xc9, 0x9b, 0x51, 0x03, 0x9a, 0xe9, 0xe5, 0x24, 0x1e, 0xf5, 0xda, 0xe0, 0x48, 0x02, 0x23, 0xd0, 0x2c, 0x81, + /* (2^ 90)P */ 0x42, 0x1b, 0xe4, 0x91, 0x85, 0x2a, 0x0c, 0xd2, 0x28, 0x66, 0x57, 0x9e, 0x33, 0x8d, 0x25, 0x71, 0x10, 0x65, 0x76, 0xa2, 0x8c, 0x21, 0x86, 0x81, 0x15, 0xc2, 0x27, 0xeb, 0x54, 0x2d, 0x4f, 0x6c, 0xe6, 0xd6, 0x24, 0x9c, 0x1a, 0x12, 0xb8, 0x81, 0xe2, 0x0a, 0xf3, 0xd3, 0xf0, 0xd3, 0xe1, 0x74, 0x1f, 0x9b, 0x11, 0x47, 0xd0, 0xcf, 0xb6, 0x54, + /* (2^ 91)P */ 0x26, 0x45, 0xa2, 0x10, 0xd4, 0x2d, 0xae, 0xc0, 0xb0, 0xe8, 0x86, 0xb3, 0xc7, 0xea, 0x70, 0x87, 0x61, 0xb5, 0xa5, 0x55, 0xbe, 0x88, 0x1d, 0x7a, 0xd9, 0x6f, 0xeb, 0x83, 0xe2, 0x44, 0x7f, 0x98, 0x04, 0xd6, 0x50, 0x9d, 0xa7, 0x86, 0x66, 0x09, 0x63, 0xe1, 0xed, 0x72, 0xb1, 0xe4, 0x1d, 0x3a, 0xfd, 0x47, 0xce, 0x1c, 0xaa, 0x3b, 0x8f, 0x1b, + /* (2^ 92)P */ 0xf4, 0x3c, 0x4a, 0xb6, 0xc2, 0x9c, 0xe0, 0x2e, 0xb7, 0x38, 0xea, 0x61, 0x35, 0x97, 0x10, 0x90, 0xae, 0x22, 0x48, 0xb3, 0xa9, 0xc6, 0x7a, 0xbb, 0x23, 0xf2, 0xf8, 0x1b, 0xa7, 0xa1, 0x79, 0xcc, 0xc4, 0xf8, 0x08, 0x76, 0x8a, 0x5a, 0x1c, 0x1b, 0xc5, 0x33, 0x91, 0xa9, 0xb8, 0xb9, 0xd3, 0xf8, 0x49, 0xcd, 0xe5, 0x82, 0x43, 0xf7, 0xca, 0x68, + /* (2^ 93)P */ 0x38, 0xba, 0xae, 0x44, 0xfe, 0x57, 0x64, 0x56, 0x7c, 0x0e, 0x9c, 0xca, 0xff, 0xa9, 0x82, 0xbb, 0x38, 0x4a, 0xa7, 0xf7, 0x47, 0xab, 0xbe, 0x6d, 0x23, 0x0b, 0x8a, 0xed, 0xc2, 0xb9, 0x8f, 0xf1, 0xec, 0x91, 0x44, 0x73, 0x64, 0xba, 0xd5, 0x8f, 0x37, 0x38, 0x0d, 0xd5, 0xf8, 0x73, 0x57, 0xb6, 0xc2, 0x45, 0xdc, 0x25, 0xb2, 0xb6, 0xea, 0xd9, + /* (2^ 94)P */ 0xbf, 0xe9, 0x1a, 0x40, 0x4d, 0xcc, 0xe6, 0x1d, 0x70, 0x1a, 0x65, 0xcc, 0x34, 0x2c, 0x37, 0x2c, 0x2d, 0x6b, 0x6d, 0xe5, 0x2f, 0x19, 0x9e, 0xe4, 0xe1, 0xaa, 0xd4, 0xab, 0x54, 0xf4, 0xa8, 0xe4, 0x69, 0x2d, 0x8e, 0x4d, 0xd7, 0xac, 0xb0, 0x5b, 0xfe, 0xe3, 0x26, 0x07, 0xc3, 0xf8, 0x1b, 0x43, 0xa8, 0x1d, 0x64, 0xa5, 0x25, 0x88, 0xbb, 0x77, + /* (2^ 95)P */ 0x92, 0xcd, 0x6e, 0xa0, 0x79, 0x04, 0x18, 0xf4, 0x11, 0x58, 0x48, 0xb5, 0x3c, 0x7b, 0xd1, 0xcc, 0xd3, 0x14, 0x2c, 0xa0, 0xdd, 0x04, 0x44, 0x11, 0xb3, 0x6d, 0x2f, 0x0d, 0xf5, 0x2a, 0x75, 0x5d, 0x1d, 0xda, 0x86, 0x8d, 0x7d, 0x6b, 0x32, 0x68, 0xb6, 0x6c, 0x64, 0x9e, 0xde, 0x80, 0x88, 0xce, 0x08, 0xbf, 0x0b, 0xe5, 0x8e, 0x4f, 0x1d, 0xfb, + /* (2^ 96)P */ 0xaf, 0xe8, 0x85, 0xbf, 0x7f, 0x37, 0x8d, 0x66, 0x7c, 0xd5, 0xd3, 0x96, 0xa5, 0x81, 0x67, 0x95, 0xff, 0x48, 0xde, 0xde, 0xd7, 0x7a, 0x46, 0x34, 0xb1, 0x13, 0x70, 0x29, 0xed, 0x87, 0x90, 0xb0, 0x40, 0x2c, 0xa6, 0x43, 0x6e, 0xb6, 0xbc, 0x48, 0x8a, 0xc1, 0xae, 0xb8, 0xd4, 0xe2, 0xc0, 0x32, 0xb2, 0xa6, 0x2a, 0x8f, 0xb5, 0x16, 0x9e, 0xc3, + /* (2^ 97)P */ 0xff, 0x4d, 0xd2, 0xd6, 0x74, 0xef, 0x2c, 0x96, 0xc1, 0x11, 0xa8, 0xb8, 0xfe, 0x94, 0x87, 0x3e, 0xa0, 0xfb, 0x57, 0xa3, 0xfc, 0x7a, 0x7e, 0x6a, 0x59, 0x6c, 0x54, 0xbb, 0xbb, 0xa2, 0x25, 0x38, 0x1b, 0xdf, 0x5d, 0x7b, 0x94, 0x14, 0xde, 0x07, 0x6e, 0xd3, 0xab, 0x02, 0x26, 0x74, 0x16, 0x12, 0xdf, 0x2e, 0x2a, 0xa7, 0xb0, 0xe8, 0x29, 0xc0, + /* (2^ 98)P */ 0x6a, 0x38, 0x0b, 0xd3, 0xba, 0x45, 0x23, 0xe0, 0x04, 0x3b, 0x83, 0x39, 0xc5, 0x11, 0xe6, 0xcf, 0x39, 0x0a, 0xb3, 0xb0, 0x3b, 0x27, 0x29, 0x63, 0x1c, 0xf3, 0x00, 0xe6, 0xd2, 0x55, 0x21, 0x1f, 0x84, 0x97, 0x9f, 0x01, 0x49, 0x43, 0x30, 0x5f, 0xe0, 0x1d, 0x24, 0xc4, 0x4e, 0xa0, 0x2b, 0x0b, 0x12, 0x55, 0xc3, 0x27, 0xae, 0x08, 0x83, 0x7c, + /* (2^ 99)P */ 0x5d, 0x1a, 0xb7, 0xa9, 0xf5, 0xfd, 0xec, 0xad, 0xb7, 0x87, 0x02, 0x5f, 0x0d, 0x30, 0x4d, 0xe2, 0x65, 0x87, 0xa4, 0x41, 0x45, 0x1d, 0x67, 0xe0, 0x30, 0x5c, 0x13, 0x87, 0xf6, 0x2e, 0x08, 0xc1, 0xc7, 0x12, 0x45, 0xc8, 0x9b, 0xad, 0xb8, 0xd5, 0x57, 0xbb, 0x5c, 0x48, 0x3a, 0xe1, 0x91, 0x5e, 0xf6, 0x4d, 0x8a, 0x63, 0x75, 0x69, 0x0c, 0x01, + /* (2^100)P */ 0x8f, 0x53, 0x2d, 0xa0, 0x71, 0x3d, 0xfc, 0x45, 0x10, 0x96, 0xcf, 0x56, 0xf9, 0xbb, 0x40, 0x3c, 0x86, 0x52, 0x76, 0xbe, 0x84, 0xf9, 0xa6, 0x9d, 0x3d, 0x27, 0xbe, 0xb4, 0x00, 0x49, 0x94, 0xf5, 0x5d, 0xe1, 0x62, 0x85, 0x66, 0xe5, 0xb8, 0x20, 0x2c, 0x09, 0x7d, 0x9d, 0x3d, 0x6e, 0x74, 0x39, 0xab, 0xad, 0xa0, 0x90, 0x97, 0x5f, 0xbb, 0xa7, + /* (2^101)P */ 0xdb, 0x2d, 0x99, 0x08, 0x16, 0x46, 0x83, 0x7a, 0xa8, 0xea, 0x3d, 0x28, 0x5b, 0x49, 0xfc, 0xb9, 0x6d, 0x00, 0x9e, 0x54, 0x4f, 0x47, 0x64, 0x9b, 0x58, 0x4d, 0x07, 0x0c, 0x6f, 0x29, 0x56, 0x0b, 0x00, 0x14, 0x85, 0x96, 0x41, 0x04, 0xb9, 0x5c, 0xa4, 0xf6, 0x16, 0x73, 0x6a, 0xc7, 0x62, 0x0c, 0x65, 0x2f, 0x93, 0xbf, 0xf7, 0xb9, 0xb7, 0xf1, + /* (2^102)P */ 0xeb, 0x6d, 0xb3, 0x46, 0x32, 0xd2, 0xcb, 0x08, 0x94, 0x14, 0xbf, 0x3f, 0xc5, 0xcb, 0x5f, 0x9f, 0x8a, 0x89, 0x0c, 0x1b, 0x45, 0xad, 0x4c, 0x50, 0xb4, 0xe1, 0xa0, 0x6b, 0x11, 0x92, 0xaf, 0x1f, 0x00, 0xcc, 0xe5, 0x13, 0x7e, 0xe4, 0x2e, 0xa0, 0x57, 0xf3, 0xa7, 0x84, 0x79, 0x7a, 0xc2, 0xb7, 0xb7, 0xfc, 0x5d, 0xa5, 0xa9, 0x64, 0xcc, 0xd8, + /* (2^103)P */ 0xa9, 0xc4, 0x12, 0x8b, 0x34, 0x78, 0x3e, 0x38, 0xfd, 0x3f, 0x87, 0xfa, 0x88, 0x94, 0xd5, 0xd9, 0x7f, 0xeb, 0x58, 0xff, 0xb9, 0x45, 0xdb, 0xa1, 0xed, 0x22, 0x28, 0x1d, 0x00, 0x6d, 0x79, 0x85, 0x7a, 0x75, 0x5d, 0xf0, 0xb1, 0x9e, 0x47, 0x28, 0x8c, 0x62, 0xdf, 0xfb, 0x4c, 0x7b, 0xc5, 0x1a, 0x42, 0x95, 0xef, 0x9a, 0xb7, 0x27, 0x7e, 0xda, + /* (2^104)P */ 0xca, 0xd5, 0xc0, 0x17, 0xa1, 0x66, 0x79, 0x9c, 0x2a, 0xb7, 0x0a, 0xfe, 0x62, 0xe4, 0x26, 0x78, 0x90, 0xa7, 0xcb, 0xb0, 0x4f, 0x6d, 0xf9, 0x8f, 0xf7, 0x7d, 0xac, 0xb8, 0x78, 0x1f, 0x41, 0xea, 0x97, 0x1e, 0x62, 0x97, 0x43, 0x80, 0x58, 0x80, 0xb6, 0x69, 0x7d, 0xee, 0x16, 0xd2, 0xa1, 0x81, 0xd7, 0xb1, 0x27, 0x03, 0x48, 0xda, 0xab, 0xec, + /* (2^105)P */ 0x5b, 0xed, 0x40, 0x8e, 0x8c, 0xc1, 0x66, 0x90, 0x7f, 0x0c, 0xb2, 0xfc, 0xbd, 0x16, 0xac, 0x7d, 0x4c, 0x6a, 0xf9, 0xae, 0xe7, 0x4e, 0x11, 0x12, 0xe9, 0xbe, 0x17, 0x09, 0xc6, 0xc1, 0x5e, 0xb5, 0x7b, 0x50, 0x5c, 0x27, 0xfb, 0x80, 0xab, 0x01, 0xfa, 0x5b, 0x9b, 0x75, 0x16, 0x6e, 0xb2, 0x5c, 0x8c, 0x2f, 0xa5, 0x6a, 0x1a, 0x68, 0xa6, 0x90, + /* (2^106)P */ 0x75, 0xfe, 0xb6, 0x96, 0x96, 0x87, 0x4c, 0x12, 0xa9, 0xd1, 0xd8, 0x03, 0xa3, 0xc1, 0x15, 0x96, 0xe8, 0xa0, 0x75, 0x82, 0xa0, 0x6d, 0xea, 0x54, 0xdc, 0x5f, 0x0d, 0x7e, 0xf6, 0x70, 0xb5, 0xdc, 0x7a, 0xf6, 0xc4, 0xd4, 0x21, 0x49, 0xf5, 0xd4, 0x14, 0x6d, 0x48, 0x1d, 0x7c, 0x99, 0x42, 0xdf, 0x78, 0x6b, 0x9d, 0xb9, 0x30, 0x3c, 0xd0, 0x29, + /* (2^107)P */ 0x85, 0xd6, 0xd8, 0xf3, 0x91, 0x74, 0xdd, 0xbd, 0x72, 0x96, 0x10, 0xe4, 0x76, 0x02, 0x5a, 0x72, 0x67, 0xd3, 0x17, 0x72, 0x14, 0x9a, 0x20, 0x5b, 0x0f, 0x8d, 0xed, 0x6d, 0x4e, 0xe3, 0xd9, 0x82, 0xc2, 0x99, 0xee, 0x39, 0x61, 0x69, 0x8a, 0x24, 0x01, 0x92, 0x15, 0xe7, 0xfc, 0xf9, 0x4d, 0xac, 0xf1, 0x30, 0x49, 0x01, 0x0b, 0x6e, 0x0f, 0x20, + /* (2^108)P */ 0xd8, 0x25, 0x94, 0x5e, 0x43, 0x29, 0xf5, 0xcc, 0xe8, 0xe3, 0x55, 0x41, 0x3c, 0x9f, 0x58, 0x5b, 0x00, 0xeb, 0xc5, 0xdf, 0xcf, 0xfb, 0xfd, 0x6e, 0x92, 0xec, 0x99, 0x30, 0xd6, 0x05, 0xdd, 0x80, 0x7a, 0x5d, 0x6d, 0x16, 0x85, 0xd8, 0x9d, 0x43, 0x65, 0xd8, 0x2c, 0x33, 0x2f, 0x5c, 0x41, 0xea, 0xb7, 0x95, 0x77, 0xf2, 0x9e, 0x59, 0x09, 0xe8, + /* (2^109)P */ 0x00, 0xa0, 0x03, 0x80, 0xcd, 0x60, 0xe5, 0x17, 0xd4, 0x15, 0x99, 0xdd, 0x4f, 0xbf, 0x66, 0xb8, 0xc0, 0xf5, 0xf9, 0xfc, 0x6d, 0x42, 0x18, 0x34, 0x1c, 0x7d, 0x5b, 0xb5, 0x09, 0xd0, 0x99, 0x57, 0x81, 0x0b, 0x62, 0xb3, 0xa2, 0xf9, 0x0b, 0xae, 0x95, 0xb8, 0xc2, 0x3b, 0x0d, 0x5b, 0x00, 0xf1, 0xed, 0xbc, 0x05, 0x9d, 0x61, 0xbc, 0x73, 0x9d, + /* (2^110)P */ 0xd4, 0xdb, 0x29, 0xe5, 0x85, 0xe9, 0xc6, 0x89, 0x2a, 0xa8, 0x54, 0xab, 0xb3, 0x7f, 0x88, 0xc0, 0x4d, 0xe0, 0xd1, 0x74, 0x6e, 0xa3, 0xa7, 0x39, 0xd5, 0xcc, 0xa1, 0x8a, 0xcb, 0x5b, 0x34, 0xad, 0x92, 0xb4, 0xd8, 0xd5, 0x17, 0xf6, 0x77, 0x18, 0x9e, 0xaf, 0x45, 0x3b, 0x03, 0xe2, 0xf8, 0x52, 0x60, 0xdc, 0x15, 0x20, 0x9e, 0xdf, 0xd8, 0x5d, + /* (2^111)P */ 0x02, 0xc1, 0xac, 0x1a, 0x15, 0x8e, 0x6c, 0xf5, 0x1e, 0x1e, 0xba, 0x7e, 0xc2, 0xda, 0x7d, 0x02, 0xda, 0x43, 0xae, 0x04, 0x70, 0x28, 0x54, 0x78, 0x94, 0xf5, 0x4f, 0x07, 0x84, 0x8f, 0xed, 0xaa, 0xc0, 0xb8, 0xcd, 0x7f, 0x7e, 0x33, 0xa3, 0xbe, 0x21, 0x29, 0xc8, 0x56, 0x34, 0xc0, 0x76, 0x87, 0x8f, 0xc7, 0x73, 0x58, 0x90, 0x16, 0xfc, 0xd6, + /* (2^112)P */ 0xb8, 0x3f, 0xe1, 0xdf, 0x3a, 0x91, 0x25, 0x0c, 0xf6, 0x47, 0xa8, 0x89, 0xc4, 0xc6, 0x61, 0xec, 0x86, 0x2c, 0xfd, 0xbe, 0xa4, 0x6f, 0xc2, 0xd4, 0x46, 0x19, 0x70, 0x5d, 0x09, 0x02, 0x86, 0xd3, 0x4b, 0xe9, 0x16, 0x7b, 0xf0, 0x0d, 0x6c, 0xff, 0x91, 0x05, 0xbf, 0x55, 0xb4, 0x00, 0x8d, 0xe5, 0x6d, 0x68, 0x20, 0x90, 0x12, 0xb5, 0x5c, 0x32, + /* (2^113)P */ 0x80, 0x45, 0xc8, 0x51, 0x87, 0xba, 0x1c, 0x5c, 0xcf, 0x5f, 0x4b, 0x3c, 0x9e, 0x3b, 0x36, 0xd2, 0x26, 0xa2, 0x7f, 0xab, 0xb7, 0xbf, 0xda, 0x68, 0x23, 0x8f, 0xc3, 0xa0, 0xfd, 0xad, 0xf1, 0x56, 0x3b, 0xd0, 0x75, 0x2b, 0x44, 0x61, 0xd8, 0xf4, 0xf1, 0x05, 0x49, 0x53, 0x07, 0xee, 0x47, 0xef, 0xc0, 0x7c, 0x9d, 0xe4, 0x15, 0x88, 0xc5, 0x47, + /* (2^114)P */ 0x2d, 0xb5, 0x09, 0x80, 0xb9, 0xd3, 0xd8, 0xfe, 0x4c, 0xd2, 0xa6, 0x6e, 0xd3, 0x75, 0xcf, 0xb0, 0x99, 0xcb, 0x50, 0x8d, 0xe9, 0x67, 0x9b, 0x20, 0xe8, 0x57, 0xd8, 0x14, 0x85, 0x73, 0x6a, 0x74, 0xe0, 0x99, 0xf0, 0x6b, 0x6e, 0x59, 0x30, 0x31, 0x33, 0x96, 0x5f, 0xa1, 0x0c, 0x1b, 0xf4, 0xca, 0x09, 0xe1, 0x9b, 0xb5, 0xcf, 0x6d, 0x0b, 0xeb, + /* (2^115)P */ 0x1a, 0xde, 0x50, 0xa9, 0xac, 0x3e, 0x10, 0x43, 0x4f, 0x82, 0x4f, 0xc0, 0xfe, 0x3f, 0x33, 0xd2, 0x64, 0x86, 0x50, 0xa9, 0x51, 0x76, 0x5e, 0x50, 0x97, 0x6c, 0x73, 0x8d, 0x77, 0xa3, 0x75, 0x03, 0xbc, 0xc9, 0xfb, 0x50, 0xd9, 0x6d, 0x16, 0xad, 0x5d, 0x32, 0x3d, 0xac, 0x44, 0xdf, 0x51, 0xf7, 0x19, 0xd4, 0x0b, 0x57, 0x78, 0x0b, 0x81, 0x4e, + /* (2^116)P */ 0x32, 0x24, 0xf1, 0x6c, 0x55, 0x62, 0x1d, 0xb3, 0x1f, 0xda, 0xfa, 0x6a, 0x8f, 0x98, 0x01, 0x16, 0xde, 0x44, 0x50, 0x0d, 0x2e, 0x6c, 0x0b, 0xa2, 0xd3, 0x74, 0x0e, 0xa9, 0xbf, 0x8d, 0xa9, 0xc8, 0xc8, 0x2f, 0x62, 0xc1, 0x35, 0x5e, 0xfd, 0x3a, 0xb3, 0x83, 0x2d, 0xee, 0x4e, 0xfd, 0x5c, 0x5e, 0xad, 0x85, 0xa5, 0x10, 0xb5, 0x4f, 0x34, 0xa7, + /* (2^117)P */ 0xd1, 0x58, 0x6f, 0xe6, 0x54, 0x2c, 0xc2, 0xcd, 0xcf, 0x83, 0xdc, 0x88, 0x0c, 0xb9, 0xb4, 0x62, 0x18, 0x89, 0x65, 0x28, 0xe9, 0x72, 0x4b, 0x65, 0xcf, 0xd6, 0x90, 0x88, 0xd7, 0x76, 0x17, 0x4f, 0x74, 0x64, 0x1e, 0xcb, 0xd3, 0xf5, 0x4b, 0xaa, 0x2e, 0x4d, 0x2d, 0x7c, 0x13, 0x1f, 0xfd, 0xd9, 0x60, 0x83, 0x7e, 0xda, 0x64, 0x1c, 0xdc, 0x9f, + /* (2^118)P */ 0xad, 0xef, 0xac, 0x1b, 0xc1, 0x30, 0x5a, 0x15, 0xc9, 0x1f, 0xac, 0xf1, 0xca, 0x44, 0x95, 0x95, 0xea, 0xf2, 0x22, 0xe7, 0x8d, 0x25, 0xf0, 0xff, 0xd8, 0x71, 0xf7, 0xf8, 0x8f, 0x8f, 0xcd, 0xf4, 0x1e, 0xfe, 0x6c, 0x68, 0x04, 0xb8, 0x78, 0xa1, 0x5f, 0xa6, 0x5d, 0x5e, 0xf9, 0x8d, 0xea, 0x80, 0xcb, 0xf3, 0x17, 0xa6, 0x03, 0xc9, 0x38, 0xd5, + /* (2^119)P */ 0x79, 0x14, 0x31, 0xc3, 0x38, 0xe5, 0xaa, 0xbf, 0x17, 0xa3, 0x04, 0x4e, 0x80, 0x59, 0x9c, 0x9f, 0x19, 0x39, 0xe4, 0x2d, 0x23, 0x54, 0x4a, 0x7f, 0x3e, 0xf3, 0xd9, 0xc7, 0xba, 0x6c, 0x8f, 0x6b, 0xfa, 0x34, 0xb5, 0x23, 0x17, 0x1d, 0xff, 0x1d, 0xea, 0x1f, 0xd7, 0xba, 0x61, 0xb2, 0xe0, 0x38, 0x6a, 0xe9, 0xcf, 0x48, 0x5d, 0x6a, 0x10, 0x9c, + /* (2^120)P */ 0xc8, 0xbb, 0x13, 0x1c, 0x3f, 0x3c, 0x34, 0xfd, 0xac, 0x37, 0x52, 0x44, 0x25, 0xa8, 0xde, 0x1d, 0x63, 0xf4, 0x81, 0x9a, 0xbe, 0x0b, 0x74, 0x2e, 0xc8, 0x51, 0x16, 0xd3, 0xac, 0x4a, 0xaf, 0xe2, 0x5f, 0x3a, 0x89, 0x32, 0xd1, 0x9b, 0x7c, 0x90, 0x0d, 0xac, 0xdc, 0x8b, 0x73, 0x45, 0x45, 0x97, 0xb1, 0x90, 0x2c, 0x1b, 0x31, 0xca, 0xb1, 0x94, + /* (2^121)P */ 0x07, 0x28, 0xdd, 0x10, 0x14, 0xa5, 0x95, 0x7e, 0xf3, 0xe4, 0xd4, 0x14, 0xb4, 0x7e, 0x76, 0xdb, 0x42, 0xd6, 0x94, 0x3e, 0xeb, 0x44, 0x64, 0x88, 0x0d, 0xec, 0xc1, 0x21, 0xf0, 0x79, 0xe0, 0x83, 0x67, 0x55, 0x53, 0xc2, 0xf6, 0xc5, 0xc5, 0x89, 0x39, 0xe8, 0x42, 0xd0, 0x17, 0xbd, 0xff, 0x35, 0x59, 0x0e, 0xc3, 0x06, 0x86, 0xd4, 0x64, 0xcf, + /* (2^122)P */ 0x91, 0xa8, 0xdb, 0x57, 0x9b, 0xe2, 0x96, 0x31, 0x10, 0x6e, 0xd7, 0x9a, 0x97, 0xb3, 0xab, 0xb5, 0x15, 0x66, 0xbe, 0xcc, 0x6d, 0x9a, 0xac, 0x06, 0xb3, 0x0d, 0xaa, 0x4b, 0x9c, 0x96, 0x79, 0x6c, 0x34, 0xee, 0x9e, 0x53, 0x4d, 0x6e, 0xbd, 0x88, 0x02, 0xbf, 0x50, 0x54, 0x12, 0x5d, 0x01, 0x02, 0x46, 0xc6, 0x74, 0x02, 0x8c, 0x24, 0xae, 0xb1, + /* (2^123)P */ 0xf5, 0x22, 0xea, 0xac, 0x7d, 0x9c, 0x33, 0x8a, 0xa5, 0x36, 0x79, 0x6a, 0x4f, 0xa4, 0xdc, 0xa5, 0x73, 0x64, 0xc4, 0x6f, 0x43, 0x02, 0x3b, 0x94, 0x66, 0xd2, 0x4b, 0x4f, 0xf6, 0x45, 0x33, 0x5d, 0x10, 0x33, 0x18, 0x1e, 0xa3, 0xfc, 0xf7, 0xd2, 0xb8, 0xc8, 0xa7, 0xe0, 0x76, 0x8a, 0xcd, 0xff, 0x4f, 0x99, 0x34, 0x47, 0x84, 0x91, 0x96, 0x9f, + /* (2^124)P */ 0x8a, 0x48, 0x3b, 0x48, 0x4a, 0xbc, 0xac, 0xe2, 0x80, 0xd6, 0xd2, 0x35, 0xde, 0xd0, 0x56, 0x42, 0x33, 0xb3, 0x56, 0x5a, 0xcd, 0xb8, 0x3d, 0xb5, 0x25, 0xc1, 0xed, 0xff, 0x87, 0x0b, 0x79, 0xff, 0xf2, 0x62, 0xe1, 0x76, 0xc6, 0xa2, 0x0f, 0xa8, 0x9b, 0x0d, 0xcc, 0x3f, 0x3d, 0x35, 0x27, 0x8d, 0x0b, 0x74, 0xb0, 0xc3, 0x78, 0x8c, 0xcc, 0xc8, + /* (2^125)P */ 0xfc, 0x9a, 0x0c, 0xa8, 0x49, 0x42, 0xb8, 0xdf, 0xcf, 0xb3, 0x19, 0xa6, 0x64, 0x57, 0xfe, 0xe8, 0xf8, 0xa6, 0x4b, 0x86, 0xa1, 0xd5, 0x83, 0x7f, 0x14, 0x99, 0x18, 0x0c, 0x7d, 0x5b, 0xf7, 0x3d, 0xf9, 0x4b, 0x79, 0xb1, 0x86, 0x30, 0xb4, 0x5e, 0x6a, 0xe8, 0x9d, 0xfa, 0x8a, 0x41, 0xc4, 0x30, 0xfc, 0x56, 0x74, 0x14, 0x42, 0xc8, 0x96, 0x0e, + /* (2^126)P */ 0xdf, 0x66, 0xec, 0xbc, 0x44, 0xdb, 0x19, 0xce, 0xd4, 0xb5, 0x49, 0x40, 0x07, 0x49, 0xe0, 0x3a, 0x61, 0x10, 0xfb, 0x7d, 0xba, 0xb1, 0xe0, 0x28, 0x5b, 0x99, 0x59, 0x96, 0xa2, 0xee, 0xe0, 0x23, 0x37, 0x39, 0x1f, 0xe6, 0x57, 0x9f, 0xf8, 0xf8, 0xdc, 0x74, 0xf6, 0x8f, 0x4f, 0x5e, 0x51, 0xa4, 0x12, 0xac, 0xbe, 0xe4, 0xf3, 0xd1, 0xf0, 0x24, + /* (2^127)P */ 0x1e, 0x3e, 0x9a, 0x5f, 0xdf, 0x9f, 0xd6, 0x4e, 0x8a, 0x28, 0xc3, 0xcd, 0x96, 0x9d, 0x57, 0xc7, 0x61, 0x81, 0x90, 0xff, 0xae, 0xb1, 0x4f, 0xc2, 0x96, 0x8b, 0x1a, 0x18, 0xf4, 0x50, 0xcb, 0x31, 0xe1, 0x57, 0xf4, 0x90, 0xa8, 0xea, 0xac, 0xe7, 0x61, 0x98, 0xb6, 0x15, 0xc1, 0x7b, 0x29, 0xa4, 0xc3, 0x18, 0xef, 0xb9, 0xd8, 0xdf, 0xf6, 0xac, + /* (2^128)P */ 0xca, 0xa8, 0x6c, 0xf1, 0xb4, 0xca, 0xfe, 0x31, 0xee, 0x48, 0x38, 0x8b, 0x0e, 0xbb, 0x7a, 0x30, 0xaa, 0xf9, 0xee, 0x27, 0x53, 0x24, 0xdc, 0x2e, 0x15, 0xa6, 0x48, 0x8f, 0xa0, 0x7e, 0xf1, 0xdc, 0x93, 0x87, 0x39, 0xeb, 0x7f, 0x38, 0x92, 0x92, 0x4c, 0x29, 0xe9, 0x57, 0xd8, 0x59, 0xfc, 0xe9, 0x9c, 0x44, 0xc0, 0x65, 0xcf, 0xac, 0x4b, 0xdc, + /* (2^129)P */ 0xa3, 0xd0, 0x37, 0x8f, 0x86, 0x2f, 0xc6, 0x47, 0x55, 0x46, 0x65, 0x26, 0x4b, 0x91, 0xe2, 0x18, 0x5c, 0x4f, 0x23, 0xc1, 0x37, 0x29, 0xb9, 0xc1, 0x27, 0xc5, 0x3c, 0xbf, 0x7e, 0x23, 0xdb, 0x73, 0x99, 0xbd, 0x1b, 0xb2, 0x31, 0x68, 0x3a, 0xad, 0xb7, 0xb0, 0x10, 0xc5, 0xe5, 0x11, 0x51, 0xba, 0xa7, 0x60, 0x66, 0x54, 0xf0, 0x08, 0xd7, 0x69, + /* (2^130)P */ 0x89, 0x41, 0x79, 0xcc, 0xeb, 0x0a, 0xf5, 0x4b, 0xa3, 0x4c, 0xce, 0x52, 0xb0, 0xa7, 0xe4, 0x41, 0x75, 0x7d, 0x04, 0xbb, 0x09, 0x4c, 0x50, 0x9f, 0xdf, 0xea, 0x74, 0x61, 0x02, 0xad, 0xb4, 0x9d, 0xb7, 0x05, 0xb9, 0xea, 0xeb, 0x91, 0x35, 0xe7, 0x49, 0xea, 0xd3, 0x4f, 0x3c, 0x60, 0x21, 0x7a, 0xde, 0xc7, 0xe2, 0x5a, 0xee, 0x8e, 0x93, 0xc7, + /* (2^131)P */ 0x00, 0xe8, 0xed, 0xd0, 0xb3, 0x0d, 0xaf, 0xb2, 0xde, 0x2c, 0xf6, 0x00, 0xe2, 0xea, 0x6d, 0xf8, 0x0e, 0xd9, 0x67, 0x59, 0xa9, 0x50, 0xbb, 0x17, 0x8f, 0xff, 0xb1, 0x9f, 0x17, 0xb6, 0xf2, 0xb5, 0xba, 0x80, 0xf7, 0x0f, 0xba, 0xd5, 0x09, 0x43, 0xaa, 0x4e, 0x3a, 0x67, 0x6a, 0x89, 0x9b, 0x18, 0x65, 0x35, 0xf8, 0x3a, 0x49, 0x91, 0x30, 0x51, + /* (2^132)P */ 0x8d, 0x25, 0xe9, 0x0e, 0x7d, 0x50, 0x76, 0xe4, 0x58, 0x7e, 0xb9, 0x33, 0xe6, 0x65, 0x90, 0xc2, 0x50, 0x9d, 0x50, 0x2e, 0x11, 0xad, 0xd5, 0x43, 0x52, 0x32, 0x41, 0x4f, 0x7b, 0xb6, 0xa0, 0xec, 0x81, 0x75, 0x36, 0x7c, 0x77, 0x85, 0x59, 0x70, 0xe4, 0xf9, 0xef, 0x66, 0x8d, 0x35, 0xc8, 0x2a, 0x6e, 0x5b, 0xc6, 0x0d, 0x0b, 0x29, 0x60, 0x68, + /* (2^133)P */ 0xf8, 0xce, 0xb0, 0x3a, 0x56, 0x7d, 0x51, 0x9a, 0x25, 0x73, 0xea, 0xdd, 0xe4, 0xe0, 0x0e, 0xf0, 0x07, 0xc0, 0x31, 0x00, 0x73, 0x35, 0xd0, 0x39, 0xc4, 0x9b, 0xb7, 0x95, 0xe0, 0x62, 0x70, 0x36, 0x0b, 0xcb, 0xa0, 0x42, 0xde, 0x51, 0xcf, 0x41, 0xe0, 0xb8, 0xb4, 0xc0, 0xe5, 0x46, 0x99, 0x9f, 0x02, 0x7f, 0x14, 0x8c, 0xc1, 0x4e, 0xef, 0xe8, + /* (2^134)P */ 0x10, 0x01, 0x57, 0x0a, 0xbe, 0x8b, 0x18, 0xc8, 0xca, 0x00, 0x28, 0x77, 0x4a, 0x9a, 0xc7, 0x55, 0x2a, 0xcc, 0x0c, 0x7b, 0xb9, 0xe9, 0xc8, 0x97, 0x7c, 0x02, 0xe3, 0x09, 0x2f, 0x62, 0x30, 0xb8, 0x40, 0x09, 0x65, 0xe9, 0x55, 0x63, 0xb5, 0x07, 0xca, 0x9f, 0x00, 0xdf, 0x9d, 0x5c, 0xc7, 0xee, 0x57, 0xa5, 0x90, 0x15, 0x1e, 0x22, 0xa0, 0x12, + /* (2^135)P */ 0x71, 0x2d, 0xc9, 0xef, 0x27, 0xb9, 0xd8, 0x12, 0x43, 0x6b, 0xa8, 0xce, 0x3b, 0x6d, 0x6e, 0x91, 0x43, 0x23, 0xbc, 0x32, 0xb3, 0xbf, 0xe1, 0xc7, 0x39, 0xcf, 0x7c, 0x42, 0x4c, 0xb1, 0x30, 0xe2, 0xdd, 0x69, 0x06, 0xe5, 0xea, 0xf0, 0x2a, 0x16, 0x50, 0x71, 0xca, 0x92, 0xdf, 0xc1, 0xcc, 0xec, 0xe6, 0x54, 0x07, 0xf3, 0x18, 0x8d, 0xd8, 0x29, + /* (2^136)P */ 0x98, 0x51, 0x48, 0x8f, 0xfa, 0x2e, 0x5e, 0x67, 0xb0, 0xc6, 0x17, 0x12, 0xb6, 0x7d, 0xc9, 0xad, 0x81, 0x11, 0xad, 0x0c, 0x1c, 0x2d, 0x45, 0xdf, 0xac, 0x66, 0xbd, 0x08, 0x6f, 0x7c, 0xc7, 0x06, 0x6e, 0x19, 0x08, 0x39, 0x64, 0xd7, 0xe4, 0xd1, 0x11, 0x5f, 0x1c, 0xf4, 0x67, 0xc3, 0x88, 0x6a, 0xe6, 0x07, 0xa3, 0x83, 0xd7, 0xfd, 0x2a, 0xf9, + /* (2^137)P */ 0x87, 0xed, 0xeb, 0xd9, 0xdf, 0xff, 0x43, 0x8b, 0xaa, 0x20, 0x58, 0xb0, 0xb4, 0x6b, 0x14, 0xb8, 0x02, 0xc5, 0x40, 0x20, 0x22, 0xbb, 0xf7, 0xb4, 0xf3, 0x05, 0x1e, 0x4d, 0x94, 0xff, 0xe3, 0xc5, 0x22, 0x82, 0xfe, 0xaf, 0x90, 0x42, 0x98, 0x6b, 0x76, 0x8b, 0x3e, 0x89, 0x3f, 0x42, 0x2a, 0xa7, 0x26, 0x00, 0xda, 0x5c, 0xa2, 0x2b, 0xec, 0xdd, + /* (2^138)P */ 0x5c, 0x21, 0x16, 0x0d, 0x46, 0xb8, 0xd0, 0xa7, 0x88, 0xe7, 0x25, 0xcb, 0x3e, 0x50, 0x73, 0x61, 0xe7, 0xaf, 0x5a, 0x3f, 0x47, 0x8b, 0x3d, 0x97, 0x79, 0x2c, 0xe6, 0x6d, 0x95, 0x74, 0x65, 0x70, 0x36, 0xfd, 0xd1, 0x9e, 0x13, 0x18, 0x63, 0xb1, 0x2d, 0x0b, 0xb5, 0x36, 0x3e, 0xe7, 0x35, 0x42, 0x3b, 0xe6, 0x1f, 0x4d, 0x9d, 0x59, 0xa2, 0x43, + /* (2^139)P */ 0x8c, 0x0c, 0x7c, 0x24, 0x9e, 0xe0, 0xf8, 0x05, 0x1c, 0x9e, 0x1f, 0x31, 0xc0, 0x70, 0xb3, 0xfb, 0x4e, 0xf8, 0x0a, 0x57, 0xb7, 0x49, 0xb5, 0x73, 0xa1, 0x5f, 0x9b, 0x6a, 0x07, 0x6c, 0x87, 0x71, 0x87, 0xd4, 0xbe, 0x98, 0x1e, 0x98, 0xee, 0x52, 0xc1, 0x7b, 0x95, 0x0f, 0x28, 0x32, 0x36, 0x28, 0xd0, 0x3a, 0x0f, 0x7d, 0x2a, 0xa9, 0x62, 0xb9, + /* (2^140)P */ 0x97, 0xe6, 0x18, 0x77, 0xf9, 0x34, 0xac, 0xbc, 0xe0, 0x62, 0x9f, 0x42, 0xde, 0xbd, 0x2f, 0xf7, 0x1f, 0xb7, 0x14, 0x52, 0x8a, 0x79, 0xb2, 0x3f, 0xd2, 0x95, 0x71, 0x01, 0xe8, 0xaf, 0x8c, 0xa4, 0xa4, 0xa7, 0x27, 0xf3, 0x5c, 0xdf, 0x3e, 0x57, 0x7a, 0xf1, 0x76, 0x49, 0xe6, 0x42, 0x3f, 0x8f, 0x1e, 0x63, 0x4a, 0x65, 0xb5, 0x41, 0xf5, 0x02, + /* (2^141)P */ 0x72, 0x85, 0xc5, 0x0b, 0xe1, 0x47, 0x64, 0x02, 0xc5, 0x4d, 0x81, 0x69, 0xb2, 0xcf, 0x0f, 0x6c, 0xd4, 0x6d, 0xd0, 0xc7, 0xb4, 0x1c, 0xd0, 0x32, 0x59, 0x89, 0xe2, 0xe0, 0x96, 0x8b, 0x12, 0x98, 0xbf, 0x63, 0x7a, 0x4c, 0x76, 0x7e, 0x58, 0x17, 0x8f, 0x5b, 0x0a, 0x59, 0x65, 0x75, 0xbc, 0x61, 0x1f, 0xbe, 0xc5, 0x6e, 0x0a, 0x57, 0x52, 0x70, + /* (2^142)P */ 0x92, 0x1c, 0x77, 0xbb, 0x62, 0x02, 0x6c, 0x25, 0x9c, 0x66, 0x07, 0x83, 0xab, 0xcc, 0x80, 0x5d, 0xd2, 0x76, 0x0c, 0xa4, 0xc5, 0xb4, 0x8a, 0x68, 0x23, 0x31, 0x32, 0x29, 0x8a, 0x47, 0x92, 0x12, 0x80, 0xb3, 0xfa, 0x18, 0xe4, 0x8d, 0xc0, 0x4d, 0xfe, 0x97, 0x5f, 0x72, 0x41, 0xb5, 0x5c, 0x7a, 0xbd, 0xf0, 0xcf, 0x5e, 0x97, 0xaa, 0x64, 0x32, + /* (2^143)P */ 0x35, 0x3f, 0x75, 0xc1, 0x7a, 0x75, 0x7e, 0xa9, 0xc6, 0x0b, 0x4e, 0x32, 0x62, 0xec, 0xe3, 0x5c, 0xfb, 0x01, 0x43, 0xb6, 0xd4, 0x5b, 0x75, 0xd2, 0xee, 0x7f, 0x5d, 0x23, 0x2b, 0xb3, 0x54, 0x34, 0x4c, 0xd3, 0xb4, 0x32, 0x84, 0x81, 0xb5, 0x09, 0x76, 0x19, 0xda, 0x58, 0xda, 0x7c, 0xdb, 0x2e, 0xdd, 0x4c, 0x8e, 0xdd, 0x5d, 0x89, 0x10, 0x10, + /* (2^144)P */ 0x57, 0x25, 0x6a, 0x08, 0x37, 0x92, 0xa8, 0xdf, 0x24, 0xef, 0x8f, 0x33, 0x34, 0x52, 0xa4, 0x4c, 0xf0, 0x77, 0x9f, 0x69, 0x77, 0xd5, 0x8f, 0xd2, 0x9a, 0xb3, 0xb6, 0x1d, 0x2d, 0xa6, 0xf7, 0x1f, 0xda, 0xd7, 0xcb, 0x75, 0x11, 0xc3, 0x6b, 0xc0, 0x38, 0xb1, 0xd5, 0x2d, 0x96, 0x84, 0x16, 0xfa, 0x26, 0xb9, 0xcc, 0x3f, 0x16, 0x47, 0x23, 0x74, + /* (2^145)P */ 0x9b, 0x61, 0x2a, 0x1c, 0xdd, 0x39, 0xa5, 0xfa, 0x1c, 0x7d, 0x63, 0x50, 0xca, 0xe6, 0x9d, 0xfa, 0xb7, 0xc4, 0x4c, 0x6a, 0x97, 0x5f, 0x36, 0x4e, 0x47, 0xdd, 0x17, 0xf7, 0xf9, 0x19, 0xce, 0x75, 0x17, 0xad, 0xce, 0x2a, 0xf3, 0xfe, 0x27, 0x8f, 0x3e, 0x48, 0xc0, 0x60, 0x87, 0x24, 0x19, 0xae, 0x59, 0xe4, 0x5a, 0x00, 0x2a, 0xba, 0xa2, 0x1f, + /* (2^146)P */ 0x26, 0x88, 0x42, 0x60, 0x9f, 0x6e, 0x2c, 0x7c, 0x39, 0x0f, 0x47, 0x6a, 0x0e, 0x02, 0xbb, 0x4b, 0x34, 0x29, 0x55, 0x18, 0x36, 0xcf, 0x3b, 0x47, 0xf1, 0x2e, 0xfc, 0x6e, 0x94, 0xff, 0xe8, 0x6b, 0x06, 0xd2, 0xba, 0x77, 0x5e, 0x60, 0xd7, 0x19, 0xef, 0x02, 0x9d, 0x3a, 0xc2, 0xb7, 0xa9, 0xd8, 0x57, 0xee, 0x7e, 0x2b, 0xf2, 0x6d, 0x28, 0xda, + /* (2^147)P */ 0xdf, 0xd9, 0x92, 0x11, 0x98, 0x23, 0xe2, 0x45, 0x2f, 0x74, 0x70, 0xee, 0x0e, 0x55, 0x65, 0x79, 0x86, 0x38, 0x17, 0x92, 0x85, 0x87, 0x99, 0x50, 0xd9, 0x7c, 0xdb, 0xa1, 0x10, 0xec, 0x30, 0xb7, 0x40, 0xa3, 0x23, 0x9b, 0x0e, 0x27, 0x49, 0x29, 0x03, 0x94, 0xff, 0x53, 0xdc, 0xd7, 0xed, 0x49, 0xa9, 0x5a, 0x3b, 0xee, 0xd7, 0xc7, 0x65, 0xaf, + /* (2^148)P */ 0xa0, 0xbd, 0xbe, 0x03, 0xee, 0x0c, 0xbe, 0x32, 0x00, 0x7b, 0x52, 0xcb, 0x92, 0x29, 0xbf, 0xa0, 0xc6, 0xd9, 0xd2, 0xd6, 0x15, 0xe8, 0x3a, 0x75, 0x61, 0x65, 0x56, 0xae, 0xad, 0x3c, 0x2a, 0x64, 0x14, 0x3f, 0x8e, 0xc1, 0x2d, 0x0c, 0x8d, 0x20, 0xdb, 0x58, 0x4b, 0xe5, 0x40, 0x15, 0x4b, 0xdc, 0xa8, 0xbd, 0xef, 0x08, 0xa7, 0xd1, 0xf4, 0xb0, + /* (2^149)P */ 0xa9, 0x0f, 0x05, 0x94, 0x66, 0xac, 0x1f, 0x65, 0x3f, 0xe1, 0xb8, 0xe1, 0x34, 0x5e, 0x1d, 0x8f, 0xe3, 0x93, 0x03, 0x15, 0xff, 0xb6, 0x65, 0xb6, 0x6e, 0xc0, 0x2f, 0xd4, 0x2e, 0xb9, 0x2c, 0x13, 0x3c, 0x99, 0x1c, 0xb5, 0x87, 0xba, 0x79, 0xcb, 0xf0, 0x18, 0x06, 0x86, 0x04, 0x14, 0x25, 0x09, 0xcd, 0x1c, 0x14, 0xda, 0x35, 0xd0, 0x38, 0x3b, + /* (2^150)P */ 0x1b, 0x04, 0xa3, 0x27, 0xb4, 0xd3, 0x37, 0x48, 0x1e, 0x8f, 0x69, 0xd3, 0x5a, 0x2f, 0x20, 0x02, 0x36, 0xbe, 0x06, 0x7b, 0x6b, 0x6c, 0x12, 0x5b, 0x80, 0x74, 0x44, 0xe6, 0xf8, 0xf5, 0x95, 0x59, 0x29, 0xab, 0x51, 0x47, 0x83, 0x28, 0xe0, 0xad, 0xde, 0xaa, 0xd3, 0xb1, 0x1a, 0xcb, 0xa3, 0xcd, 0x8b, 0x6a, 0xb1, 0xa7, 0x0a, 0xd1, 0xf9, 0xbe, + /* (2^151)P */ 0xce, 0x2f, 0x85, 0xca, 0x74, 0x6d, 0x49, 0xb8, 0xce, 0x80, 0x44, 0xe0, 0xda, 0x5b, 0xcf, 0x2f, 0x79, 0x74, 0xfe, 0xb4, 0x2c, 0x99, 0x20, 0x6e, 0x09, 0x04, 0xfb, 0x6d, 0x57, 0x5b, 0x95, 0x0c, 0x45, 0xda, 0x4f, 0x7f, 0x63, 0xcc, 0x85, 0x5a, 0x67, 0x50, 0x68, 0x71, 0xb4, 0x67, 0xb1, 0x2e, 0xc1, 0x1c, 0xdc, 0xff, 0x2a, 0x7c, 0x10, 0x5e, + /* (2^152)P */ 0xa6, 0xde, 0xf3, 0xd4, 0x22, 0x30, 0x24, 0x9e, 0x0b, 0x30, 0x54, 0x59, 0x7e, 0xa2, 0xeb, 0x89, 0x54, 0x65, 0x3e, 0x40, 0xd1, 0xde, 0xe6, 0xee, 0x4d, 0xbf, 0x5e, 0x40, 0x1d, 0xee, 0x4f, 0x68, 0xd9, 0xa7, 0x2f, 0xb3, 0x64, 0xb3, 0xf5, 0xc8, 0xd3, 0xaa, 0x70, 0x70, 0x3d, 0xef, 0xd3, 0x95, 0x54, 0xdb, 0x3e, 0x94, 0x95, 0x92, 0x1f, 0x45, + /* (2^153)P */ 0x22, 0x80, 0x1d, 0x9d, 0x96, 0xa5, 0x78, 0x6f, 0xe0, 0x1e, 0x1b, 0x66, 0x42, 0xc8, 0xae, 0x9e, 0x46, 0x45, 0x08, 0x41, 0xdf, 0x80, 0xae, 0x6f, 0xdb, 0x15, 0x5a, 0x21, 0x31, 0x7a, 0xd0, 0xf2, 0x54, 0x15, 0x88, 0xd3, 0x0f, 0x7f, 0x14, 0x5a, 0x14, 0x97, 0xab, 0xf4, 0x58, 0x6a, 0x9f, 0xea, 0x74, 0xe5, 0x6b, 0x90, 0x59, 0x2b, 0x48, 0xd9, + /* (2^154)P */ 0x12, 0x24, 0x04, 0xf5, 0x50, 0xc2, 0x8c, 0xb0, 0x7c, 0x46, 0x98, 0xd5, 0x24, 0xad, 0xf6, 0x72, 0xdc, 0x82, 0x1a, 0x60, 0xc1, 0xeb, 0x48, 0xef, 0x7f, 0x6e, 0xe6, 0xcc, 0xdb, 0x7b, 0xae, 0xbe, 0x5e, 0x1e, 0x5c, 0xe6, 0x0a, 0x70, 0xdf, 0xa4, 0xa3, 0x85, 0x1b, 0x1b, 0x7f, 0x72, 0xb9, 0x96, 0x6f, 0xdc, 0x03, 0x76, 0x66, 0xfb, 0xa0, 0x33, + /* (2^155)P */ 0x37, 0x40, 0xbb, 0xbc, 0x68, 0x58, 0x86, 0xca, 0xbb, 0xa5, 0x24, 0x76, 0x3d, 0x48, 0xd1, 0xad, 0xb4, 0xa8, 0xcf, 0xc3, 0xb6, 0xa8, 0xba, 0x1a, 0x3a, 0xbe, 0x33, 0x75, 0x04, 0x5c, 0x13, 0x8c, 0x0d, 0x70, 0x8d, 0xa6, 0x4e, 0x2a, 0xeb, 0x17, 0x3c, 0x22, 0xdd, 0x3e, 0x96, 0x40, 0x11, 0x9e, 0x4e, 0xae, 0x3d, 0xf8, 0x91, 0xd7, 0x50, 0xc8, + /* (2^156)P */ 0xd8, 0xca, 0xde, 0x19, 0xcf, 0x00, 0xe4, 0x73, 0x18, 0x7f, 0x9b, 0x9f, 0xf4, 0x5b, 0x49, 0x49, 0x99, 0xdc, 0xa4, 0x46, 0x21, 0xb5, 0xd7, 0x3e, 0xb7, 0x47, 0x1b, 0xa9, 0x9f, 0x4c, 0x69, 0x7d, 0xec, 0x33, 0xd6, 0x1c, 0x51, 0x7f, 0x47, 0x74, 0x7a, 0x6c, 0xf3, 0xd2, 0x2e, 0xbf, 0xdf, 0x6c, 0x9e, 0x77, 0x3b, 0x34, 0xf6, 0x73, 0x80, 0xed, + /* (2^157)P */ 0x16, 0xfb, 0x16, 0xc3, 0xc2, 0x83, 0xe4, 0xf4, 0x03, 0x7f, 0x52, 0xb0, 0x67, 0x51, 0x7b, 0x24, 0x5a, 0x51, 0xd3, 0xb6, 0x4e, 0x59, 0x76, 0xcd, 0x08, 0x7b, 0x1d, 0x7a, 0x9c, 0x65, 0xae, 0xce, 0xaa, 0xd2, 0x1c, 0x85, 0x66, 0x68, 0x06, 0x15, 0xa8, 0x06, 0xe6, 0x16, 0x37, 0xf4, 0x49, 0x9e, 0x0f, 0x50, 0x37, 0xb1, 0xb2, 0x93, 0x70, 0x43, + /* (2^158)P */ 0x18, 0x3a, 0x16, 0xe5, 0x8d, 0xc8, 0x35, 0xd6, 0x7b, 0x09, 0xec, 0x61, 0x5f, 0x5c, 0x2a, 0x19, 0x96, 0x2e, 0xc3, 0xfd, 0xab, 0xe6, 0x23, 0xae, 0xab, 0xc5, 0xcb, 0xb9, 0x7b, 0x2d, 0x34, 0x51, 0xb9, 0x41, 0x9e, 0x7d, 0xca, 0xda, 0x25, 0x45, 0x14, 0xb0, 0xc7, 0x4d, 0x26, 0x2b, 0xfe, 0x43, 0xb0, 0x21, 0x5e, 0xfa, 0xdc, 0x7c, 0xf9, 0x5a, + /* (2^159)P */ 0x94, 0xad, 0x42, 0x17, 0xf5, 0xcd, 0x1c, 0x0d, 0xf6, 0x41, 0xd2, 0x55, 0xbb, 0x50, 0xf1, 0xc6, 0xbc, 0xa6, 0xc5, 0x3a, 0xfd, 0x9b, 0x75, 0x3e, 0xf6, 0x1a, 0xa7, 0xb2, 0x6e, 0x64, 0x12, 0xdc, 0x3c, 0xe5, 0xf6, 0xfc, 0x3b, 0xfa, 0x43, 0x81, 0xd4, 0xa5, 0xee, 0xf5, 0x9c, 0x47, 0x2f, 0xd0, 0x9c, 0xde, 0xa1, 0x48, 0x91, 0x9a, 0x34, 0xc1, + /* (2^160)P */ 0x37, 0x1b, 0xb3, 0x88, 0xc9, 0x98, 0x4e, 0xfb, 0x84, 0x4f, 0x2b, 0x0a, 0xb6, 0x8f, 0x35, 0x15, 0xcd, 0x61, 0x7a, 0x5f, 0x5c, 0xa0, 0xca, 0x23, 0xa0, 0x93, 0x1f, 0xcc, 0x3c, 0x39, 0x3a, 0x24, 0xa7, 0x49, 0xad, 0x8d, 0x59, 0xcc, 0x94, 0x5a, 0x16, 0xf5, 0x70, 0xe8, 0x52, 0x1e, 0xee, 0x20, 0x30, 0x17, 0x7e, 0xf0, 0x4c, 0x93, 0x06, 0x5a, + /* (2^161)P */ 0x81, 0xba, 0x3b, 0xd7, 0x3e, 0xb4, 0x32, 0x3a, 0x22, 0x39, 0x2a, 0xfc, 0x19, 0xd9, 0xd2, 0xf6, 0xc5, 0x79, 0x6c, 0x0e, 0xde, 0xda, 0x01, 0xff, 0x52, 0xfb, 0xb6, 0x95, 0x4e, 0x7a, 0x10, 0xb8, 0x06, 0x86, 0x3c, 0xcd, 0x56, 0xd6, 0x15, 0xbf, 0x6e, 0x3e, 0x4f, 0x35, 0x5e, 0xca, 0xbc, 0xa5, 0x95, 0xa2, 0xdf, 0x2d, 0x1d, 0xaf, 0x59, 0xf9, + /* (2^162)P */ 0x69, 0xe5, 0xe2, 0xfa, 0xc9, 0x7f, 0xdd, 0x09, 0xf5, 0x6b, 0x4e, 0x2e, 0xbe, 0xb4, 0xbf, 0x3e, 0xb2, 0xf2, 0x81, 0x30, 0xe1, 0x07, 0xa8, 0x0d, 0x2b, 0xd2, 0x5a, 0x55, 0xbe, 0x4b, 0x86, 0x5d, 0xb0, 0x5e, 0x7c, 0x8f, 0xc1, 0x3c, 0x81, 0x4c, 0xf7, 0x6d, 0x7d, 0xe6, 0x4f, 0x8a, 0x85, 0xc2, 0x2f, 0x28, 0xef, 0x8c, 0x69, 0xc2, 0xc2, 0x1a, + /* (2^163)P */ 0xd9, 0xe4, 0x0e, 0x1e, 0xc2, 0xf7, 0x2f, 0x9f, 0xa1, 0x40, 0xfe, 0x46, 0x16, 0xaf, 0x2e, 0xd1, 0xec, 0x15, 0x9b, 0x61, 0x92, 0xce, 0xfc, 0x10, 0x43, 0x1d, 0x00, 0xf6, 0xbe, 0x20, 0x80, 0x80, 0x6f, 0x3c, 0x16, 0x94, 0x59, 0xba, 0x03, 0x53, 0x6e, 0xb6, 0xdd, 0x25, 0x7b, 0x86, 0xbf, 0x96, 0xf4, 0x2f, 0xa1, 0x96, 0x8d, 0xf9, 0xb3, 0x29, + /* (2^164)P */ 0x3b, 0x04, 0x60, 0x6e, 0xce, 0xab, 0xd2, 0x63, 0x18, 0x53, 0x88, 0x16, 0x4a, 0x6a, 0xab, 0x72, 0x03, 0x68, 0xa5, 0xd4, 0x0d, 0xb2, 0x82, 0x81, 0x1f, 0x2b, 0x5c, 0x75, 0xe8, 0xd2, 0x1d, 0x7f, 0xe7, 0x1b, 0x35, 0x02, 0xde, 0xec, 0xbd, 0xcb, 0xc7, 0x01, 0xd3, 0x95, 0x61, 0xfe, 0xb2, 0x7a, 0x66, 0x09, 0x4c, 0x6d, 0xfd, 0x39, 0xf7, 0x52, + /* (2^165)P */ 0x42, 0xc1, 0x5f, 0xf8, 0x35, 0x52, 0xc1, 0xfe, 0xc5, 0x11, 0x80, 0x1c, 0x11, 0x46, 0x31, 0x11, 0xbe, 0xd0, 0xc4, 0xb6, 0x07, 0x13, 0x38, 0xa0, 0x8d, 0x65, 0xf0, 0x56, 0x9e, 0x16, 0xbf, 0x9d, 0xcd, 0x51, 0x34, 0xf9, 0x08, 0x48, 0x7b, 0x76, 0x0c, 0x7b, 0x30, 0x07, 0xa8, 0x76, 0xaf, 0xa3, 0x29, 0x38, 0xb0, 0x58, 0xde, 0x72, 0x4b, 0x45, + /* (2^166)P */ 0xd4, 0x16, 0xa7, 0xc0, 0xb4, 0x9f, 0xdf, 0x1a, 0x37, 0xc8, 0x35, 0xed, 0xc5, 0x85, 0x74, 0x64, 0x09, 0x22, 0xef, 0xe9, 0x0c, 0xaf, 0x12, 0x4c, 0x9e, 0xf8, 0x47, 0x56, 0xe0, 0x7f, 0x4e, 0x24, 0x6b, 0x0c, 0xe7, 0xad, 0xc6, 0x47, 0x1d, 0xa4, 0x0d, 0x86, 0x89, 0x65, 0xe8, 0x5f, 0x71, 0xc7, 0xe9, 0xcd, 0xec, 0x6c, 0x62, 0xc7, 0xe3, 0xb3, + /* (2^167)P */ 0xb5, 0xea, 0x86, 0xe3, 0x15, 0x18, 0x3f, 0x6d, 0x7b, 0x05, 0x95, 0x15, 0x53, 0x26, 0x1c, 0xeb, 0xbe, 0x7e, 0x16, 0x42, 0x4b, 0xa2, 0x3d, 0xdd, 0x0e, 0xff, 0xba, 0x67, 0xb5, 0xae, 0x7a, 0x17, 0xde, 0x23, 0xad, 0x14, 0xcc, 0xd7, 0xaf, 0x57, 0x01, 0xe0, 0xdd, 0x48, 0xdd, 0xd7, 0xe3, 0xdf, 0xe9, 0x2d, 0xda, 0x67, 0xa4, 0x9f, 0x29, 0x04, + /* (2^168)P */ 0x16, 0x53, 0xe6, 0x9c, 0x4e, 0xe5, 0x1e, 0x70, 0x81, 0x25, 0x02, 0x9b, 0x47, 0x6d, 0xd2, 0x08, 0x73, 0xbe, 0x0a, 0xf1, 0x7b, 0xeb, 0x24, 0xeb, 0x38, 0x23, 0x5c, 0xb6, 0x3e, 0xce, 0x1e, 0xe3, 0xbc, 0x82, 0x35, 0x1f, 0xaf, 0x3a, 0x3a, 0xe5, 0x4e, 0xc1, 0xca, 0xbf, 0x47, 0xb4, 0xbb, 0xbc, 0x5f, 0xea, 0xc6, 0xca, 0xf3, 0xa0, 0xa2, 0x73, + /* (2^169)P */ 0xef, 0xa4, 0x7a, 0x4e, 0xe4, 0xc7, 0xb6, 0x43, 0x2e, 0xa5, 0xe4, 0xa5, 0xba, 0x1e, 0xa5, 0xfe, 0x9e, 0xce, 0xa9, 0x80, 0x04, 0xcb, 0x4f, 0xd8, 0x74, 0x05, 0x48, 0xfa, 0x99, 0x11, 0x5d, 0x97, 0x3b, 0x07, 0x0d, 0xdd, 0xe6, 0xb1, 0x74, 0x87, 0x1a, 0xd3, 0x26, 0xb7, 0x8f, 0xe1, 0x63, 0x3d, 0xec, 0x53, 0x93, 0xb0, 0x81, 0x78, 0x34, 0xa4, + /* (2^170)P */ 0xe1, 0xe7, 0xd4, 0x58, 0x9d, 0x0e, 0x8b, 0x65, 0x66, 0x37, 0x16, 0x48, 0x6f, 0xaa, 0x42, 0x37, 0x77, 0xad, 0xb1, 0x56, 0x48, 0xdf, 0x65, 0x36, 0x30, 0xb8, 0x00, 0x12, 0xd8, 0x32, 0x28, 0x7f, 0xc1, 0x71, 0xeb, 0x93, 0x0f, 0x48, 0x04, 0xe1, 0x5a, 0x6a, 0x96, 0xc1, 0xca, 0x89, 0x6d, 0x1b, 0x82, 0x4c, 0x18, 0x6d, 0x55, 0x4b, 0xea, 0xfd, + /* (2^171)P */ 0x62, 0x1a, 0x53, 0xb4, 0xb1, 0xbe, 0x6f, 0x15, 0x18, 0x88, 0xd4, 0x66, 0x61, 0xc7, 0x12, 0x69, 0x02, 0xbd, 0x03, 0x23, 0x2b, 0xef, 0xf9, 0x54, 0xa4, 0x85, 0xa8, 0xe3, 0xb7, 0xbd, 0xa9, 0xa3, 0xf3, 0x2a, 0xdd, 0xf1, 0xd4, 0x03, 0x0f, 0xa9, 0xa1, 0xd8, 0xa3, 0xcd, 0xb2, 0x71, 0x90, 0x4b, 0x35, 0x62, 0xf2, 0x2f, 0xce, 0x67, 0x1f, 0xaa, + /* (2^172)P */ 0x9e, 0x1e, 0xcd, 0x43, 0x7e, 0x87, 0x37, 0x94, 0x3a, 0x97, 0x4c, 0x7e, 0xee, 0xc9, 0x37, 0x85, 0xf1, 0xd9, 0x4f, 0xbf, 0xf9, 0x6f, 0x39, 0x9a, 0x39, 0x87, 0x2e, 0x25, 0x84, 0x42, 0xc3, 0x80, 0xcb, 0x07, 0x22, 0xae, 0x30, 0xd5, 0x50, 0xa1, 0x23, 0xcc, 0x31, 0x81, 0x9d, 0xf1, 0x30, 0xd9, 0x2b, 0x73, 0x41, 0x16, 0x50, 0xab, 0x2d, 0xa2, + /* (2^173)P */ 0xa4, 0x69, 0x4f, 0xa1, 0x4e, 0xb9, 0xbf, 0x14, 0xe8, 0x2b, 0x04, 0x93, 0xb7, 0x6e, 0x9f, 0x7d, 0x73, 0x0a, 0xc5, 0x14, 0xb8, 0xde, 0x8c, 0xc1, 0xfe, 0xc0, 0xa7, 0xa4, 0xcc, 0x42, 0x42, 0x81, 0x15, 0x65, 0x8a, 0x80, 0xb9, 0xde, 0x1f, 0x60, 0x33, 0x0e, 0xcb, 0xfc, 0xe0, 0xdb, 0x83, 0xa1, 0xe5, 0xd0, 0x16, 0x86, 0x2c, 0xe2, 0x87, 0xed, + /* (2^174)P */ 0x7a, 0xc0, 0xeb, 0x6b, 0xf6, 0x0d, 0x4c, 0x6d, 0x1e, 0xdb, 0xab, 0xe7, 0x19, 0x45, 0xc6, 0xe3, 0xb2, 0x06, 0xbb, 0xbc, 0x70, 0x99, 0x83, 0x33, 0xeb, 0x28, 0xc8, 0x77, 0xf6, 0x4d, 0x01, 0xb7, 0x59, 0xa0, 0xd2, 0xb3, 0x2a, 0x72, 0x30, 0xe7, 0x11, 0x39, 0xb6, 0x41, 0x29, 0x65, 0x5a, 0x14, 0xb9, 0x86, 0x08, 0xe0, 0x7d, 0x32, 0x8c, 0xf0, + /* (2^175)P */ 0x5c, 0x11, 0x30, 0x9e, 0x05, 0x27, 0xf5, 0x45, 0x0f, 0xb3, 0xc9, 0x75, 0xc3, 0xd7, 0xe1, 0x82, 0x3b, 0x8e, 0x87, 0x23, 0x00, 0x15, 0x19, 0x07, 0xd9, 0x21, 0x53, 0xc7, 0xf1, 0xa3, 0xbf, 0x70, 0x64, 0x15, 0x18, 0xca, 0x23, 0x9e, 0xd3, 0x08, 0xc3, 0x2a, 0x8b, 0xe5, 0x83, 0x04, 0x89, 0x14, 0xfd, 0x28, 0x25, 0x1c, 0xe3, 0x26, 0xa7, 0x22, + /* (2^176)P */ 0xdc, 0xd4, 0x75, 0x60, 0x99, 0x94, 0xea, 0x09, 0x8e, 0x8a, 0x3c, 0x1b, 0xf9, 0xbd, 0x33, 0x0d, 0x51, 0x3d, 0x12, 0x6f, 0x4e, 0x72, 0xe0, 0x17, 0x20, 0xe9, 0x75, 0xe6, 0x3a, 0xb2, 0x13, 0x83, 0x4e, 0x7a, 0x08, 0x9e, 0xd1, 0x04, 0x5f, 0x6b, 0x42, 0x0b, 0x76, 0x2a, 0x2d, 0x77, 0x53, 0x6c, 0x65, 0x6d, 0x8e, 0x25, 0x3c, 0xb6, 0x8b, 0x69, + /* (2^177)P */ 0xb9, 0x49, 0x28, 0xd0, 0xdc, 0x6c, 0x8f, 0x4c, 0xc9, 0x14, 0x8a, 0x38, 0xa3, 0xcb, 0xc4, 0x9d, 0x53, 0xcf, 0xe9, 0xe3, 0xcf, 0xe0, 0xb1, 0xf2, 0x1b, 0x4c, 0x7f, 0x83, 0x2a, 0x7a, 0xe9, 0x8b, 0x3b, 0x86, 0x61, 0x30, 0xe9, 0x99, 0xbd, 0xba, 0x19, 0x6e, 0x65, 0x2a, 0x12, 0x3e, 0x9c, 0xa8, 0xaf, 0xc3, 0xcf, 0xf8, 0x1f, 0x77, 0x86, 0xea, + /* (2^178)P */ 0x30, 0xde, 0xe7, 0xff, 0x54, 0xf7, 0xa2, 0x59, 0xf6, 0x0b, 0xfb, 0x7a, 0xf2, 0x39, 0xf0, 0xdb, 0x39, 0xbc, 0xf0, 0xfa, 0x60, 0xeb, 0x6b, 0x4f, 0x47, 0x17, 0xc8, 0x00, 0x65, 0x6d, 0x25, 0x1c, 0xd0, 0x48, 0x56, 0x53, 0x45, 0x11, 0x30, 0x02, 0x49, 0x20, 0x27, 0xac, 0xf2, 0x4c, 0xac, 0x64, 0x3d, 0x52, 0xb8, 0x89, 0xe0, 0x93, 0x16, 0x0f, + /* (2^179)P */ 0x84, 0x09, 0xba, 0x40, 0xb2, 0x2f, 0xa3, 0xa8, 0xc2, 0xba, 0x46, 0x33, 0x05, 0x9d, 0x62, 0xad, 0xa1, 0x3c, 0x33, 0xef, 0x0d, 0xeb, 0xf0, 0x77, 0x11, 0x5a, 0xb0, 0x21, 0x9c, 0xdf, 0x55, 0x24, 0x25, 0x35, 0x51, 0x61, 0x92, 0xf0, 0xb1, 0xce, 0xf5, 0xd4, 0x7b, 0x6c, 0x21, 0x9d, 0x56, 0x52, 0xf8, 0xa1, 0x4c, 0xe9, 0x27, 0x55, 0xac, 0x91, + /* (2^180)P */ 0x03, 0x3e, 0x30, 0xd2, 0x0a, 0xfa, 0x7d, 0x82, 0x3d, 0x1f, 0x8b, 0xcb, 0xb6, 0x04, 0x5c, 0xcc, 0x8b, 0xda, 0xe2, 0x68, 0x74, 0x08, 0x8c, 0x44, 0x83, 0x57, 0x6d, 0x6f, 0x80, 0xb0, 0x7e, 0xa9, 0x82, 0x91, 0x7b, 0x4c, 0x37, 0x97, 0xd1, 0x63, 0xd1, 0xbd, 0x45, 0xe6, 0x8a, 0x86, 0xd6, 0x89, 0x54, 0xfd, 0xd2, 0xb1, 0xd7, 0x54, 0xad, 0xaf, + /* (2^181)P */ 0x8b, 0x33, 0x62, 0x49, 0x9f, 0x63, 0xf9, 0x87, 0x42, 0x58, 0xbf, 0xb3, 0xe6, 0x68, 0x02, 0x60, 0x5c, 0x76, 0x62, 0xf7, 0x61, 0xd7, 0x36, 0x31, 0xf7, 0x9c, 0xb5, 0xe5, 0x13, 0x6c, 0xea, 0x78, 0xae, 0xcf, 0xde, 0xbf, 0xb6, 0xeb, 0x4f, 0xc8, 0x2a, 0xb4, 0x9a, 0x9f, 0xf3, 0xd1, 0x6a, 0xec, 0x0c, 0xbd, 0x85, 0x98, 0x40, 0x06, 0x1c, 0x2a, + /* (2^182)P */ 0x74, 0x3b, 0xe7, 0x81, 0xd5, 0xae, 0x54, 0x56, 0x03, 0xe8, 0x97, 0x16, 0x76, 0xcf, 0x24, 0x96, 0x96, 0x5b, 0xcc, 0x09, 0xab, 0x23, 0x6f, 0x54, 0xae, 0x8f, 0xe4, 0x12, 0xcb, 0xfd, 0xbc, 0xac, 0x93, 0x45, 0x3d, 0x68, 0x08, 0x22, 0x59, 0xc6, 0xf0, 0x47, 0x19, 0x8c, 0x79, 0x93, 0x1e, 0x0e, 0x30, 0xb0, 0x94, 0xfb, 0x17, 0x1d, 0x5a, 0x12, + /* (2^183)P */ 0x85, 0xff, 0x40, 0x18, 0x85, 0xff, 0x44, 0x37, 0x69, 0x23, 0x4d, 0x34, 0xe1, 0xeb, 0xa3, 0x1b, 0x55, 0x40, 0xc1, 0x64, 0xf4, 0xd4, 0x13, 0x0a, 0x9f, 0xb9, 0x19, 0xfc, 0x88, 0x7d, 0xc0, 0x72, 0xcf, 0x69, 0x2f, 0xd2, 0x0c, 0x82, 0x0f, 0xda, 0x08, 0xba, 0x0f, 0xaa, 0x3b, 0xe9, 0xe5, 0x83, 0x7a, 0x06, 0xe8, 0x1b, 0x38, 0x43, 0xc3, 0x54, + /* (2^184)P */ 0x14, 0xaa, 0xb3, 0x6e, 0xe6, 0x28, 0xee, 0xc5, 0x22, 0x6c, 0x7c, 0xf9, 0xa8, 0x71, 0xcc, 0xfe, 0x68, 0x7e, 0xd3, 0xb8, 0x37, 0x96, 0xca, 0x0b, 0xd9, 0xb6, 0x06, 0xa9, 0xf6, 0x71, 0xe8, 0x31, 0xf7, 0xd8, 0xf1, 0x5d, 0xab, 0xb9, 0xf0, 0x5c, 0x98, 0xcf, 0x22, 0xa2, 0x2a, 0xf6, 0xd0, 0x59, 0xf0, 0x9d, 0xd9, 0x6a, 0x4f, 0x59, 0x57, 0xad, + /* (2^185)P */ 0xd7, 0x2b, 0x3d, 0x38, 0x4c, 0x2e, 0x23, 0x4d, 0x49, 0xa2, 0x62, 0x62, 0xf9, 0x0f, 0xde, 0x08, 0xf3, 0x86, 0x71, 0xb6, 0xc7, 0xf9, 0x85, 0x9c, 0x33, 0xa1, 0xcf, 0x16, 0xaa, 0x60, 0xb9, 0xb7, 0xea, 0xed, 0x01, 0x1c, 0x59, 0xdb, 0x3f, 0x3f, 0x97, 0x2e, 0xf0, 0x09, 0x9f, 0x10, 0x85, 0x5f, 0x53, 0x39, 0xf3, 0x13, 0x40, 0x56, 0x95, 0xf9, + /* (2^186)P */ 0xb4, 0xe3, 0xda, 0xc6, 0x1f, 0x78, 0x8e, 0xac, 0xd4, 0x20, 0x1d, 0xa0, 0xbf, 0x4c, 0x09, 0x16, 0xa7, 0x30, 0xb5, 0x8d, 0x9e, 0xa1, 0x5f, 0x6d, 0x52, 0xf4, 0x71, 0xb6, 0x32, 0x2d, 0x21, 0x51, 0xc6, 0xfc, 0x2f, 0x08, 0xf4, 0x13, 0x6c, 0x55, 0xba, 0x72, 0x81, 0x24, 0x49, 0x0e, 0x4f, 0x06, 0x36, 0x39, 0x6a, 0xc5, 0x81, 0xfc, 0xeb, 0xb2, + /* (2^187)P */ 0x7d, 0x8d, 0xc8, 0x6c, 0xea, 0xb4, 0xb9, 0xe8, 0x40, 0xc9, 0x69, 0xc9, 0x30, 0x05, 0xfd, 0x34, 0x46, 0xfd, 0x94, 0x05, 0x16, 0xf5, 0x4b, 0x13, 0x3d, 0x24, 0x1a, 0xd6, 0x64, 0x2b, 0x9c, 0xe2, 0xa5, 0xd9, 0x98, 0xe0, 0xe8, 0xf4, 0xbc, 0x2c, 0xbd, 0xa2, 0x56, 0xe3, 0x9e, 0x14, 0xdb, 0xbf, 0x05, 0xbf, 0x9a, 0x13, 0x5d, 0xf7, 0x91, 0xa3, + /* (2^188)P */ 0x8b, 0xcb, 0x27, 0xf3, 0x15, 0x26, 0x05, 0x40, 0x0f, 0xa6, 0x15, 0x13, 0x71, 0x95, 0xa2, 0xc6, 0x38, 0x04, 0x67, 0xf8, 0x9a, 0x83, 0x06, 0xaa, 0x25, 0x36, 0x72, 0x01, 0x6f, 0x74, 0x5f, 0xe5, 0x6e, 0x44, 0x99, 0xce, 0x13, 0xbc, 0x82, 0xc2, 0x0d, 0xa4, 0x98, 0x50, 0x38, 0xf3, 0xa2, 0xc5, 0xe5, 0x24, 0x1f, 0x6f, 0x56, 0x3e, 0x07, 0xb2, + /* (2^189)P */ 0xbd, 0x0f, 0x32, 0x60, 0x07, 0xb1, 0xd7, 0x0b, 0x11, 0x07, 0x57, 0x02, 0x89, 0xe8, 0x8b, 0xe8, 0x5a, 0x1f, 0xee, 0x54, 0x6b, 0xff, 0xb3, 0x04, 0x07, 0x57, 0x13, 0x0b, 0x94, 0xa8, 0x4d, 0x81, 0xe2, 0x17, 0x16, 0x45, 0xd4, 0x4b, 0xf7, 0x7e, 0x64, 0x66, 0x20, 0xe8, 0x0b, 0x26, 0xfd, 0xa9, 0x8a, 0x47, 0x52, 0x89, 0x14, 0xd0, 0xd1, 0xa1, + /* (2^190)P */ 0xdc, 0x03, 0xe6, 0x20, 0x44, 0x47, 0x8f, 0x04, 0x16, 0x24, 0x22, 0xc1, 0x55, 0x5c, 0xbe, 0x43, 0xc3, 0x92, 0xc5, 0x54, 0x3d, 0x5d, 0xd1, 0x05, 0x9c, 0xc6, 0x7c, 0xbf, 0x23, 0x84, 0x1a, 0xba, 0x4f, 0x1f, 0xfc, 0xa1, 0xae, 0x1a, 0x64, 0x02, 0x51, 0xf1, 0xcb, 0x7a, 0x20, 0xce, 0xb2, 0x34, 0x3c, 0xca, 0xe0, 0xe4, 0xba, 0x22, 0xd4, 0x7b, + /* (2^191)P */ 0xca, 0xfd, 0xca, 0xd7, 0xde, 0x61, 0xae, 0xf0, 0x79, 0x0c, 0x20, 0xab, 0xbc, 0x6f, 0x4d, 0x61, 0xf0, 0xc7, 0x9c, 0x8d, 0x4b, 0x52, 0xf3, 0xb9, 0x48, 0x63, 0x0b, 0xb6, 0xd2, 0x25, 0x9a, 0x96, 0x72, 0xc1, 0x6b, 0x0c, 0xb5, 0xfb, 0x71, 0xaa, 0xad, 0x47, 0x5b, 0xe7, 0xc0, 0x0a, 0x55, 0xb2, 0xd4, 0x16, 0x2f, 0xb1, 0x01, 0xfd, 0xce, 0x27, + /* (2^192)P */ 0x64, 0x11, 0x4b, 0xab, 0x57, 0x09, 0xc6, 0x49, 0x4a, 0x37, 0xc3, 0x36, 0xc4, 0x7b, 0x81, 0x1f, 0x42, 0xed, 0xbb, 0xe0, 0xa0, 0x8d, 0x51, 0xe6, 0xca, 0x8b, 0xb9, 0xcd, 0x99, 0x2d, 0x91, 0x53, 0xa9, 0x47, 0xcb, 0x32, 0xc7, 0xa4, 0x92, 0xec, 0x46, 0x74, 0x44, 0x6d, 0x71, 0x9f, 0x6d, 0x0c, 0x69, 0xa4, 0xf8, 0xbe, 0x9f, 0x7f, 0xa0, 0xd7, + /* (2^193)P */ 0x5f, 0x33, 0xb6, 0x91, 0xc8, 0xa5, 0x3f, 0x5d, 0x7f, 0x38, 0x6e, 0x74, 0x20, 0x4a, 0xd6, 0x2b, 0x98, 0x2a, 0x41, 0x4b, 0x83, 0x64, 0x0b, 0x92, 0x7a, 0x06, 0x1e, 0xc6, 0x2c, 0xf6, 0xe4, 0x91, 0xe5, 0xb1, 0x2e, 0x6e, 0x4e, 0xa8, 0xc8, 0x14, 0x32, 0x57, 0x44, 0x1c, 0xe4, 0xb9, 0x7f, 0x54, 0x51, 0x08, 0x81, 0xaa, 0x4e, 0xce, 0xa1, 0x5d, + /* (2^194)P */ 0x5c, 0xd5, 0x9b, 0x5e, 0x7c, 0xb5, 0xb1, 0x52, 0x73, 0x00, 0x41, 0x56, 0x79, 0x08, 0x7e, 0x07, 0x28, 0x06, 0xa6, 0xfb, 0x7f, 0x69, 0xbd, 0x7a, 0x3c, 0xae, 0x9f, 0x39, 0xbb, 0x54, 0xa2, 0x79, 0xb9, 0x0e, 0x7f, 0xbb, 0xe0, 0xe6, 0xb7, 0x27, 0x64, 0x38, 0x45, 0xdb, 0x84, 0xe4, 0x61, 0x72, 0x3f, 0xe2, 0x24, 0xfe, 0x7a, 0x31, 0x9a, 0xc9, + /* (2^195)P */ 0xa1, 0xd2, 0xa4, 0xee, 0x24, 0x96, 0xe5, 0x5b, 0x79, 0x78, 0x3c, 0x7b, 0x82, 0x3b, 0x8b, 0x58, 0x0b, 0xa3, 0x63, 0x2d, 0xbc, 0x75, 0x46, 0xe8, 0x83, 0x1a, 0xc0, 0x2a, 0x92, 0x61, 0xa8, 0x75, 0x37, 0x3c, 0xbf, 0x0f, 0xef, 0x8f, 0x6c, 0x97, 0x75, 0x10, 0x05, 0x7a, 0xde, 0x23, 0xe8, 0x2a, 0x35, 0xeb, 0x41, 0x64, 0x7d, 0xcf, 0xe0, 0x52, + /* (2^196)P */ 0x4a, 0xd0, 0x49, 0x93, 0xae, 0xf3, 0x24, 0x8c, 0xe1, 0x09, 0x98, 0x45, 0xd8, 0xb9, 0xfe, 0x8e, 0x8c, 0xa8, 0x2c, 0xc9, 0x9f, 0xce, 0x01, 0xdc, 0x38, 0x11, 0xab, 0x85, 0xb9, 0xe8, 0x00, 0x51, 0xfd, 0x82, 0xe1, 0x9b, 0x4e, 0xfc, 0xb5, 0x2a, 0x0f, 0x8b, 0xda, 0x4e, 0x02, 0xca, 0xcc, 0xe3, 0x91, 0xc4, 0xe0, 0xcf, 0x7b, 0xd6, 0xe6, 0x6a, + /* (2^197)P */ 0xfe, 0x11, 0xd7, 0xaa, 0xe3, 0x0c, 0x52, 0x2e, 0x04, 0xe0, 0xe0, 0x61, 0xc8, 0x05, 0xd7, 0x31, 0x4c, 0xc3, 0x9b, 0x2d, 0xce, 0x59, 0xbe, 0x12, 0xb7, 0x30, 0x21, 0xfc, 0x81, 0xb8, 0x5e, 0x57, 0x73, 0xd0, 0xad, 0x8e, 0x9e, 0xe4, 0xeb, 0xcd, 0xcf, 0xd2, 0x0f, 0x01, 0x35, 0x16, 0xed, 0x7a, 0x43, 0x8e, 0x42, 0xdc, 0xea, 0x4c, 0xa8, 0x7c, + /* (2^198)P */ 0x37, 0x26, 0xcc, 0x76, 0x0b, 0xe5, 0x76, 0xdd, 0x3e, 0x19, 0x3c, 0xc4, 0x6c, 0x7f, 0xd0, 0x03, 0xc1, 0xb8, 0x59, 0x82, 0xca, 0x36, 0xc1, 0xe4, 0xc8, 0xb2, 0x83, 0x69, 0x9c, 0xc5, 0x9d, 0x12, 0x82, 0x1c, 0xea, 0xb2, 0x84, 0x9f, 0xf3, 0x52, 0x6b, 0xbb, 0xd8, 0x81, 0x56, 0x83, 0x04, 0x66, 0x05, 0x22, 0x49, 0x37, 0x93, 0xb1, 0xfd, 0xd5, + /* (2^199)P */ 0xaf, 0x96, 0xbf, 0x03, 0xbe, 0xe6, 0x5d, 0x78, 0x19, 0xba, 0x37, 0x46, 0x0a, 0x2b, 0x52, 0x7c, 0xd8, 0x51, 0x9e, 0x3d, 0x29, 0x42, 0xdb, 0x0e, 0x31, 0x20, 0x94, 0xf8, 0x43, 0x9a, 0x2d, 0x22, 0xd3, 0xe3, 0xa1, 0x79, 0x68, 0xfb, 0x2d, 0x7e, 0xd6, 0x79, 0xda, 0x0b, 0xc6, 0x5b, 0x76, 0x68, 0xf0, 0xfe, 0x72, 0x59, 0xbb, 0xa1, 0x9c, 0x74, + /* (2^200)P */ 0x0a, 0xd9, 0xec, 0xc5, 0xbd, 0xf0, 0xda, 0xcf, 0x82, 0xab, 0x46, 0xc5, 0x32, 0x13, 0xdc, 0x5b, 0xac, 0xc3, 0x53, 0x9a, 0x7f, 0xef, 0xa5, 0x40, 0x5a, 0x1f, 0xc1, 0x12, 0x91, 0x54, 0x83, 0x6a, 0xb0, 0x9a, 0x85, 0x4d, 0xbf, 0x36, 0x8e, 0xd3, 0xa2, 0x2b, 0xe5, 0xd6, 0xc6, 0xe1, 0x58, 0x5b, 0x82, 0x9b, 0xc8, 0xf2, 0x03, 0xba, 0xf5, 0x92, + /* (2^201)P */ 0xfb, 0x21, 0x7e, 0xde, 0xe7, 0xb4, 0xc0, 0x56, 0x86, 0x3a, 0x5b, 0x78, 0xf8, 0xf0, 0xf4, 0xe7, 0x5c, 0x00, 0xd2, 0xd7, 0xd6, 0xf8, 0x75, 0x5e, 0x0f, 0x3e, 0xd1, 0x4b, 0x77, 0xd8, 0xad, 0xb0, 0xc9, 0x8b, 0x59, 0x7d, 0x30, 0x76, 0x64, 0x7a, 0x76, 0xd9, 0x51, 0x69, 0xfc, 0xbd, 0x8e, 0xb5, 0x55, 0xe0, 0xd2, 0x07, 0x15, 0xa9, 0xf7, 0xa4, + /* (2^202)P */ 0xaa, 0x2d, 0x2f, 0x2b, 0x3c, 0x15, 0xdd, 0xcd, 0xe9, 0x28, 0x82, 0x4f, 0xa2, 0xaa, 0x31, 0x48, 0xcc, 0xfa, 0x07, 0x73, 0x8a, 0x34, 0x74, 0x0d, 0xab, 0x1a, 0xca, 0xd2, 0xbf, 0x3a, 0xdb, 0x1a, 0x5f, 0x50, 0x62, 0xf4, 0x6b, 0x83, 0x38, 0x43, 0x96, 0xee, 0x6b, 0x39, 0x1e, 0xf0, 0x17, 0x80, 0x1e, 0x9b, 0xed, 0x2b, 0x2f, 0xcc, 0x65, 0xf7, + /* (2^203)P */ 0x03, 0xb3, 0x23, 0x9c, 0x0d, 0xd1, 0xeb, 0x7e, 0x34, 0x17, 0x8a, 0x4c, 0xde, 0x54, 0x39, 0xc4, 0x11, 0x82, 0xd3, 0xa4, 0x00, 0x32, 0x95, 0x9c, 0xa6, 0x64, 0x76, 0x6e, 0xd6, 0x53, 0x27, 0xb4, 0x6a, 0x14, 0x8c, 0x54, 0xf6, 0x58, 0x9e, 0x22, 0x4a, 0x55, 0x18, 0x77, 0xd0, 0x08, 0x6b, 0x19, 0x8a, 0xb5, 0xe7, 0x19, 0xb8, 0x60, 0x92, 0xb1, + /* (2^204)P */ 0x66, 0xec, 0xf3, 0x12, 0xde, 0x67, 0x7f, 0xd4, 0x5b, 0xf6, 0x70, 0x64, 0x0a, 0xb5, 0xc2, 0xf9, 0xb3, 0x64, 0xab, 0x56, 0x46, 0xc7, 0x93, 0xc2, 0x8b, 0x2d, 0xd0, 0xd6, 0x39, 0x3b, 0x1f, 0xcd, 0xb3, 0xac, 0xcc, 0x2c, 0x27, 0x6a, 0xbc, 0xb3, 0x4b, 0xa8, 0x3c, 0x69, 0x20, 0xe2, 0x18, 0x35, 0x17, 0xe1, 0x8a, 0xd3, 0x11, 0x74, 0xaa, 0x4d, + /* (2^205)P */ 0x96, 0xc4, 0x16, 0x7e, 0xfd, 0xf5, 0xd0, 0x7d, 0x1f, 0x32, 0x1b, 0xdb, 0xa6, 0xfd, 0x51, 0x75, 0x4d, 0xd7, 0x00, 0xe5, 0x7f, 0x58, 0x5b, 0xeb, 0x4b, 0x6a, 0x78, 0xfe, 0xe5, 0xd6, 0x8f, 0x99, 0x17, 0xca, 0x96, 0x45, 0xf7, 0x52, 0xdf, 0x84, 0x06, 0x77, 0xb9, 0x05, 0x63, 0x5d, 0xe9, 0x91, 0xb1, 0x4b, 0x82, 0x5a, 0xdb, 0xd7, 0xca, 0x69, + /* (2^206)P */ 0x02, 0xd3, 0x38, 0x38, 0x87, 0xea, 0xbd, 0x9f, 0x11, 0xca, 0xf3, 0x21, 0xf1, 0x9b, 0x35, 0x97, 0x98, 0xff, 0x8e, 0x6d, 0x3d, 0xd6, 0xb2, 0xfa, 0x68, 0xcb, 0x7e, 0x62, 0x85, 0xbb, 0xc7, 0x5d, 0xee, 0x32, 0x30, 0x2e, 0x71, 0x96, 0x63, 0x43, 0x98, 0xc4, 0xa7, 0xde, 0x60, 0xb2, 0xd9, 0x43, 0x4a, 0xfa, 0x97, 0x2d, 0x5f, 0x21, 0xd4, 0xfe, + /* (2^207)P */ 0x3b, 0x20, 0x29, 0x07, 0x07, 0xb5, 0x78, 0xc3, 0xc7, 0xab, 0x56, 0xba, 0x40, 0xde, 0x1d, 0xcf, 0xc3, 0x00, 0x56, 0x21, 0x0c, 0xc8, 0x42, 0xd9, 0x0e, 0xcd, 0x02, 0x7c, 0x07, 0xb9, 0x11, 0xd7, 0x96, 0xaf, 0xff, 0xad, 0xc5, 0xba, 0x30, 0x6d, 0x82, 0x3a, 0xbf, 0xef, 0x7b, 0xf7, 0x0a, 0x74, 0xbd, 0x31, 0x0c, 0xe4, 0xec, 0x1a, 0xe5, 0xc5, + /* (2^208)P */ 0xcc, 0xf2, 0x28, 0x16, 0x12, 0xbf, 0xef, 0x85, 0xbc, 0xf7, 0xcb, 0x9f, 0xdb, 0xa8, 0xb2, 0x49, 0x53, 0x48, 0xa8, 0x24, 0xa8, 0x68, 0x8d, 0xbb, 0x21, 0x0a, 0x5a, 0xbd, 0xb2, 0x91, 0x61, 0x47, 0xc4, 0x43, 0x08, 0xa6, 0x19, 0xef, 0x8e, 0x88, 0x39, 0xc6, 0x33, 0x30, 0xf3, 0x0e, 0xc5, 0x92, 0x66, 0xd6, 0xfe, 0xc5, 0x12, 0xd9, 0x4c, 0x2d, + /* (2^209)P */ 0x30, 0x34, 0x07, 0xbf, 0x9c, 0x5a, 0x4e, 0x65, 0xf1, 0x39, 0x35, 0x38, 0xae, 0x7b, 0x55, 0xac, 0x6a, 0x92, 0x24, 0x7e, 0x50, 0xd3, 0xba, 0x78, 0x51, 0xfe, 0x4d, 0x32, 0x05, 0x11, 0xf5, 0x52, 0xf1, 0x31, 0x45, 0x39, 0x98, 0x7b, 0x28, 0x56, 0xc3, 0x5d, 0x4f, 0x07, 0x6f, 0x84, 0xb8, 0x1a, 0x58, 0x0b, 0xc4, 0x7c, 0xc4, 0x8d, 0x32, 0x8e, + /* (2^210)P */ 0x7e, 0xaf, 0x98, 0xce, 0xc5, 0x2b, 0x9d, 0xf6, 0xfa, 0x2c, 0xb6, 0x2a, 0x5a, 0x1d, 0xc0, 0x24, 0x8d, 0xa4, 0xce, 0xb1, 0x12, 0x01, 0xf9, 0x79, 0xc6, 0x79, 0x38, 0x0c, 0xd4, 0x07, 0xc9, 0xf7, 0x37, 0xa1, 0x0b, 0xfe, 0x72, 0xec, 0x5d, 0xd6, 0xb0, 0x1c, 0x70, 0xbe, 0x70, 0x01, 0x13, 0xe0, 0x86, 0x95, 0xc7, 0x2e, 0x12, 0x3b, 0xe6, 0xa6, + /* (2^211)P */ 0x24, 0x82, 0x67, 0xe0, 0x14, 0x7b, 0x56, 0x08, 0x38, 0x44, 0xdb, 0xa0, 0x3a, 0x05, 0x47, 0xb2, 0xc0, 0xac, 0xd1, 0xcc, 0x3f, 0x82, 0xb8, 0x8a, 0x88, 0xbc, 0xf5, 0x33, 0xa1, 0x35, 0x0f, 0xf6, 0xe2, 0xef, 0x6c, 0xf7, 0x37, 0x9e, 0xe8, 0x10, 0xca, 0xb0, 0x8e, 0x80, 0x86, 0x00, 0x23, 0xd0, 0x4a, 0x76, 0x9f, 0xf7, 0x2c, 0x52, 0x15, 0x0e, + /* (2^212)P */ 0x5e, 0x49, 0xe1, 0x2c, 0x9a, 0x01, 0x76, 0xa6, 0xb3, 0x07, 0x5b, 0xa4, 0x07, 0xef, 0x1d, 0xc3, 0x6a, 0xbb, 0x64, 0xbe, 0x71, 0x15, 0x6e, 0x32, 0x31, 0x46, 0x9a, 0x9e, 0x8f, 0x45, 0x73, 0xce, 0x0b, 0x94, 0x1a, 0x52, 0x07, 0xf4, 0x50, 0x30, 0x49, 0x53, 0x50, 0xfb, 0x71, 0x1f, 0x5a, 0x03, 0xa9, 0x76, 0xf2, 0x8f, 0x42, 0xff, 0xed, 0xed, + /* (2^213)P */ 0xed, 0x08, 0xdb, 0x91, 0x1c, 0xee, 0xa2, 0xb4, 0x47, 0xa2, 0xfa, 0xcb, 0x03, 0xd1, 0xff, 0x8c, 0xad, 0x64, 0x50, 0x61, 0xcd, 0xfc, 0x88, 0xa0, 0x31, 0x95, 0x30, 0xb9, 0x58, 0xdd, 0xd7, 0x43, 0xe4, 0x46, 0xc2, 0x16, 0xd9, 0x72, 0x4a, 0x56, 0x51, 0x70, 0x85, 0xf1, 0xa1, 0x80, 0x40, 0xd5, 0xba, 0x67, 0x81, 0xda, 0xcd, 0x03, 0xea, 0x51, + /* (2^214)P */ 0x42, 0x50, 0xf0, 0xef, 0x37, 0x61, 0x72, 0x85, 0xe1, 0xf1, 0xff, 0x6f, 0x3d, 0xe8, 0x7b, 0x21, 0x5c, 0xe5, 0x50, 0x03, 0xde, 0x00, 0xc1, 0xf7, 0x3a, 0x55, 0x12, 0x1c, 0x9e, 0x1e, 0xce, 0xd1, 0x2f, 0xaf, 0x05, 0x70, 0x5b, 0x47, 0xf2, 0x04, 0x7a, 0x89, 0xbc, 0x78, 0xa6, 0x65, 0x6c, 0xaa, 0x3c, 0xa2, 0x3c, 0x8b, 0x5c, 0xa9, 0x22, 0x48, + /* (2^215)P */ 0x7e, 0x8c, 0x8f, 0x2f, 0x60, 0xe3, 0x5a, 0x94, 0xd4, 0xce, 0xdd, 0x9d, 0x83, 0x3b, 0x77, 0x78, 0x43, 0x1d, 0xfd, 0x8f, 0xc8, 0xe8, 0x02, 0x90, 0xab, 0xf6, 0xc9, 0xfc, 0xf1, 0x63, 0xaa, 0x5f, 0x42, 0xf1, 0x78, 0x34, 0x64, 0x16, 0x75, 0x9c, 0x7d, 0xd0, 0xe4, 0x74, 0x5a, 0xa8, 0xfb, 0xcb, 0xac, 0x20, 0xa3, 0xc2, 0xa6, 0x20, 0xf8, 0x1b, + /* (2^216)P */ 0x00, 0x4f, 0x1e, 0x56, 0xb5, 0x34, 0xb2, 0x87, 0x31, 0xe5, 0xee, 0x8d, 0xf1, 0x41, 0x67, 0xb7, 0x67, 0x3a, 0x54, 0x86, 0x5c, 0xf0, 0x0b, 0x37, 0x2f, 0x1b, 0x92, 0x5d, 0x58, 0x93, 0xdc, 0xd8, 0x58, 0xcc, 0x9e, 0x67, 0xd0, 0x97, 0x3a, 0xaf, 0x49, 0x39, 0x2d, 0x3b, 0xd8, 0x98, 0xfb, 0x76, 0x6b, 0xe7, 0xaf, 0xc3, 0x45, 0x44, 0x53, 0x94, + /* (2^217)P */ 0x30, 0xbd, 0x90, 0x75, 0xd3, 0xbd, 0x3b, 0x58, 0x27, 0x14, 0x9f, 0x6b, 0xd4, 0x31, 0x99, 0xcd, 0xde, 0x3a, 0x21, 0x1e, 0xb4, 0x02, 0xe4, 0x33, 0x04, 0x02, 0xb0, 0x50, 0x66, 0x68, 0x90, 0xdd, 0x7b, 0x69, 0x31, 0xd9, 0xcf, 0x68, 0x73, 0xf1, 0x60, 0xdd, 0xc8, 0x1d, 0x5d, 0xe3, 0xd6, 0x5b, 0x2a, 0xa4, 0xea, 0xc4, 0x3f, 0x08, 0xcd, 0x9c, + /* (2^218)P */ 0x6b, 0x1a, 0xbf, 0x55, 0xc1, 0x1b, 0x0c, 0x05, 0x09, 0xdf, 0xf5, 0x5e, 0xa3, 0x77, 0x95, 0xe9, 0xdf, 0x19, 0xdd, 0xc7, 0x94, 0xcb, 0x06, 0x73, 0xd0, 0x88, 0x02, 0x33, 0x94, 0xca, 0x7a, 0x2f, 0x8e, 0x3d, 0x72, 0x61, 0x2d, 0x4d, 0xa6, 0x61, 0x1f, 0x32, 0x5e, 0x87, 0x53, 0x36, 0x11, 0x15, 0x20, 0xb3, 0x5a, 0x57, 0x51, 0x93, 0x20, 0xd8, + /* (2^219)P */ 0xb7, 0x56, 0xf4, 0xab, 0x7d, 0x0c, 0xfb, 0x99, 0x1a, 0x30, 0x29, 0xb0, 0x75, 0x2a, 0xf8, 0x53, 0x71, 0x23, 0xbd, 0xa7, 0xd8, 0x0a, 0xe2, 0x27, 0x65, 0xe9, 0x74, 0x26, 0x98, 0x4a, 0x69, 0x19, 0xb2, 0x4d, 0x0a, 0x17, 0x98, 0xb2, 0xa9, 0x57, 0x4e, 0xf6, 0x86, 0xc8, 0x01, 0xa4, 0xc6, 0x98, 0xad, 0x5a, 0x90, 0x2c, 0x05, 0x46, 0x64, 0xb7, + /* (2^220)P */ 0x7b, 0x91, 0xdf, 0xfc, 0xf8, 0x1c, 0x8c, 0x15, 0x9e, 0xf7, 0xd5, 0xa8, 0xe8, 0xe7, 0xe3, 0xa3, 0xb0, 0x04, 0x74, 0xfa, 0x78, 0xfb, 0x26, 0xbf, 0x67, 0x42, 0xf9, 0x8c, 0x9b, 0xb4, 0x69, 0x5b, 0x02, 0x13, 0x6d, 0x09, 0x6c, 0xd6, 0x99, 0x61, 0x7b, 0x89, 0x4a, 0x67, 0x75, 0xa3, 0x98, 0x13, 0x23, 0x1d, 0x18, 0x24, 0x0e, 0xef, 0x41, 0x79, + /* (2^221)P */ 0x86, 0x33, 0xab, 0x08, 0xcb, 0xbf, 0x1e, 0x76, 0x3c, 0x0b, 0xbd, 0x30, 0xdb, 0xe9, 0xa3, 0x35, 0x87, 0x1b, 0xe9, 0x07, 0x00, 0x66, 0x7f, 0x3b, 0x35, 0x0c, 0x8a, 0x3f, 0x61, 0xbc, 0xe0, 0xae, 0xf6, 0xcc, 0x54, 0xe1, 0x72, 0x36, 0x2d, 0xee, 0x93, 0x24, 0xf8, 0xd7, 0xc5, 0xf9, 0xcb, 0xb0, 0xe5, 0x88, 0x0d, 0x23, 0x4b, 0x76, 0x15, 0xa2, + /* (2^222)P */ 0x37, 0xdb, 0x83, 0xd5, 0x6d, 0x06, 0x24, 0x37, 0x1b, 0x15, 0x85, 0x15, 0xe2, 0xc0, 0x4e, 0x02, 0xa9, 0x6d, 0x0a, 0x3a, 0x94, 0x4a, 0x6f, 0x49, 0x00, 0x01, 0x72, 0xbb, 0x60, 0x14, 0x35, 0xae, 0xb4, 0xc6, 0x01, 0x0a, 0x00, 0x9e, 0xc3, 0x58, 0xc5, 0xd1, 0x5e, 0x30, 0x73, 0x96, 0x24, 0x85, 0x9d, 0xf0, 0xf9, 0xec, 0x09, 0xd3, 0xe7, 0x70, + /* (2^223)P */ 0xf3, 0xbd, 0x96, 0x87, 0xe9, 0x71, 0xbd, 0xd6, 0xa2, 0x45, 0xeb, 0x0a, 0xcd, 0x2c, 0xf1, 0x72, 0xa6, 0x31, 0xa9, 0x6f, 0x09, 0xa1, 0x5e, 0xdd, 0xc8, 0x8d, 0x0d, 0xbc, 0x5a, 0x8d, 0xb1, 0x2c, 0x9a, 0xcc, 0x37, 0x74, 0xc2, 0xa9, 0x4e, 0xd6, 0xc0, 0x3c, 0xa0, 0x23, 0xb0, 0xa0, 0x77, 0x14, 0x80, 0x45, 0x71, 0x6a, 0x2d, 0x41, 0xc3, 0x82, + /* (2^224)P */ 0x37, 0x44, 0xec, 0x8a, 0x3e, 0xc1, 0x0c, 0xa9, 0x12, 0x9c, 0x08, 0x88, 0xcb, 0xd9, 0xf8, 0xba, 0x00, 0xd6, 0xc3, 0xdf, 0xef, 0x7a, 0x44, 0x7e, 0x25, 0x69, 0xc9, 0xc1, 0x46, 0xe5, 0x20, 0x9e, 0xcc, 0x0b, 0x05, 0x3e, 0xf4, 0x78, 0x43, 0x0c, 0xa6, 0x2f, 0xc1, 0xfa, 0x70, 0xb2, 0x3c, 0x31, 0x7a, 0x63, 0x58, 0xab, 0x17, 0xcf, 0x4c, 0x4f, + /* (2^225)P */ 0x2b, 0x08, 0x31, 0x59, 0x75, 0x8b, 0xec, 0x0a, 0xa9, 0x79, 0x70, 0xdd, 0xf1, 0x11, 0xc3, 0x11, 0x1f, 0xab, 0x37, 0xaa, 0x26, 0xea, 0x53, 0xc4, 0x79, 0xa7, 0x91, 0x00, 0xaa, 0x08, 0x42, 0xeb, 0x8b, 0x8b, 0xe8, 0xc3, 0x2f, 0xb8, 0x78, 0x90, 0x38, 0x0e, 0x8a, 0x42, 0x0c, 0x0f, 0xbf, 0x3e, 0xf8, 0xd8, 0x07, 0xcf, 0x6a, 0x34, 0xc9, 0xfa, + /* (2^226)P */ 0x11, 0xe0, 0x76, 0x4d, 0x23, 0xc5, 0xa6, 0xcc, 0x9f, 0x9a, 0x2a, 0xde, 0x3a, 0xb5, 0x92, 0x39, 0x19, 0x8a, 0xf1, 0x8d, 0xf9, 0x4d, 0xc9, 0xb4, 0x39, 0x9f, 0x57, 0xd8, 0x72, 0xab, 0x1d, 0x61, 0x6a, 0xb2, 0xff, 0x52, 0xba, 0x54, 0x0e, 0xfb, 0x83, 0x30, 0x8a, 0xf7, 0x3b, 0xf4, 0xd8, 0xae, 0x1a, 0x94, 0x3a, 0xec, 0x63, 0xfe, 0x6e, 0x7c, + /* (2^227)P */ 0xdc, 0x70, 0x8e, 0x55, 0x44, 0xbf, 0xd2, 0x6a, 0xa0, 0x14, 0x61, 0x89, 0xd5, 0x55, 0x45, 0x3c, 0xf6, 0x40, 0x0d, 0x83, 0x85, 0x44, 0xb4, 0x62, 0x56, 0xfe, 0x60, 0xd7, 0x07, 0x1d, 0x47, 0x30, 0x3b, 0x73, 0xa4, 0xb5, 0xb7, 0xea, 0xac, 0xda, 0xf1, 0x17, 0xaa, 0x60, 0xdf, 0xe9, 0x84, 0xda, 0x31, 0x32, 0x61, 0xbf, 0xd0, 0x7e, 0x8a, 0x02, + /* (2^228)P */ 0xb9, 0x51, 0xb3, 0x89, 0x21, 0x5d, 0xa2, 0xfe, 0x79, 0x2a, 0xb3, 0x2a, 0x3b, 0xe6, 0x6f, 0x2b, 0x22, 0x03, 0xea, 0x7b, 0x1f, 0xaf, 0x85, 0xc3, 0x38, 0x55, 0x5b, 0x8e, 0xb4, 0xaa, 0x77, 0xfe, 0x03, 0x6e, 0xda, 0x91, 0x24, 0x0c, 0x48, 0x39, 0x27, 0x43, 0x16, 0xd2, 0x0a, 0x0d, 0x43, 0xa3, 0x0e, 0xca, 0x45, 0xd1, 0x7f, 0xf5, 0xd3, 0x16, + /* (2^229)P */ 0x3d, 0x32, 0x9b, 0x38, 0xf8, 0x06, 0x93, 0x78, 0x5b, 0x50, 0x2b, 0x06, 0xd8, 0x66, 0xfe, 0xab, 0x9b, 0x58, 0xc7, 0xd1, 0x4d, 0xd5, 0xf8, 0x3b, 0x10, 0x7e, 0x85, 0xde, 0x58, 0x4e, 0xdf, 0x53, 0xd9, 0x58, 0xe0, 0x15, 0x81, 0x9f, 0x1a, 0x78, 0xfc, 0x9f, 0x10, 0xc2, 0x23, 0xd6, 0x78, 0xd1, 0x9d, 0xd2, 0xd5, 0x1c, 0x53, 0xe2, 0xc9, 0x76, + /* (2^230)P */ 0x98, 0x1e, 0x38, 0x7b, 0x71, 0x18, 0x4b, 0x15, 0xaf, 0xa1, 0xa6, 0x98, 0xcb, 0x26, 0xa3, 0xc8, 0x07, 0x46, 0xda, 0x3b, 0x70, 0x65, 0xec, 0x7a, 0x2b, 0x34, 0x94, 0xa8, 0xb6, 0x14, 0xf8, 0x1a, 0xce, 0xf7, 0xc8, 0x60, 0xf3, 0x88, 0xf4, 0x33, 0x60, 0x7b, 0xd1, 0x02, 0xe7, 0xda, 0x00, 0x4a, 0xea, 0xd2, 0xfd, 0x88, 0xd2, 0x99, 0x28, 0xf3, + /* (2^231)P */ 0x28, 0x24, 0x1d, 0x26, 0xc2, 0xeb, 0x8b, 0x3b, 0xb4, 0x6b, 0xbe, 0x6b, 0x77, 0xff, 0xf3, 0x21, 0x3b, 0x26, 0x6a, 0x8c, 0x8e, 0x2a, 0x44, 0xa8, 0x01, 0x2b, 0x71, 0xea, 0x64, 0x30, 0xfd, 0xfd, 0x95, 0xcb, 0x39, 0x38, 0x48, 0xfa, 0x96, 0x97, 0x8c, 0x2f, 0x33, 0xca, 0x03, 0xe6, 0xd7, 0x94, 0x55, 0x6c, 0xc3, 0xb3, 0xa8, 0xf7, 0xae, 0x8c, + /* (2^232)P */ 0xea, 0x62, 0x8a, 0xb4, 0xeb, 0x74, 0xf7, 0xb8, 0xae, 0xc5, 0x20, 0x71, 0x06, 0xd6, 0x7c, 0x62, 0x9b, 0x69, 0x74, 0xef, 0xa7, 0x6d, 0xd6, 0x8c, 0x37, 0xb9, 0xbf, 0xcf, 0xeb, 0xe4, 0x2f, 0x04, 0x02, 0x21, 0x7d, 0x75, 0x6b, 0x92, 0x48, 0xf8, 0x70, 0xad, 0x69, 0xe2, 0xea, 0x0e, 0x88, 0x67, 0x72, 0xcc, 0x2d, 0x10, 0xce, 0x2d, 0xcf, 0x65, + /* (2^233)P */ 0x49, 0xf3, 0x57, 0x64, 0xe5, 0x5c, 0xc5, 0x65, 0x49, 0x97, 0xc4, 0x8a, 0xcc, 0xa9, 0xca, 0x94, 0x7b, 0x86, 0x88, 0xb6, 0x51, 0x27, 0x69, 0xa5, 0x0f, 0x8b, 0x06, 0x59, 0xa0, 0x94, 0xef, 0x63, 0x1a, 0x01, 0x9e, 0x4f, 0xd2, 0x5a, 0x93, 0xc0, 0x7c, 0xe6, 0x61, 0x77, 0xb6, 0xf5, 0x40, 0xd9, 0x98, 0x43, 0x5b, 0x56, 0x68, 0xe9, 0x37, 0x8f, + /* (2^234)P */ 0xee, 0x87, 0xd2, 0x05, 0x1b, 0x39, 0x89, 0x10, 0x07, 0x6d, 0xe8, 0xfd, 0x8b, 0x4d, 0xb2, 0xa7, 0x7b, 0x1e, 0xa0, 0x6c, 0x0d, 0x3d, 0x3d, 0x49, 0xba, 0x61, 0x36, 0x1f, 0xc2, 0x84, 0x4a, 0xcc, 0x87, 0xa9, 0x1b, 0x23, 0x04, 0xe2, 0x3e, 0x97, 0xe1, 0xdb, 0xd5, 0x5a, 0xe8, 0x41, 0x6b, 0xe5, 0x5a, 0xa1, 0x99, 0xe5, 0x7b, 0xa7, 0xe0, 0x3b, + /* (2^235)P */ 0xea, 0xa3, 0x6a, 0xdd, 0x77, 0x7f, 0x77, 0x41, 0xc5, 0x6a, 0xe4, 0xaf, 0x11, 0x5f, 0x88, 0xa5, 0x10, 0xee, 0xd0, 0x8c, 0x0c, 0xb4, 0xa5, 0x2a, 0xd0, 0xd8, 0x1d, 0x47, 0x06, 0xc0, 0xd5, 0xce, 0x51, 0x54, 0x9b, 0x2b, 0xe6, 0x2f, 0xe7, 0xe7, 0x31, 0x5f, 0x5c, 0x23, 0x81, 0x3e, 0x03, 0x93, 0xaa, 0x2d, 0x71, 0x84, 0xa0, 0x89, 0x32, 0xa6, + /* (2^236)P */ 0x55, 0xa3, 0x13, 0x92, 0x4e, 0x93, 0x7d, 0xec, 0xca, 0x57, 0xfb, 0x37, 0xae, 0xd2, 0x18, 0x2e, 0x54, 0x05, 0x6c, 0xd1, 0x28, 0xca, 0x90, 0x40, 0x82, 0x2e, 0x79, 0xc6, 0x5a, 0xc7, 0xdd, 0x84, 0x93, 0xdf, 0x15, 0xb8, 0x1f, 0xb1, 0xf9, 0xaf, 0x2c, 0xe5, 0x32, 0xcd, 0xc2, 0x99, 0x6d, 0xac, 0x85, 0x5c, 0x63, 0xd3, 0xe2, 0xff, 0x24, 0xda, + /* (2^237)P */ 0x2d, 0x8d, 0xfd, 0x65, 0xcc, 0xe5, 0x02, 0xa0, 0xe5, 0xb9, 0xec, 0x59, 0x09, 0x50, 0x27, 0xb7, 0x3d, 0x2a, 0x79, 0xb2, 0x76, 0x5d, 0x64, 0x95, 0xf8, 0xc5, 0xaf, 0x8a, 0x62, 0x11, 0x5c, 0x56, 0x1c, 0x05, 0x64, 0x9e, 0x5e, 0xbd, 0x54, 0x04, 0xe6, 0x9e, 0xab, 0xe6, 0x22, 0x7e, 0x42, 0x54, 0xb5, 0xa5, 0xd0, 0x8d, 0x28, 0x6b, 0x0f, 0x0b, + /* (2^238)P */ 0x2d, 0xb2, 0x8c, 0x59, 0x10, 0x37, 0x84, 0x3b, 0x9b, 0x65, 0x1b, 0x0f, 0x10, 0xf9, 0xea, 0x60, 0x1b, 0x02, 0xf5, 0xee, 0x8b, 0xe6, 0x32, 0x7d, 0x10, 0x7f, 0x5f, 0x8c, 0x72, 0x09, 0x4e, 0x1f, 0x29, 0xff, 0x65, 0xcb, 0x3e, 0x3a, 0xd2, 0x96, 0x50, 0x1e, 0xea, 0x64, 0x99, 0xb5, 0x4c, 0x7a, 0x69, 0xb8, 0x95, 0xae, 0x48, 0xc0, 0x7c, 0xb1, + /* (2^239)P */ 0xcd, 0x7c, 0x4f, 0x3e, 0xea, 0xf3, 0x90, 0xcb, 0x12, 0x76, 0xd1, 0x17, 0xdc, 0x0d, 0x13, 0x0f, 0xfd, 0x4d, 0xb5, 0x1f, 0xe4, 0xdd, 0xf2, 0x4d, 0x58, 0xea, 0xa5, 0x66, 0x92, 0xcf, 0xe5, 0x54, 0xea, 0x9b, 0x35, 0x83, 0x1a, 0x44, 0x8e, 0x62, 0x73, 0x45, 0x98, 0xa3, 0x89, 0x95, 0x52, 0x93, 0x1a, 0x8d, 0x63, 0x0f, 0xc2, 0x57, 0x3c, 0xb1, + /* (2^240)P */ 0x72, 0xb4, 0xdf, 0x51, 0xb7, 0xf6, 0x52, 0xa2, 0x14, 0x56, 0xe5, 0x0a, 0x2e, 0x75, 0x81, 0x02, 0xee, 0x93, 0x48, 0x0a, 0x92, 0x4e, 0x0c, 0x0f, 0xdf, 0x09, 0x89, 0x99, 0xf6, 0xf9, 0x22, 0xa2, 0x32, 0xf8, 0xb0, 0x76, 0x0c, 0xb2, 0x4d, 0x6e, 0xbe, 0x83, 0x35, 0x61, 0x44, 0xd2, 0x58, 0xc7, 0xdd, 0x14, 0xcf, 0xc3, 0x4b, 0x7c, 0x07, 0xee, + /* (2^241)P */ 0x8b, 0x03, 0xee, 0xcb, 0xa7, 0x2e, 0x28, 0xbd, 0x97, 0xd1, 0x4c, 0x2b, 0xd1, 0x92, 0x67, 0x5b, 0x5a, 0x12, 0xbf, 0x29, 0x17, 0xfc, 0x50, 0x09, 0x74, 0x76, 0xa2, 0xd4, 0x82, 0xfd, 0x2c, 0x0c, 0x90, 0xf7, 0xe7, 0xe5, 0x9a, 0x2c, 0x16, 0x40, 0xb9, 0x6c, 0xd9, 0xe0, 0x22, 0x9e, 0xf8, 0xdd, 0x73, 0xe4, 0x7b, 0x9e, 0xbe, 0x4f, 0x66, 0x22, + /* (2^242)P */ 0xa4, 0x10, 0xbe, 0xb8, 0x83, 0x3a, 0x77, 0x8e, 0xea, 0x0a, 0xc4, 0x97, 0x3e, 0xb6, 0x6c, 0x81, 0xd7, 0x65, 0xd9, 0xf7, 0xae, 0xe6, 0xbe, 0xab, 0x59, 0x81, 0x29, 0x4b, 0xff, 0xe1, 0x0f, 0xc3, 0x2b, 0xad, 0x4b, 0xef, 0xc4, 0x50, 0x9f, 0x88, 0x31, 0xf2, 0xde, 0x80, 0xd6, 0xf4, 0x20, 0x9c, 0x77, 0x9b, 0xbe, 0xbe, 0x08, 0xf5, 0xf0, 0x95, + /* (2^243)P */ 0x0e, 0x7c, 0x7b, 0x7c, 0xb3, 0xd8, 0x83, 0xfc, 0x8c, 0x75, 0x51, 0x74, 0x1b, 0xe1, 0x6d, 0x11, 0x05, 0x46, 0x24, 0x0d, 0xa4, 0x2b, 0x32, 0xfd, 0x2c, 0x4e, 0x21, 0xdf, 0x39, 0x6b, 0x96, 0xfc, 0xff, 0x92, 0xfc, 0x35, 0x0d, 0x9a, 0x4b, 0xc0, 0x70, 0x46, 0x32, 0x7d, 0xc0, 0xc4, 0x04, 0xe0, 0x2d, 0x83, 0xa7, 0x00, 0xc7, 0xcb, 0xb4, 0x8f, + /* (2^244)P */ 0xa9, 0x5a, 0x7f, 0x0e, 0xdd, 0x2c, 0x85, 0xaa, 0x4d, 0xac, 0xde, 0xb3, 0xb6, 0xaf, 0xe6, 0xd1, 0x06, 0x7b, 0x2c, 0xa4, 0x01, 0x19, 0x22, 0x7d, 0x78, 0xf0, 0x3a, 0xea, 0x89, 0xfe, 0x21, 0x61, 0x6d, 0xb8, 0xfe, 0xa5, 0x2a, 0xab, 0x0d, 0x7b, 0x51, 0x39, 0xb6, 0xde, 0xbc, 0xf0, 0xc5, 0x48, 0xd7, 0x09, 0x82, 0x6e, 0x66, 0x75, 0xc5, 0xcd, + /* (2^245)P */ 0xee, 0xdf, 0x2b, 0x6c, 0xa8, 0xde, 0x61, 0xe1, 0x27, 0xfa, 0x2a, 0x0f, 0x68, 0xe7, 0x7a, 0x9b, 0x13, 0xe9, 0x56, 0xd2, 0x1c, 0x3d, 0x2f, 0x3c, 0x7a, 0xf6, 0x6f, 0x45, 0xee, 0xe8, 0xf4, 0xa0, 0xa6, 0xe8, 0xa5, 0x27, 0xee, 0xf2, 0x85, 0xa9, 0xd5, 0x0e, 0xa9, 0x26, 0x60, 0xfe, 0xee, 0xc7, 0x59, 0x99, 0x5e, 0xa3, 0xdf, 0x23, 0x36, 0xd5, + /* (2^246)P */ 0x15, 0x66, 0x6f, 0xd5, 0x78, 0xa4, 0x0a, 0xf7, 0xb1, 0xe8, 0x75, 0x6b, 0x48, 0x7d, 0xa6, 0x4d, 0x3d, 0x36, 0x9b, 0xc7, 0xcc, 0x68, 0x9a, 0xfe, 0x2f, 0x39, 0x2a, 0x51, 0x31, 0x39, 0x7d, 0x73, 0x6f, 0xc8, 0x74, 0x72, 0x6f, 0x6e, 0xda, 0x5f, 0xad, 0x48, 0xc8, 0x40, 0xe1, 0x06, 0x01, 0x36, 0xa1, 0x88, 0xc8, 0x99, 0x9c, 0xd1, 0x11, 0x8f, + /* (2^247)P */ 0xab, 0xc5, 0xcb, 0xcf, 0xbd, 0x73, 0x21, 0xd0, 0x82, 0xb1, 0x2e, 0x2d, 0xd4, 0x36, 0x1b, 0xed, 0xa9, 0x8a, 0x26, 0x79, 0xc4, 0x17, 0xae, 0xe5, 0x09, 0x0a, 0x0c, 0xa4, 0x21, 0xa0, 0x6e, 0xdd, 0x62, 0x8e, 0x44, 0x62, 0xcc, 0x50, 0xff, 0x93, 0xb3, 0x9a, 0x72, 0x8c, 0x3f, 0xa1, 0xa6, 0x4d, 0x87, 0xd5, 0x1c, 0x5a, 0xc0, 0x0b, 0x1a, 0xd6, + /* (2^248)P */ 0x67, 0x36, 0x6a, 0x1f, 0x96, 0xe5, 0x80, 0x20, 0xa9, 0xe8, 0x0b, 0x0e, 0x21, 0x29, 0x3f, 0xc8, 0x0a, 0x6d, 0x27, 0x47, 0xca, 0xd9, 0x05, 0x55, 0xbf, 0x11, 0xcf, 0x31, 0x7a, 0x37, 0xc7, 0x90, 0xa9, 0xf4, 0x07, 0x5e, 0xd5, 0xc3, 0x92, 0xaa, 0x95, 0xc8, 0x23, 0x2a, 0x53, 0x45, 0xe3, 0x3a, 0x24, 0xe9, 0x67, 0x97, 0x3a, 0x82, 0xf9, 0xa6, + /* (2^249)P */ 0x92, 0x9e, 0x6d, 0x82, 0x67, 0xe9, 0xf9, 0x17, 0x96, 0x2c, 0xa7, 0xd3, 0x89, 0xf9, 0xdb, 0xd8, 0x20, 0xc6, 0x2e, 0xec, 0x4a, 0x76, 0x64, 0xbf, 0x27, 0x40, 0xe2, 0xb4, 0xdf, 0x1f, 0xa0, 0xef, 0x07, 0x80, 0xfb, 0x8e, 0x12, 0xf8, 0xb8, 0xe1, 0xc6, 0xdf, 0x7c, 0x69, 0x35, 0x5a, 0xe1, 0x8e, 0x5d, 0x69, 0x84, 0x56, 0xb6, 0x31, 0x1c, 0x0b, + /* (2^250)P */ 0xd6, 0x94, 0x5c, 0xef, 0xbb, 0x46, 0x45, 0x44, 0x5b, 0xa1, 0xae, 0x03, 0x65, 0xdd, 0xb5, 0x66, 0x88, 0x35, 0x29, 0x95, 0x16, 0x54, 0xa6, 0xf5, 0xc9, 0x78, 0x34, 0xe6, 0x0f, 0xc4, 0x2b, 0x5b, 0x79, 0x51, 0x68, 0x48, 0x3a, 0x26, 0x87, 0x05, 0x70, 0xaf, 0x8b, 0xa6, 0xc7, 0x2e, 0xb3, 0xa9, 0x10, 0x01, 0xb0, 0xb9, 0x31, 0xfd, 0xdc, 0x80, + /* (2^251)P */ 0x25, 0xf2, 0xad, 0xd6, 0x75, 0xa3, 0x04, 0x05, 0x64, 0x8a, 0x97, 0x60, 0x27, 0x2a, 0xe5, 0x6d, 0xb0, 0x73, 0xf4, 0x07, 0x2a, 0x9d, 0xe9, 0x46, 0xb4, 0x1c, 0x51, 0xf8, 0x63, 0x98, 0x7e, 0xe5, 0x13, 0x51, 0xed, 0x98, 0x65, 0x98, 0x4f, 0x8f, 0xe7, 0x7e, 0x72, 0xd7, 0x64, 0x11, 0x2f, 0xcd, 0x12, 0xf8, 0xc4, 0x63, 0x52, 0x0f, 0x7f, 0xc4, + /* (2^252)P */ 0x5c, 0xd9, 0x85, 0x63, 0xc7, 0x8a, 0x65, 0x9a, 0x25, 0x83, 0x31, 0x73, 0x49, 0xf0, 0x93, 0x96, 0x70, 0x67, 0x6d, 0xb1, 0xff, 0x95, 0x54, 0xe4, 0xf8, 0x15, 0x6c, 0x5f, 0xbd, 0xf6, 0x0f, 0x38, 0x7b, 0x68, 0x7d, 0xd9, 0x3d, 0xf0, 0xa9, 0xa0, 0xe4, 0xd1, 0xb6, 0x34, 0x6d, 0x14, 0x16, 0xc2, 0x4c, 0x30, 0x0e, 0x67, 0xd3, 0xbe, 0x2e, 0xc0, + /* (2^253)P */ 0x06, 0x6b, 0x52, 0xc8, 0x14, 0xcd, 0xae, 0x03, 0x93, 0xea, 0xc1, 0xf2, 0xf6, 0x8b, 0xc5, 0xb6, 0xdc, 0x82, 0x42, 0x29, 0x94, 0xe0, 0x25, 0x6c, 0x3f, 0x9f, 0x5d, 0xe4, 0x96, 0xf6, 0x8e, 0x3f, 0xf9, 0x72, 0xc4, 0x77, 0x60, 0x8b, 0xa4, 0xf9, 0xa8, 0xc3, 0x0a, 0x81, 0xb1, 0x97, 0x70, 0x18, 0xab, 0xea, 0x37, 0x8a, 0x08, 0xc7, 0xe2, 0x95, + /* (2^254)P */ 0x94, 0x49, 0xd9, 0x5f, 0x76, 0x72, 0x82, 0xad, 0x2d, 0x50, 0x1a, 0x7a, 0x5b, 0xe6, 0x95, 0x1e, 0x95, 0x65, 0x87, 0x1c, 0x52, 0xd7, 0x44, 0xe6, 0x9b, 0x56, 0xcd, 0x6f, 0x05, 0xff, 0x67, 0xc5, 0xdb, 0xa2, 0xac, 0xe4, 0xa2, 0x28, 0x63, 0x5f, 0xfb, 0x0c, 0x3b, 0xf1, 0x87, 0xc3, 0x36, 0x78, 0x3f, 0x77, 0xfa, 0x50, 0x85, 0xf9, 0xd7, 0x82, + /* (2^255)P */ 0x64, 0xc0, 0xe0, 0xd8, 0x2d, 0xed, 0xcb, 0x6a, 0xfd, 0xcd, 0xbc, 0x7e, 0x9f, 0xc8, 0x85, 0xe9, 0xc1, 0x7c, 0x0f, 0xe5, 0x18, 0xea, 0xd4, 0x51, 0xad, 0x59, 0x13, 0x75, 0xd9, 0x3d, 0xd4, 0x8a, 0xb2, 0xbe, 0x78, 0x52, 0x2b, 0x52, 0x94, 0x37, 0x41, 0xd6, 0xb4, 0xb6, 0x45, 0x20, 0x76, 0xe0, 0x1f, 0x31, 0xdb, 0xb1, 0xa1, 0x43, 0xf0, 0x18, + /* (2^256)P */ 0x74, 0xa9, 0xa4, 0xa9, 0xdd, 0x6e, 0x3e, 0x68, 0xe5, 0xc3, 0x2e, 0x92, 0x17, 0xa4, 0xcb, 0x80, 0xb1, 0xf0, 0x06, 0x93, 0xef, 0xe6, 0x00, 0xe6, 0x3b, 0xb1, 0x32, 0x65, 0x7b, 0x83, 0xb6, 0x8a, 0x49, 0x1b, 0x14, 0x89, 0xee, 0xba, 0xf5, 0x6a, 0x8d, 0x36, 0xef, 0xb0, 0xd8, 0xb2, 0x16, 0x99, 0x17, 0x35, 0x02, 0x16, 0x55, 0x58, 0xdd, 0x82, + /* (2^257)P */ 0x36, 0x95, 0xe8, 0xf4, 0x36, 0x42, 0xbb, 0xc5, 0x3e, 0xfa, 0x30, 0x84, 0x9e, 0x59, 0xfd, 0xd2, 0x95, 0x42, 0xf8, 0x64, 0xd9, 0xb9, 0x0e, 0x9f, 0xfa, 0xd0, 0x7b, 0x20, 0x31, 0x77, 0x48, 0x29, 0x4d, 0xd0, 0x32, 0x57, 0x56, 0x30, 0xa6, 0x17, 0x53, 0x04, 0xbf, 0x08, 0x28, 0xec, 0xb8, 0x46, 0xc1, 0x03, 0x89, 0xdc, 0xed, 0xa0, 0x35, 0x53, + /* (2^258)P */ 0xc5, 0x7f, 0x9e, 0xd8, 0xc5, 0xba, 0x5f, 0x68, 0xc8, 0x23, 0x75, 0xea, 0x0d, 0xd9, 0x5a, 0xfd, 0x61, 0x1a, 0xa3, 0x2e, 0x45, 0x63, 0x14, 0x55, 0x86, 0x21, 0x29, 0xbe, 0xef, 0x5e, 0x50, 0xe5, 0x18, 0x59, 0xe7, 0xe3, 0xce, 0x4d, 0x8c, 0x15, 0x8f, 0x89, 0x66, 0x44, 0x52, 0x3d, 0xfa, 0xc7, 0x9a, 0x59, 0x90, 0x8e, 0xc0, 0x06, 0x3f, 0xc9, + /* (2^259)P */ 0x8e, 0x04, 0xd9, 0x16, 0x50, 0x1d, 0x8c, 0x9f, 0xd5, 0xe3, 0xce, 0xfd, 0x47, 0x04, 0x27, 0x4d, 0xc2, 0xfa, 0x71, 0xd9, 0x0b, 0xb8, 0x65, 0xf4, 0x11, 0xf3, 0x08, 0xee, 0x81, 0xc8, 0x67, 0x99, 0x0b, 0x8d, 0x77, 0xa3, 0x4f, 0xb5, 0x9b, 0xdb, 0x26, 0xf1, 0x97, 0xeb, 0x04, 0x54, 0xeb, 0x80, 0x08, 0x1d, 0x1d, 0xf6, 0x3d, 0x1f, 0x5a, 0xb8, + /* (2^260)P */ 0xb7, 0x9c, 0x9d, 0xee, 0xb9, 0x5c, 0xad, 0x0d, 0x9e, 0xfd, 0x60, 0x3c, 0x27, 0x4e, 0xa2, 0x95, 0xfb, 0x64, 0x7e, 0x79, 0x64, 0x87, 0x10, 0xb4, 0x73, 0xe0, 0x9d, 0x46, 0x4d, 0x3d, 0xee, 0x83, 0xe4, 0x16, 0x88, 0x97, 0xe6, 0x4d, 0xba, 0x70, 0xb6, 0x96, 0x7b, 0xff, 0x4b, 0xc8, 0xcf, 0x72, 0x83, 0x3e, 0x5b, 0x24, 0x2e, 0x57, 0xf1, 0x82, + /* (2^261)P */ 0x30, 0x71, 0x40, 0x51, 0x4f, 0x44, 0xbb, 0xc7, 0xf0, 0x54, 0x6e, 0x9d, 0xeb, 0x15, 0xad, 0xf8, 0x61, 0x43, 0x5a, 0xef, 0xc0, 0xb1, 0x57, 0xae, 0x03, 0x40, 0xe8, 0x68, 0x6f, 0x03, 0x20, 0x4f, 0x8a, 0x51, 0x2a, 0x9e, 0xd2, 0x45, 0xaf, 0xb4, 0xf5, 0xd4, 0x95, 0x7f, 0x3d, 0x3d, 0xb7, 0xb6, 0x28, 0xc5, 0x08, 0x8b, 0x44, 0xd6, 0x3f, 0xe7, + /* (2^262)P */ 0xa9, 0x52, 0x04, 0x67, 0xcb, 0x20, 0x63, 0xf8, 0x18, 0x01, 0x44, 0x21, 0x6a, 0x8a, 0x83, 0x48, 0xd4, 0xaf, 0x23, 0x0f, 0x35, 0x8d, 0xe5, 0x5a, 0xc4, 0x7c, 0x55, 0x46, 0x19, 0x5f, 0x35, 0xe0, 0x5d, 0x97, 0x4c, 0x2d, 0x04, 0xed, 0x59, 0xd4, 0xb0, 0xb2, 0xc6, 0xe3, 0x51, 0xe1, 0x38, 0xc6, 0x30, 0x49, 0x8f, 0xae, 0x61, 0x64, 0xce, 0xa8, + /* (2^263)P */ 0x9b, 0x64, 0x83, 0x3c, 0xd3, 0xdf, 0xb9, 0x27, 0xe7, 0x5b, 0x7f, 0xeb, 0xf3, 0x26, 0xcf, 0xb1, 0x8f, 0xaf, 0x26, 0xc8, 0x48, 0xce, 0xa1, 0xac, 0x7d, 0x10, 0x34, 0x28, 0xe1, 0x1f, 0x69, 0x03, 0x64, 0x77, 0x61, 0xdd, 0x4a, 0x9b, 0x18, 0x47, 0xf8, 0xca, 0x63, 0xc9, 0x03, 0x2d, 0x20, 0x2a, 0x69, 0x6e, 0x42, 0xd0, 0xe7, 0xaa, 0xb5, 0xf3, + /* (2^264)P */ 0xea, 0x31, 0x0c, 0x57, 0x0f, 0x3e, 0xe3, 0x35, 0xd8, 0x30, 0xa5, 0x6f, 0xdd, 0x95, 0x43, 0xc6, 0x66, 0x07, 0x4f, 0x34, 0xc3, 0x7e, 0x04, 0x10, 0x2d, 0xc4, 0x1c, 0x94, 0x52, 0x2e, 0x5b, 0x9a, 0x65, 0x2f, 0x91, 0xaa, 0x4f, 0x3c, 0xdc, 0x23, 0x18, 0xe1, 0x4f, 0x85, 0xcd, 0xf4, 0x8c, 0x51, 0xf7, 0xab, 0x4f, 0xdc, 0x15, 0x5c, 0x9e, 0xc5, + /* (2^265)P */ 0x54, 0x57, 0x23, 0x17, 0xe7, 0x82, 0x2f, 0x04, 0x7d, 0xfe, 0xe7, 0x1f, 0xa2, 0x57, 0x79, 0xe9, 0x58, 0x9b, 0xbe, 0xc6, 0x16, 0x4a, 0x17, 0x50, 0x90, 0x4a, 0x34, 0x70, 0x87, 0x37, 0x01, 0x26, 0xd8, 0xa3, 0x5f, 0x07, 0x7c, 0xd0, 0x7d, 0x05, 0x8a, 0x93, 0x51, 0x2f, 0x99, 0xea, 0xcf, 0x00, 0xd8, 0xc7, 0xe6, 0x9b, 0x8c, 0x62, 0x45, 0x87, + /* (2^266)P */ 0xc3, 0xfd, 0x29, 0x66, 0xe7, 0x30, 0x29, 0x77, 0xe0, 0x0d, 0x63, 0x5b, 0xe6, 0x90, 0x1a, 0x1e, 0x99, 0xc2, 0xa7, 0xab, 0xff, 0xa7, 0xbd, 0x79, 0x01, 0x97, 0xfd, 0x27, 0x1b, 0x43, 0x2b, 0xe6, 0xfe, 0x5e, 0xf1, 0xb9, 0x35, 0x38, 0x08, 0x25, 0x55, 0x90, 0x68, 0x2e, 0xc3, 0x67, 0x39, 0x9f, 0x2b, 0x2c, 0x70, 0x48, 0x8c, 0x47, 0xee, 0x56, + /* (2^267)P */ 0xf7, 0x32, 0x70, 0xb5, 0xe6, 0x42, 0xfd, 0x0a, 0x39, 0x9b, 0x07, 0xfe, 0x0e, 0xf4, 0x47, 0xba, 0x6a, 0x3f, 0xf5, 0x2c, 0x15, 0xf3, 0x60, 0x3f, 0xb1, 0x83, 0x7b, 0x2e, 0x34, 0x58, 0x1a, 0x6e, 0x4a, 0x49, 0x05, 0x45, 0xca, 0xdb, 0x00, 0x01, 0x0c, 0x42, 0x5e, 0x60, 0x40, 0x5f, 0xd9, 0xc7, 0x3a, 0x9e, 0x1c, 0x8d, 0xab, 0x11, 0x55, 0x65, + /* (2^268)P */ 0x87, 0x40, 0xb7, 0x0d, 0xaa, 0x34, 0x89, 0x90, 0x75, 0x6d, 0xa2, 0xfe, 0x3b, 0x6d, 0x5c, 0x39, 0x98, 0x10, 0x9e, 0x15, 0xc5, 0x35, 0xa2, 0x27, 0x23, 0x0a, 0x2d, 0x60, 0xe2, 0xa8, 0x7f, 0x3e, 0x77, 0x8f, 0xcc, 0x44, 0xcc, 0x30, 0x28, 0xe2, 0xf0, 0x04, 0x8c, 0xee, 0xe4, 0x5f, 0x68, 0x8c, 0xdf, 0x70, 0xbf, 0x31, 0xee, 0x2a, 0xfc, 0xce, + /* (2^269)P */ 0x92, 0xf2, 0xa0, 0xd9, 0x58, 0x3b, 0x7c, 0x1a, 0x99, 0x46, 0x59, 0x54, 0x60, 0x06, 0x8d, 0x5e, 0xf0, 0x22, 0xa1, 0xed, 0x92, 0x8a, 0x4d, 0x76, 0x95, 0x05, 0x0b, 0xff, 0xfc, 0x9a, 0xd1, 0xcc, 0x05, 0xb9, 0x5e, 0x99, 0xe8, 0x2a, 0x76, 0x7b, 0xfd, 0xa6, 0xe2, 0xd1, 0x1a, 0xd6, 0x76, 0x9f, 0x2f, 0x0e, 0xd1, 0xa8, 0x77, 0x5a, 0x40, 0x5a, + /* (2^270)P */ 0xff, 0xf9, 0x3f, 0xa9, 0xa6, 0x6c, 0x6d, 0x03, 0x8b, 0xa7, 0x10, 0x5d, 0x3f, 0xec, 0x3e, 0x1c, 0x0b, 0x6b, 0xa2, 0x6a, 0x22, 0xa9, 0x28, 0xd0, 0x66, 0xc9, 0xc2, 0x3d, 0x47, 0x20, 0x7d, 0xa6, 0x1d, 0xd8, 0x25, 0xb5, 0xf2, 0xf9, 0x70, 0x19, 0x6b, 0xf8, 0x43, 0x36, 0xc5, 0x1f, 0xe4, 0x5a, 0x4c, 0x13, 0xe4, 0x6d, 0x08, 0x0b, 0x1d, 0xb1, + /* (2^271)P */ 0x3f, 0x20, 0x9b, 0xfb, 0xec, 0x7d, 0x31, 0xc5, 0xfc, 0x88, 0x0b, 0x30, 0xed, 0x36, 0xc0, 0x63, 0xb1, 0x7d, 0x10, 0xda, 0xb6, 0x2e, 0xad, 0xf3, 0xec, 0x94, 0xe7, 0xec, 0xb5, 0x9c, 0xfe, 0xf5, 0x35, 0xf0, 0xa2, 0x2d, 0x7f, 0xca, 0x6b, 0x67, 0x1a, 0xf6, 0xb3, 0xda, 0x09, 0x2a, 0xaa, 0xdf, 0xb1, 0xca, 0x9b, 0xfb, 0xeb, 0xb3, 0xcd, 0xc0, + /* (2^272)P */ 0xcd, 0x4d, 0x89, 0x00, 0xa4, 0x3b, 0x48, 0xf0, 0x76, 0x91, 0x35, 0xa5, 0xf8, 0xc9, 0xb6, 0x46, 0xbc, 0xf6, 0x9a, 0x45, 0x47, 0x17, 0x96, 0x80, 0x5b, 0x3a, 0x28, 0x33, 0xf9, 0x5a, 0xef, 0x43, 0x07, 0xfe, 0x3b, 0xf4, 0x8e, 0x19, 0xce, 0xd2, 0x94, 0x4b, 0x6d, 0x8e, 0x67, 0x20, 0xc7, 0x4f, 0x2f, 0x59, 0x8e, 0xe1, 0xa1, 0xa9, 0xf9, 0x0e, + /* (2^273)P */ 0xdc, 0x7b, 0xb5, 0x50, 0x2e, 0xe9, 0x7e, 0x8b, 0x78, 0xa1, 0x38, 0x96, 0x22, 0xc3, 0x61, 0x67, 0x6d, 0xc8, 0x58, 0xed, 0x41, 0x1d, 0x5d, 0x86, 0x98, 0x7f, 0x2f, 0x1b, 0x8d, 0x3e, 0xaa, 0xc1, 0xd2, 0x0a, 0xf3, 0xbf, 0x95, 0x04, 0xf3, 0x10, 0x3c, 0x2b, 0x7f, 0x90, 0x46, 0x04, 0xaa, 0x6a, 0xa9, 0x35, 0x76, 0xac, 0x49, 0xb5, 0x00, 0x45, + /* (2^274)P */ 0xb1, 0x93, 0x79, 0x84, 0x4a, 0x2a, 0x30, 0x78, 0x16, 0xaa, 0xc5, 0x74, 0x06, 0xce, 0xa5, 0xa7, 0x32, 0x86, 0xe0, 0xf9, 0x10, 0xd2, 0x58, 0x76, 0xfb, 0x66, 0x49, 0x76, 0x3a, 0x90, 0xba, 0xb5, 0xcc, 0x99, 0xcd, 0x09, 0xc1, 0x9a, 0x74, 0x23, 0xdf, 0x0c, 0xfe, 0x99, 0x52, 0x80, 0xa3, 0x7c, 0x1c, 0x71, 0x5f, 0x2c, 0x49, 0x57, 0xf4, 0xf9, + /* (2^275)P */ 0x6d, 0xbf, 0x52, 0xe6, 0x25, 0x98, 0xed, 0xcf, 0xe3, 0xbc, 0x08, 0xa2, 0x1a, 0x90, 0xae, 0xa0, 0xbf, 0x07, 0x15, 0xad, 0x0a, 0x9f, 0x3e, 0x47, 0x44, 0xc2, 0x10, 0x46, 0xa6, 0x7a, 0x9e, 0x2f, 0x57, 0xbc, 0xe2, 0xf0, 0x1d, 0xd6, 0x9a, 0x06, 0xed, 0xfc, 0x54, 0x95, 0x92, 0x15, 0xa2, 0xf7, 0x8d, 0x6b, 0xef, 0xb2, 0x05, 0xed, 0x5c, 0x63, + /* (2^276)P */ 0xbc, 0x0b, 0x27, 0x3a, 0x3a, 0xf8, 0xe1, 0x48, 0x02, 0x7e, 0x27, 0xe6, 0x81, 0x62, 0x07, 0x73, 0x74, 0xe5, 0x52, 0xd7, 0xf8, 0x26, 0xca, 0x93, 0x4d, 0x3e, 0x9b, 0x55, 0x09, 0x8e, 0xe3, 0xd7, 0xa6, 0xe3, 0xb6, 0x2a, 0xa9, 0xb3, 0xb0, 0xa0, 0x8c, 0x01, 0xbb, 0x07, 0x90, 0x78, 0x6d, 0x6d, 0xe9, 0xf0, 0x7a, 0x90, 0xbd, 0xdc, 0x0c, 0x36, + /* (2^277)P */ 0x7f, 0x20, 0x12, 0x0f, 0x40, 0x00, 0x53, 0xd8, 0x0c, 0x27, 0x47, 0x47, 0x22, 0x80, 0xfb, 0x62, 0xe4, 0xa7, 0xf7, 0xbd, 0x42, 0xa5, 0xc3, 0x2b, 0xb2, 0x7f, 0x50, 0xcc, 0xe2, 0xfb, 0xd5, 0xc0, 0x63, 0xdd, 0x24, 0x5f, 0x7c, 0x08, 0x91, 0xbf, 0x6e, 0x47, 0x44, 0xd4, 0x6a, 0xc0, 0xc3, 0x09, 0x39, 0x27, 0xdd, 0xc7, 0xca, 0x06, 0x29, 0x55, + /* (2^278)P */ 0x76, 0x28, 0x58, 0xb0, 0xd2, 0xf3, 0x0f, 0x04, 0xe9, 0xc9, 0xab, 0x66, 0x5b, 0x75, 0x51, 0xdc, 0xe5, 0x8f, 0xe8, 0x1f, 0xdb, 0x03, 0x0f, 0xb0, 0x7d, 0xf9, 0x20, 0x64, 0x89, 0xe9, 0xdc, 0xe6, 0x24, 0xc3, 0xd5, 0xd2, 0x41, 0xa6, 0xe4, 0xe3, 0xc4, 0x79, 0x7c, 0x0f, 0xa1, 0x61, 0x2f, 0xda, 0xa4, 0xc9, 0xfd, 0xad, 0x5c, 0x65, 0x6a, 0xf3, + /* (2^279)P */ 0xd5, 0xab, 0x72, 0x7a, 0x3b, 0x59, 0xea, 0xcf, 0xd5, 0x17, 0xd2, 0xb2, 0x5f, 0x2d, 0xab, 0xad, 0x9e, 0x88, 0x64, 0x55, 0x96, 0x6e, 0xf3, 0x44, 0xa9, 0x11, 0xf5, 0xf8, 0x3a, 0xf1, 0xcd, 0x79, 0x4c, 0x99, 0x6d, 0x23, 0x6a, 0xa0, 0xc2, 0x1a, 0x19, 0x45, 0xb5, 0xd8, 0x95, 0x2f, 0x49, 0xe9, 0x46, 0x39, 0x26, 0x60, 0x04, 0x15, 0x8b, 0xcc, + /* (2^280)P */ 0x66, 0x0c, 0xf0, 0x54, 0x41, 0x02, 0x91, 0xab, 0xe5, 0x85, 0x8a, 0x44, 0xa6, 0x34, 0x96, 0x32, 0xc0, 0xdf, 0x6c, 0x41, 0x39, 0xd4, 0xc6, 0xe1, 0xe3, 0x81, 0xb0, 0x4c, 0x34, 0x4f, 0xe5, 0xf4, 0x35, 0x46, 0x1f, 0xeb, 0x75, 0xfd, 0x43, 0x37, 0x50, 0x99, 0xab, 0xad, 0xb7, 0x8c, 0xa1, 0x57, 0xcb, 0xe6, 0xce, 0x16, 0x2e, 0x85, 0xcc, 0xf9, + /* (2^281)P */ 0x63, 0xd1, 0x3f, 0x9e, 0xa2, 0x17, 0x2e, 0x1d, 0x3e, 0xce, 0x48, 0x2d, 0xbb, 0x8f, 0x69, 0xc9, 0xa6, 0x3d, 0x4e, 0xfe, 0x09, 0x56, 0xb3, 0x02, 0x5f, 0x99, 0x97, 0x0c, 0x54, 0xda, 0x32, 0x97, 0x9b, 0xf4, 0x95, 0xf1, 0xad, 0xe3, 0x2b, 0x04, 0xa7, 0x9b, 0x3f, 0xbb, 0xe7, 0x87, 0x2e, 0x1f, 0x8b, 0x4b, 0x7a, 0xa4, 0x43, 0x0c, 0x0f, 0x35, + /* (2^282)P */ 0x05, 0xdc, 0xe0, 0x2c, 0xa1, 0xc1, 0xd0, 0xf1, 0x1f, 0x4e, 0xc0, 0x6c, 0x35, 0x7b, 0xca, 0x8f, 0x8b, 0x02, 0xb1, 0xf7, 0xd6, 0x2e, 0xe7, 0x93, 0x80, 0x85, 0x18, 0x88, 0x19, 0xb9, 0xb4, 0x4a, 0xbc, 0xeb, 0x5a, 0x78, 0x38, 0xed, 0xc6, 0x27, 0x2a, 0x74, 0x76, 0xf0, 0x1b, 0x79, 0x92, 0x2f, 0xd2, 0x81, 0x98, 0xdf, 0xa9, 0x50, 0x19, 0xeb, + /* (2^283)P */ 0xb5, 0xe7, 0xb4, 0x11, 0x3a, 0x81, 0xb6, 0xb4, 0xf8, 0xa2, 0xb3, 0x6c, 0xfc, 0x9d, 0xe0, 0xc0, 0xe0, 0x59, 0x7f, 0x05, 0x37, 0xef, 0x2c, 0xa9, 0x3a, 0x24, 0xac, 0x7b, 0x25, 0xa0, 0x55, 0xd2, 0x44, 0x82, 0x82, 0x6e, 0x64, 0xa3, 0x58, 0xc8, 0x67, 0xae, 0x26, 0xa7, 0x0f, 0x42, 0x63, 0xe1, 0x93, 0x01, 0x52, 0x19, 0xaf, 0x49, 0x3e, 0x33, + /* (2^284)P */ 0x05, 0x85, 0xe6, 0x66, 0xaf, 0x5f, 0xdf, 0xbf, 0x9d, 0x24, 0x62, 0x60, 0x90, 0xe2, 0x4c, 0x7d, 0x4e, 0xc3, 0x74, 0x5d, 0x4f, 0x53, 0xf3, 0x63, 0x13, 0xf4, 0x74, 0x28, 0x6b, 0x7d, 0x57, 0x0c, 0x9d, 0x84, 0xa7, 0x1a, 0xff, 0xa0, 0x79, 0xdf, 0xfc, 0x65, 0x98, 0x8e, 0x22, 0x0d, 0x62, 0x7e, 0xf2, 0x34, 0x60, 0x83, 0x05, 0x14, 0xb1, 0xc1, + /* (2^285)P */ 0x64, 0x22, 0xcc, 0xdf, 0x5c, 0xbc, 0x88, 0x68, 0x4c, 0xd9, 0xbc, 0x0e, 0xc9, 0x8b, 0xb4, 0x23, 0x52, 0xad, 0xb0, 0xb3, 0xf1, 0x17, 0xd8, 0x15, 0x04, 0x6b, 0x99, 0xf0, 0xc4, 0x7d, 0x48, 0x22, 0x4a, 0xf8, 0x6f, 0xaa, 0x88, 0x0d, 0xc5, 0x5e, 0xa9, 0x1c, 0x61, 0x3d, 0x95, 0xa9, 0x7b, 0x6a, 0x79, 0x33, 0x0a, 0x2b, 0x99, 0xe3, 0x4e, 0x48, + /* (2^286)P */ 0x6b, 0x9b, 0x6a, 0x2a, 0xf1, 0x60, 0x31, 0xb4, 0x73, 0xd1, 0x87, 0x45, 0x9c, 0x15, 0x58, 0x4b, 0x91, 0x6d, 0x94, 0x1c, 0x41, 0x11, 0x4a, 0x83, 0xec, 0xaf, 0x65, 0xbc, 0x34, 0xaa, 0x26, 0xe2, 0xaf, 0xed, 0x46, 0x05, 0x4e, 0xdb, 0xc6, 0x4e, 0x10, 0x28, 0x4e, 0x72, 0xe5, 0x31, 0xa3, 0x20, 0xd7, 0xb1, 0x96, 0x64, 0xf6, 0xce, 0x08, 0x08, + /* (2^287)P */ 0x16, 0xa9, 0x5c, 0x9f, 0x9a, 0xb4, 0xb8, 0xc8, 0x32, 0x78, 0xc0, 0x3a, 0xd9, 0x5f, 0x94, 0xac, 0x3a, 0x42, 0x1f, 0x43, 0xd6, 0x80, 0x47, 0x2c, 0xdc, 0x76, 0x27, 0xfa, 0x50, 0xe5, 0xa1, 0xe4, 0xc3, 0xcb, 0x61, 0x31, 0xe1, 0x2e, 0xde, 0x81, 0x3b, 0x77, 0x1c, 0x39, 0x3c, 0xdb, 0xda, 0x87, 0x4b, 0x84, 0x12, 0xeb, 0xdd, 0x54, 0xbf, 0xe7, + /* (2^288)P */ 0xbf, 0xcb, 0x73, 0x21, 0x3d, 0x7e, 0x13, 0x8c, 0xa6, 0x34, 0x21, 0x2b, 0xa5, 0xe4, 0x9f, 0x8e, 0x9c, 0x01, 0x9c, 0x43, 0xd9, 0xc7, 0xb9, 0xf1, 0xbe, 0x7f, 0x45, 0x51, 0x97, 0xa1, 0x8e, 0x01, 0xf8, 0xbd, 0xd2, 0xbf, 0x81, 0x3a, 0x8b, 0xab, 0xe4, 0x89, 0xb7, 0xbd, 0xf2, 0xcd, 0xa9, 0x8a, 0x8a, 0xde, 0xfb, 0x8a, 0x55, 0x12, 0x7b, 0x17, + /* (2^289)P */ 0x1b, 0x95, 0x58, 0x4d, 0xe6, 0x51, 0x31, 0x52, 0x1c, 0xd8, 0x15, 0x84, 0xb1, 0x0d, 0x36, 0x25, 0x88, 0x91, 0x46, 0x71, 0x42, 0x56, 0xe2, 0x90, 0x08, 0x9e, 0x77, 0x1b, 0xee, 0x22, 0x3f, 0xec, 0xee, 0x8c, 0x7b, 0x2e, 0x79, 0xc4, 0x6c, 0x07, 0xa1, 0x7e, 0x52, 0xf5, 0x26, 0x5c, 0x84, 0x2a, 0x50, 0x6e, 0x82, 0xb3, 0x76, 0xda, 0x35, 0x16, + /* (2^290)P */ 0x0a, 0x6f, 0x99, 0x87, 0xc0, 0x7d, 0x8a, 0xb2, 0xca, 0xae, 0xe8, 0x65, 0x98, 0x0f, 0xb3, 0x44, 0xe1, 0xdc, 0x52, 0x79, 0x75, 0xec, 0x8f, 0x95, 0x87, 0x45, 0xd1, 0x32, 0x18, 0x55, 0x15, 0xce, 0x64, 0x9b, 0x08, 0x4f, 0x2c, 0xea, 0xba, 0x1c, 0x57, 0x06, 0x63, 0xc8, 0xb1, 0xfd, 0xc5, 0x67, 0xe7, 0x1f, 0x87, 0x9e, 0xde, 0x72, 0x7d, 0xec, + /* (2^291)P */ 0x36, 0x8b, 0x4d, 0x2c, 0xc2, 0x46, 0xe8, 0x96, 0xac, 0x0b, 0x8c, 0xc5, 0x09, 0x10, 0xfc, 0xf2, 0xda, 0xea, 0x22, 0xb2, 0xd3, 0x89, 0xeb, 0xb2, 0x85, 0x0f, 0xff, 0x59, 0x50, 0x2c, 0x99, 0x5a, 0x1f, 0xec, 0x2a, 0x6f, 0xec, 0xcf, 0xe9, 0xce, 0x12, 0x6b, 0x19, 0xd8, 0xde, 0x9b, 0xce, 0x0e, 0x6a, 0xaa, 0xe1, 0x32, 0xea, 0x4c, 0xfe, 0x92, + /* (2^292)P */ 0x5f, 0x17, 0x70, 0x53, 0x26, 0x03, 0x0b, 0xab, 0xd1, 0xc1, 0x42, 0x0b, 0xab, 0x2b, 0x3d, 0x31, 0xa4, 0xd5, 0x2b, 0x5e, 0x00, 0xd5, 0x9a, 0x22, 0x34, 0xe0, 0x53, 0x3f, 0x59, 0x7f, 0x2c, 0x6d, 0x72, 0x9a, 0xa4, 0xbe, 0x3d, 0x42, 0x05, 0x1b, 0xf2, 0x7f, 0x88, 0x56, 0xd1, 0x7c, 0x7d, 0x6b, 0x9f, 0x43, 0xfe, 0x65, 0x19, 0xae, 0x9c, 0x4c, + /* (2^293)P */ 0xf3, 0x7c, 0x20, 0xa9, 0xfc, 0xf2, 0xf2, 0x3b, 0x3c, 0x57, 0x41, 0x94, 0xe5, 0xcc, 0x6a, 0x37, 0x5d, 0x09, 0xf2, 0xab, 0xc2, 0xca, 0x60, 0x38, 0x6b, 0x7a, 0xe1, 0x78, 0x2b, 0xc1, 0x1d, 0xe8, 0xfd, 0xbc, 0x3d, 0x5c, 0xa2, 0xdb, 0x49, 0x20, 0x79, 0xe6, 0x1b, 0x9b, 0x65, 0xd9, 0x6d, 0xec, 0x57, 0x1d, 0xd2, 0xe9, 0x90, 0xeb, 0x43, 0x7b, + /* (2^294)P */ 0x2a, 0x8b, 0x2e, 0x19, 0x18, 0x10, 0xb8, 0x83, 0xe7, 0x7d, 0x2d, 0x9a, 0x3a, 0xe5, 0xd1, 0xe4, 0x7c, 0x38, 0xe5, 0x59, 0x2a, 0x6e, 0xd9, 0x01, 0x29, 0x3d, 0x23, 0xf7, 0x52, 0xba, 0x61, 0x04, 0x9a, 0xde, 0xc4, 0x31, 0x50, 0xeb, 0x1b, 0xaa, 0xde, 0x39, 0x58, 0xd8, 0x1b, 0x1e, 0xfc, 0x57, 0x9a, 0x28, 0x43, 0x9e, 0x97, 0x5e, 0xaa, 0xa3, + /* (2^295)P */ 0x97, 0x0a, 0x74, 0xc4, 0x39, 0x99, 0x6b, 0x40, 0xc7, 0x3e, 0x8c, 0xa7, 0xb1, 0x4e, 0x9a, 0x59, 0x6e, 0x1c, 0xfe, 0xfc, 0x2a, 0x5e, 0x73, 0x2b, 0x8c, 0xa9, 0x71, 0xf5, 0xda, 0x6b, 0x15, 0xab, 0xf7, 0xbe, 0x2a, 0x44, 0x5f, 0xba, 0xae, 0x67, 0x93, 0xc5, 0x86, 0xc1, 0xb8, 0xdf, 0xdc, 0xcb, 0xd7, 0xff, 0xb1, 0x71, 0x7c, 0x6f, 0x88, 0xf8, + /* (2^296)P */ 0x3f, 0x89, 0xb1, 0xbf, 0x24, 0x16, 0xac, 0x56, 0xfe, 0xdf, 0x94, 0x71, 0xbf, 0xd6, 0x57, 0x0c, 0xb4, 0x77, 0x37, 0xaa, 0x2a, 0x70, 0x76, 0x49, 0xaf, 0x0c, 0x97, 0x8e, 0x78, 0x2a, 0x67, 0xc9, 0x3b, 0x3d, 0x5b, 0x01, 0x2f, 0xda, 0xd5, 0xa8, 0xde, 0x02, 0xa9, 0xac, 0x76, 0x00, 0x0b, 0x46, 0xc6, 0x2d, 0xdc, 0x08, 0xf4, 0x10, 0x2c, 0xbe, + /* (2^297)P */ 0xcb, 0x07, 0xf9, 0x91, 0xc6, 0xd5, 0x3e, 0x54, 0x63, 0xae, 0xfc, 0x10, 0xbe, 0x3a, 0x20, 0x73, 0x4e, 0x65, 0x0e, 0x2d, 0x86, 0x77, 0x83, 0x9d, 0xe2, 0x0a, 0xe9, 0xac, 0x22, 0x52, 0x76, 0xd4, 0x6e, 0xfa, 0xe0, 0x09, 0xef, 0x78, 0x82, 0x9f, 0x26, 0xf9, 0x06, 0xb5, 0xe7, 0x05, 0x0e, 0xf2, 0x46, 0x72, 0x93, 0xd3, 0x24, 0xbd, 0x87, 0x60, + /* (2^298)P */ 0x14, 0x55, 0x84, 0x7b, 0x6c, 0x60, 0x80, 0x73, 0x8c, 0xbe, 0x2d, 0xd6, 0x69, 0xd6, 0x17, 0x26, 0x44, 0x9f, 0x88, 0xa2, 0x39, 0x7c, 0x89, 0xbc, 0x6d, 0x9e, 0x46, 0xb6, 0x68, 0x66, 0xea, 0xdc, 0x31, 0xd6, 0x21, 0x51, 0x9f, 0x28, 0x28, 0xaf, 0x9e, 0x47, 0x2c, 0x4c, 0x8f, 0xf3, 0xaf, 0x1f, 0xe4, 0xab, 0xac, 0xe9, 0x0c, 0x91, 0x3a, 0x61, + /* (2^299)P */ 0xb0, 0x37, 0x55, 0x4b, 0xe9, 0xc3, 0xb1, 0xce, 0x42, 0xe6, 0xc5, 0x11, 0x7f, 0x2c, 0x11, 0xfc, 0x4e, 0x71, 0x17, 0x00, 0x74, 0x7f, 0xbf, 0x07, 0x4d, 0xfd, 0x40, 0xb2, 0x87, 0xb0, 0xef, 0x1f, 0x35, 0x2c, 0x2d, 0xd7, 0xe1, 0xe4, 0xad, 0x0e, 0x7f, 0x63, 0x66, 0x62, 0x23, 0x41, 0xf6, 0xc1, 0x14, 0xa6, 0xd7, 0xa9, 0x11, 0x56, 0x9d, 0x1b, + /* (2^300)P */ 0x02, 0x82, 0x42, 0x18, 0x4f, 0x1b, 0xc9, 0x5d, 0x78, 0x5f, 0xee, 0xed, 0x01, 0x49, 0x8f, 0xf2, 0xa0, 0xe2, 0x6e, 0xbb, 0x6b, 0x04, 0x8d, 0xb2, 0x41, 0xae, 0xc8, 0x1b, 0x59, 0x34, 0xb8, 0x2a, 0xdb, 0x1f, 0xd2, 0x52, 0xdf, 0x3f, 0x35, 0x00, 0x8b, 0x61, 0xbc, 0x97, 0xa0, 0xc4, 0x77, 0xd1, 0xe4, 0x2c, 0x59, 0x68, 0xff, 0x30, 0xf2, 0xe2, + /* (2^301)P */ 0x79, 0x08, 0xb1, 0xdb, 0x55, 0xae, 0xd0, 0xed, 0xda, 0xa0, 0xec, 0x6c, 0xae, 0x68, 0xf2, 0x0b, 0x61, 0xb3, 0xf5, 0x21, 0x69, 0x87, 0x0b, 0x03, 0xea, 0x8a, 0x15, 0xd9, 0x7e, 0xca, 0xf7, 0xcd, 0xf3, 0x33, 0xb3, 0x4c, 0x5b, 0x23, 0x4e, 0x6f, 0x90, 0xad, 0x91, 0x4b, 0x4f, 0x46, 0x37, 0xe5, 0xe8, 0xb7, 0xeb, 0xd5, 0xca, 0x34, 0x4e, 0x23, + /* (2^302)P */ 0x09, 0x02, 0xdd, 0xfd, 0x70, 0xac, 0x56, 0x80, 0x36, 0x5e, 0x49, 0xd0, 0x3f, 0xc2, 0xe0, 0xba, 0x46, 0x7f, 0x5c, 0xf7, 0xc5, 0xbd, 0xd5, 0x55, 0x7d, 0x3f, 0xd5, 0x7d, 0x06, 0xdf, 0x27, 0x20, 0x4f, 0xe9, 0x30, 0xec, 0x1b, 0xa0, 0x0c, 0xd4, 0x2c, 0xe1, 0x2b, 0x65, 0x73, 0xea, 0x75, 0x35, 0xe8, 0xe6, 0x56, 0xd6, 0x07, 0x15, 0x99, 0xdf, + /* (2^303)P */ 0x4e, 0x10, 0xb7, 0xd0, 0x63, 0x8c, 0xcf, 0x16, 0x00, 0x7c, 0x58, 0xdf, 0x86, 0xdc, 0x4e, 0xca, 0x9c, 0x40, 0x5a, 0x42, 0xfd, 0xec, 0x98, 0xa4, 0x42, 0x53, 0xae, 0x16, 0x9d, 0xfd, 0x75, 0x5a, 0x12, 0x56, 0x1e, 0xc6, 0x57, 0xcc, 0x79, 0x27, 0x96, 0x00, 0xcf, 0x80, 0x4f, 0x8a, 0x36, 0x5c, 0xbb, 0xe9, 0x12, 0xdb, 0xb6, 0x2b, 0xad, 0x96, + /* (2^304)P */ 0x92, 0x32, 0x1f, 0xfd, 0xc6, 0x02, 0x94, 0x08, 0x1b, 0x60, 0x6a, 0x9f, 0x8b, 0xd6, 0xc8, 0xad, 0xd5, 0x1b, 0x27, 0x4e, 0xa4, 0x4d, 0x4a, 0x00, 0x10, 0x5f, 0x86, 0x11, 0xf5, 0xe3, 0x14, 0x32, 0x43, 0xee, 0xb9, 0xc7, 0xab, 0xf4, 0x6f, 0xe5, 0x66, 0x0c, 0x06, 0x0d, 0x96, 0x79, 0x28, 0xaf, 0x45, 0x2b, 0x56, 0xbe, 0xe4, 0x4a, 0x52, 0xd6, + /* (2^305)P */ 0x15, 0x16, 0x69, 0xef, 0x60, 0xca, 0x82, 0x25, 0x0f, 0xc6, 0x30, 0xa0, 0x0a, 0xd1, 0x83, 0x29, 0xcd, 0xb6, 0x89, 0x6c, 0xf5, 0xb2, 0x08, 0x38, 0xe6, 0xca, 0x6b, 0x19, 0x93, 0xc6, 0x5f, 0x75, 0x8e, 0x60, 0x34, 0x23, 0xc4, 0x13, 0x17, 0x69, 0x55, 0xcc, 0x72, 0x9c, 0x2b, 0x6c, 0x80, 0xf4, 0x4b, 0x8b, 0xb6, 0x97, 0x65, 0x07, 0xb6, 0xfb, + /* (2^306)P */ 0x01, 0x99, 0x74, 0x28, 0xa6, 0x67, 0xa3, 0xe5, 0x25, 0xfb, 0xdf, 0x82, 0x93, 0xe7, 0x35, 0x74, 0xce, 0xe3, 0x15, 0x1c, 0x1d, 0x79, 0x52, 0x84, 0x08, 0x04, 0x2f, 0x5c, 0xb8, 0xcd, 0x7f, 0x89, 0xb0, 0x39, 0x93, 0x63, 0xc9, 0x5d, 0x06, 0x01, 0x59, 0xf7, 0x7e, 0xf1, 0x4c, 0x3d, 0x12, 0x8d, 0x69, 0x1d, 0xb7, 0x21, 0x5e, 0x88, 0x82, 0xa2, + /* (2^307)P */ 0x8e, 0x69, 0xaf, 0x9a, 0x41, 0x0d, 0x9d, 0xcf, 0x8e, 0x8d, 0x5c, 0x51, 0x6e, 0xde, 0x0e, 0x48, 0x23, 0x89, 0xe5, 0x37, 0x80, 0xd6, 0x9d, 0x72, 0x32, 0x26, 0x38, 0x2d, 0x63, 0xa0, 0xfa, 0xd3, 0x40, 0xc0, 0x8c, 0x68, 0x6f, 0x2b, 0x1e, 0x9a, 0x39, 0x51, 0x78, 0x74, 0x9a, 0x7b, 0x4a, 0x8f, 0x0c, 0xa0, 0x88, 0x60, 0xa5, 0x21, 0xcd, 0xc7, + /* (2^308)P */ 0x3a, 0x7f, 0x73, 0x14, 0xbf, 0x89, 0x6a, 0x4c, 0x09, 0x5d, 0xf2, 0x93, 0x20, 0x2d, 0xc4, 0x29, 0x86, 0x06, 0x95, 0xab, 0x22, 0x76, 0x4c, 0x54, 0xe1, 0x7e, 0x80, 0x6d, 0xab, 0x29, 0x61, 0x87, 0x77, 0xf6, 0xc0, 0x3e, 0xda, 0xab, 0x65, 0x7e, 0x39, 0x12, 0xa1, 0x6b, 0x42, 0xf7, 0xc5, 0x97, 0x77, 0xec, 0x6f, 0x22, 0xbe, 0x44, 0xc7, 0x03, + /* (2^309)P */ 0xa5, 0x23, 0x90, 0x41, 0xa3, 0xc5, 0x3e, 0xe0, 0xa5, 0x32, 0x49, 0x1f, 0x39, 0x78, 0xb1, 0xd8, 0x24, 0xea, 0xd4, 0x87, 0x53, 0x42, 0x51, 0xf4, 0xd9, 0x46, 0x25, 0x2f, 0x62, 0xa9, 0x90, 0x9a, 0x4a, 0x25, 0x8a, 0xd2, 0x10, 0xe7, 0x3c, 0xbc, 0x58, 0x8d, 0x16, 0x14, 0x96, 0xa4, 0x6f, 0xf8, 0x12, 0x69, 0x91, 0x73, 0xe2, 0xfa, 0xf4, 0x57, + /* (2^310)P */ 0x51, 0x45, 0x3f, 0x96, 0xdc, 0x97, 0x38, 0xa6, 0x01, 0x63, 0x09, 0xea, 0xc2, 0x13, 0x30, 0xb0, 0x00, 0xb8, 0x0a, 0xce, 0xd1, 0x8f, 0x3e, 0x69, 0x62, 0x46, 0x33, 0x9c, 0xbf, 0x4b, 0xcb, 0x0c, 0x90, 0x1c, 0x45, 0xcf, 0x37, 0x5b, 0xf7, 0x4b, 0x5e, 0x95, 0xc3, 0x28, 0x9f, 0x08, 0x83, 0x53, 0x74, 0xab, 0x0c, 0xb4, 0xc0, 0xa1, 0xbc, 0x89, + /* (2^311)P */ 0x06, 0xb1, 0x51, 0x15, 0x65, 0x60, 0x21, 0x17, 0x7a, 0x20, 0x65, 0xee, 0x12, 0x35, 0x4d, 0x46, 0xf4, 0xf8, 0xd0, 0xb1, 0xca, 0x09, 0x30, 0x08, 0x89, 0x23, 0x3b, 0xe7, 0xab, 0x8b, 0x77, 0xa6, 0xad, 0x25, 0xdd, 0xea, 0x3c, 0x7d, 0xa5, 0x24, 0xb3, 0xe8, 0xfa, 0xfb, 0xc9, 0xf2, 0x71, 0xe9, 0xfa, 0xf2, 0xdc, 0x54, 0xdd, 0x55, 0x2e, 0x2f, + /* (2^312)P */ 0x7f, 0x96, 0x96, 0xfb, 0x52, 0x86, 0xcf, 0xea, 0x62, 0x18, 0xf1, 0x53, 0x1f, 0x61, 0x2a, 0x9f, 0x8c, 0x51, 0xca, 0x2c, 0xde, 0x6d, 0xce, 0xab, 0x58, 0x32, 0x0b, 0x33, 0x9b, 0x99, 0xb4, 0x5c, 0x88, 0x2a, 0x76, 0xcc, 0x3e, 0x54, 0x1e, 0x9d, 0xa2, 0x89, 0xe4, 0x19, 0xba, 0x80, 0xc8, 0x39, 0x32, 0x7f, 0x0f, 0xc7, 0x84, 0xbb, 0x43, 0x56, + /* (2^313)P */ 0x9b, 0x07, 0xb4, 0x42, 0xa9, 0xa0, 0x78, 0x4f, 0x28, 0x70, 0x2b, 0x7e, 0x61, 0xe0, 0xdd, 0x02, 0x98, 0xfc, 0xed, 0x31, 0x80, 0xf1, 0x15, 0x52, 0x89, 0x23, 0xcd, 0x5d, 0x2b, 0xc5, 0x19, 0x32, 0xfb, 0x70, 0x50, 0x7a, 0x97, 0x6b, 0x42, 0xdb, 0xca, 0xdb, 0xc4, 0x59, 0x99, 0xe0, 0x12, 0x1f, 0x17, 0xba, 0x8b, 0xf0, 0xc4, 0x38, 0x5d, 0x27, + /* (2^314)P */ 0x29, 0x1d, 0xdc, 0x2b, 0xf6, 0x5b, 0x04, 0x61, 0x36, 0x76, 0xa0, 0x56, 0x36, 0x6e, 0xd7, 0x24, 0x4d, 0xe7, 0xef, 0x44, 0xd2, 0xd5, 0x07, 0xcd, 0xc4, 0x9d, 0x80, 0x48, 0xc3, 0x38, 0xcf, 0xd8, 0xa3, 0xdd, 0xb2, 0x5e, 0xb5, 0x70, 0x15, 0xbb, 0x36, 0x85, 0x8a, 0xd7, 0xfb, 0x56, 0x94, 0x73, 0x9c, 0x81, 0xbe, 0xb1, 0x44, 0x28, 0xf1, 0x37, + /* (2^315)P */ 0xbf, 0xcf, 0x5c, 0xd2, 0xe2, 0xea, 0xc2, 0xcd, 0x70, 0x7a, 0x9d, 0xcb, 0x81, 0xc1, 0xe9, 0xf1, 0x56, 0x71, 0x52, 0xf7, 0x1b, 0x87, 0xc6, 0xd8, 0xcc, 0xb2, 0x69, 0xf3, 0xb0, 0xbd, 0xba, 0x83, 0x12, 0x26, 0xc4, 0xce, 0x72, 0xde, 0x3b, 0x21, 0x28, 0x9e, 0x5a, 0x94, 0xf5, 0x04, 0xa3, 0xc8, 0x0f, 0x5e, 0xbc, 0x71, 0xf9, 0x0d, 0xce, 0xf5, + /* (2^316)P */ 0x93, 0x97, 0x00, 0x85, 0xf4, 0xb4, 0x40, 0xec, 0xd9, 0x2b, 0x6c, 0xd6, 0x63, 0x9e, 0x93, 0x0a, 0x5a, 0xf4, 0xa7, 0x9a, 0xe3, 0x3c, 0xf0, 0x55, 0xd1, 0x96, 0x6c, 0xf5, 0x2a, 0xce, 0xd7, 0x95, 0x72, 0xbf, 0xc5, 0x0c, 0xce, 0x79, 0xa2, 0x0a, 0x78, 0xe0, 0x72, 0xd0, 0x66, 0x28, 0x05, 0x75, 0xd3, 0x23, 0x09, 0x91, 0xed, 0x7e, 0xc4, 0xbc, + /* (2^317)P */ 0x77, 0xc2, 0x9a, 0xf7, 0xa6, 0xe6, 0x18, 0xb4, 0xe7, 0xf6, 0xda, 0xec, 0x44, 0x6d, 0xfb, 0x08, 0xee, 0x65, 0xa8, 0x92, 0x85, 0x1f, 0xba, 0x38, 0x93, 0x20, 0x5c, 0x4d, 0xd2, 0x18, 0x0f, 0x24, 0xbe, 0x1a, 0x96, 0x44, 0x7d, 0xeb, 0xb3, 0xda, 0x95, 0xf4, 0xaf, 0x6c, 0x06, 0x0f, 0x47, 0x37, 0xc8, 0x77, 0x63, 0xe1, 0x29, 0xef, 0xff, 0xa5, + /* (2^318)P */ 0x16, 0x12, 0xd9, 0x47, 0x90, 0x22, 0x9b, 0x05, 0xf2, 0xa5, 0x9a, 0xae, 0x83, 0x98, 0xb5, 0xac, 0xab, 0x29, 0xaa, 0xdc, 0x5f, 0xde, 0xcd, 0xf7, 0x42, 0xad, 0x3b, 0x96, 0xd6, 0x3e, 0x6e, 0x52, 0x47, 0xb1, 0xab, 0x51, 0xde, 0x49, 0x7c, 0x87, 0x8d, 0x86, 0xe2, 0x70, 0x13, 0x21, 0x51, 0x1c, 0x0c, 0x25, 0xc1, 0xb0, 0xe6, 0x19, 0xcf, 0x12, + /* (2^319)P */ 0xf0, 0xbc, 0x97, 0x8f, 0x4b, 0x2f, 0xd1, 0x1f, 0x8c, 0x57, 0xed, 0x3c, 0xf4, 0x26, 0x19, 0xbb, 0x60, 0xca, 0x24, 0xc5, 0xd9, 0x97, 0xe2, 0x5f, 0x76, 0x49, 0x39, 0x7e, 0x2d, 0x12, 0x21, 0x98, 0xda, 0xe6, 0xdb, 0xd2, 0xd8, 0x9f, 0x18, 0xd8, 0x83, 0x6c, 0xba, 0x89, 0x8d, 0x29, 0xfa, 0x46, 0x33, 0x8c, 0x28, 0xdf, 0x6a, 0xb3, 0x69, 0x28, + /* (2^320)P */ 0x86, 0x17, 0xbc, 0xd6, 0x7c, 0xba, 0x1e, 0x83, 0xbb, 0x84, 0xb5, 0x8c, 0xad, 0xdf, 0xa1, 0x24, 0x81, 0x70, 0x40, 0x0f, 0xad, 0xad, 0x3b, 0x23, 0xd0, 0x93, 0xa0, 0x49, 0x5c, 0x4b, 0x51, 0xbe, 0x20, 0x49, 0x4e, 0xda, 0x2d, 0xd3, 0xad, 0x1b, 0x74, 0x08, 0x41, 0xf0, 0xef, 0x19, 0xe9, 0x45, 0x5d, 0x02, 0xae, 0x26, 0x25, 0xd9, 0xd1, 0xc2, + /* (2^321)P */ 0x48, 0x81, 0x3e, 0xb2, 0x83, 0xf8, 0x4d, 0xb3, 0xd0, 0x4c, 0x75, 0xb3, 0xa0, 0x52, 0x26, 0xf2, 0xaf, 0x5d, 0x36, 0x70, 0x72, 0xd6, 0xb7, 0x88, 0x08, 0x69, 0xbd, 0x15, 0x25, 0xb1, 0x45, 0x1b, 0xb7, 0x0b, 0x5f, 0x71, 0x5d, 0x83, 0x49, 0xb9, 0x84, 0x3b, 0x7c, 0xc1, 0x50, 0x93, 0x05, 0x53, 0xe0, 0x61, 0xea, 0xc1, 0xef, 0xdb, 0x82, 0x97, + /* (2^322)P */ 0x00, 0xd5, 0xc3, 0x3a, 0x4d, 0x8a, 0x23, 0x7a, 0xef, 0xff, 0x37, 0xef, 0xf3, 0xbc, 0xa9, 0xb6, 0xae, 0xd7, 0x3a, 0x7b, 0xfd, 0x3e, 0x8e, 0x9b, 0xab, 0x44, 0x54, 0x60, 0x28, 0x6c, 0xbf, 0x15, 0x24, 0x4a, 0x56, 0x60, 0x7f, 0xa9, 0x7a, 0x28, 0x59, 0x2c, 0x8a, 0xd1, 0x7d, 0x6b, 0x00, 0xfd, 0xa5, 0xad, 0xbc, 0x19, 0x3f, 0xcb, 0x73, 0xe0, + /* (2^323)P */ 0xcf, 0x9e, 0x66, 0x06, 0x4d, 0x2b, 0xf5, 0x9c, 0xc2, 0x9d, 0x9e, 0xed, 0x5a, 0x5c, 0x2d, 0x00, 0xbf, 0x29, 0x90, 0x88, 0xe4, 0x5d, 0xfd, 0xe2, 0xf0, 0x38, 0xec, 0x4d, 0x26, 0xea, 0x54, 0xf0, 0x3c, 0x84, 0x10, 0x6a, 0xf9, 0x66, 0x9c, 0xe7, 0x21, 0xfd, 0x0f, 0xc7, 0x13, 0x50, 0x81, 0xb6, 0x50, 0xf9, 0x04, 0x7f, 0xa4, 0x37, 0x85, 0x14, + /* (2^324)P */ 0xdb, 0x87, 0x49, 0xc7, 0xa8, 0x39, 0x0c, 0x32, 0x98, 0x0c, 0xb9, 0x1a, 0x1b, 0x4d, 0xe0, 0x8a, 0x9a, 0x8e, 0x8f, 0xab, 0x5a, 0x17, 0x3d, 0x04, 0x21, 0xce, 0x3e, 0x2c, 0xf9, 0xa3, 0x97, 0xe4, 0x77, 0x95, 0x0e, 0xb6, 0xa5, 0x15, 0xad, 0x3a, 0x1e, 0x46, 0x53, 0x17, 0x09, 0x83, 0x71, 0x4e, 0x86, 0x38, 0xd5, 0x23, 0x44, 0x16, 0x8d, 0xc8, + /* (2^325)P */ 0x05, 0x5e, 0x99, 0x08, 0xbb, 0xc3, 0xc0, 0xb7, 0x6c, 0x12, 0xf2, 0xf3, 0xf4, 0x7c, 0x6a, 0x4d, 0x9e, 0xeb, 0x3d, 0xb9, 0x63, 0x94, 0xce, 0x81, 0xd8, 0x11, 0xcb, 0x55, 0x69, 0x4a, 0x20, 0x0b, 0x4c, 0x2e, 0x14, 0xb8, 0xd4, 0x6a, 0x7c, 0xf0, 0xed, 0xfc, 0x8f, 0xef, 0xa0, 0xeb, 0x6c, 0x01, 0xe2, 0xdc, 0x10, 0x22, 0xa2, 0x01, 0x85, 0x64, + /* (2^326)P */ 0x58, 0xe1, 0x9c, 0x27, 0x55, 0xc6, 0x25, 0xa6, 0x7d, 0x67, 0x88, 0x65, 0x99, 0x6c, 0xcb, 0xdb, 0x27, 0x4f, 0x44, 0x29, 0xf5, 0x4a, 0x23, 0x10, 0xbc, 0x03, 0x3f, 0x36, 0x1e, 0xef, 0xb0, 0xba, 0x75, 0xe8, 0x74, 0x5f, 0x69, 0x3e, 0x26, 0x40, 0xb4, 0x2f, 0xdc, 0x43, 0xbf, 0xa1, 0x8b, 0xbd, 0xca, 0x6e, 0xc1, 0x6e, 0x21, 0x79, 0xa0, 0xd0, + /* (2^327)P */ 0x78, 0x93, 0x4a, 0x2d, 0x22, 0x6e, 0x6e, 0x7d, 0x74, 0xd2, 0x66, 0x58, 0xce, 0x7b, 0x1d, 0x97, 0xb1, 0xf2, 0xda, 0x1c, 0x79, 0xfb, 0xba, 0xd1, 0xc0, 0xc5, 0x6e, 0xc9, 0x11, 0x89, 0xd2, 0x41, 0x8d, 0x70, 0xb9, 0xcc, 0xea, 0x6a, 0xb3, 0x45, 0xb6, 0x05, 0x2e, 0xf2, 0x17, 0xf1, 0x27, 0xb8, 0xed, 0x06, 0x1f, 0xdb, 0x9d, 0x1f, 0x69, 0x28, + /* (2^328)P */ 0x93, 0x12, 0xa8, 0x11, 0xe1, 0x92, 0x30, 0x8d, 0xac, 0xe1, 0x1c, 0x60, 0x7c, 0xed, 0x2d, 0x2e, 0xd3, 0x03, 0x5c, 0x9c, 0xc5, 0xbd, 0x64, 0x4a, 0x8c, 0xba, 0x76, 0xfe, 0xc6, 0xc1, 0xea, 0xc2, 0x4f, 0xbe, 0x70, 0x3d, 0x64, 0xcf, 0x8e, 0x18, 0xcb, 0xcd, 0x57, 0xa7, 0xf7, 0x36, 0xa9, 0x6b, 0x3e, 0xb8, 0x69, 0xee, 0x47, 0xa2, 0x7e, 0xb2, + /* (2^329)P */ 0x96, 0xaf, 0x3a, 0xf5, 0xed, 0xcd, 0xaf, 0xf7, 0x82, 0xaf, 0x59, 0x62, 0x0b, 0x36, 0x85, 0xf9, 0xaf, 0xd6, 0x38, 0xff, 0x87, 0x2e, 0x1d, 0x6c, 0x8b, 0xaf, 0x3b, 0xdf, 0x28, 0xa2, 0xd6, 0x4d, 0x80, 0x92, 0xc3, 0x0f, 0x34, 0xa8, 0xae, 0x69, 0x5d, 0x7b, 0x9d, 0xbc, 0xf5, 0xfd, 0x1d, 0xb1, 0x96, 0x55, 0x86, 0xe1, 0x5c, 0xb6, 0xac, 0xb9, + /* (2^330)P */ 0x50, 0x9e, 0x37, 0x28, 0x7d, 0xa8, 0x33, 0x63, 0xda, 0x3f, 0x20, 0x98, 0x0e, 0x09, 0xa8, 0x77, 0x3b, 0x7a, 0xfc, 0x16, 0x85, 0x44, 0x64, 0x77, 0x65, 0x68, 0x92, 0x41, 0xc6, 0x1f, 0xdf, 0x27, 0xf9, 0xec, 0xa0, 0x61, 0x22, 0xea, 0x19, 0xe7, 0x75, 0x8b, 0x4e, 0xe5, 0x0f, 0xb7, 0xf7, 0xd2, 0x53, 0xf4, 0xdd, 0x4a, 0xaa, 0x78, 0x40, 0xb7, + /* (2^331)P */ 0xd4, 0x89, 0xe3, 0x79, 0xba, 0xb6, 0xc3, 0xda, 0xe6, 0x78, 0x65, 0x7d, 0x6e, 0x22, 0x62, 0xb1, 0x3d, 0xea, 0x90, 0x84, 0x30, 0x5e, 0xd4, 0x39, 0x84, 0x78, 0xd9, 0x75, 0xd6, 0xce, 0x2a, 0x11, 0x29, 0x69, 0xa4, 0x5e, 0xaa, 0x2a, 0x98, 0x5a, 0xe5, 0x91, 0x8f, 0xb2, 0xfb, 0xda, 0x97, 0xe8, 0x83, 0x6f, 0x04, 0xb9, 0x5d, 0xaf, 0xe1, 0x9b, + /* (2^332)P */ 0x8b, 0xe4, 0xe1, 0x48, 0x9c, 0xc4, 0x83, 0x89, 0xdf, 0x65, 0xd3, 0x35, 0x55, 0x13, 0xf4, 0x1f, 0x36, 0x92, 0x33, 0x38, 0xcb, 0xed, 0x15, 0xe6, 0x60, 0x2d, 0x25, 0xf5, 0x36, 0x60, 0x3a, 0x37, 0x9b, 0x71, 0x9d, 0x42, 0xb0, 0x14, 0xc8, 0xba, 0x62, 0xa3, 0x49, 0xb0, 0x88, 0xc1, 0x72, 0x73, 0xdd, 0x62, 0x40, 0xa9, 0x62, 0x88, 0x99, 0xca, + /* (2^333)P */ 0x47, 0x7b, 0xea, 0xda, 0x46, 0x2f, 0x45, 0xc6, 0xe3, 0xb4, 0x4d, 0x8d, 0xac, 0x0b, 0x54, 0x22, 0x06, 0x31, 0x16, 0x66, 0x3e, 0xe4, 0x38, 0x12, 0xcd, 0xf3, 0xe7, 0x99, 0x37, 0xd9, 0x62, 0x24, 0x4b, 0x05, 0xf2, 0x58, 0xe6, 0x29, 0x4b, 0x0d, 0xf6, 0xc1, 0xba, 0xa0, 0x1e, 0x0f, 0xcb, 0x1f, 0xc6, 0x2b, 0x19, 0xfc, 0x82, 0x01, 0xd0, 0x86, + /* (2^334)P */ 0xa2, 0xae, 0x77, 0x20, 0xfb, 0xa8, 0x18, 0xb4, 0x61, 0xef, 0xe8, 0x52, 0x79, 0xbb, 0x86, 0x90, 0x5d, 0x2e, 0x76, 0xed, 0x66, 0x60, 0x5d, 0x00, 0xb5, 0xa4, 0x00, 0x40, 0x89, 0xec, 0xd1, 0xd2, 0x0d, 0x26, 0xb9, 0x30, 0xb2, 0xd2, 0xb8, 0xe8, 0x0e, 0x56, 0xf9, 0x67, 0x94, 0x2e, 0x62, 0xe1, 0x79, 0x48, 0x2b, 0xa9, 0xfa, 0xea, 0xdb, 0x28, + /* (2^335)P */ 0x35, 0xf1, 0xb0, 0x43, 0xbd, 0x27, 0xef, 0x18, 0x44, 0xa2, 0x04, 0xb4, 0x69, 0xa1, 0x97, 0x1f, 0x8c, 0x04, 0x82, 0x9b, 0x00, 0x6d, 0xf8, 0xbf, 0x7d, 0xc1, 0x5b, 0xab, 0xe8, 0xb2, 0x34, 0xbd, 0xaf, 0x7f, 0xb2, 0x0d, 0xf3, 0xed, 0xfc, 0x5b, 0x50, 0xee, 0xe7, 0x4a, 0x20, 0xd9, 0xf5, 0xc6, 0x9a, 0x97, 0x6d, 0x07, 0x2f, 0xb9, 0x31, 0x02, + /* (2^336)P */ 0xf9, 0x54, 0x4a, 0xc5, 0x61, 0x7e, 0x1d, 0xa6, 0x0e, 0x1a, 0xa8, 0xd3, 0x8c, 0x36, 0x7d, 0xf1, 0x06, 0xb1, 0xac, 0x93, 0xcd, 0xe9, 0x8f, 0x61, 0x6c, 0x5d, 0x03, 0x23, 0xdf, 0x85, 0x53, 0x39, 0x63, 0x5e, 0xeb, 0xf3, 0xd3, 0xd3, 0x75, 0x97, 0x9b, 0x62, 0x9b, 0x01, 0xb3, 0x19, 0xd8, 0x2b, 0x36, 0xf2, 0x2c, 0x2c, 0x6f, 0x36, 0xc6, 0x3c, + /* (2^337)P */ 0x05, 0x74, 0x43, 0x10, 0xb6, 0xb0, 0xf8, 0xbf, 0x02, 0x46, 0x9a, 0xee, 0xc1, 0xaf, 0xc1, 0xe5, 0x5a, 0x2e, 0xbb, 0xe1, 0xdc, 0xc6, 0xce, 0x51, 0x29, 0x50, 0xbf, 0x1b, 0xde, 0xff, 0xba, 0x4d, 0x8d, 0x8b, 0x7e, 0xe7, 0xbd, 0x5b, 0x8f, 0xbe, 0xe3, 0x75, 0x71, 0xff, 0x37, 0x05, 0x5a, 0x10, 0xeb, 0x54, 0x7e, 0x44, 0x72, 0x2c, 0xd4, 0xfc, + /* (2^338)P */ 0x03, 0x12, 0x1c, 0xb2, 0x08, 0x90, 0xa1, 0x2d, 0x50, 0xa0, 0xad, 0x7f, 0x8d, 0xa6, 0x97, 0xc1, 0xbd, 0xdc, 0xc3, 0xa7, 0xad, 0x31, 0xdf, 0xb8, 0x03, 0x84, 0xc3, 0xb9, 0x29, 0x3d, 0x92, 0x2e, 0xc3, 0x90, 0x07, 0xe8, 0xa7, 0xc7, 0xbc, 0x61, 0xe9, 0x3e, 0xa0, 0x35, 0xda, 0x1d, 0xab, 0x48, 0xfe, 0x50, 0xc9, 0x25, 0x59, 0x23, 0x69, 0x3f, + /* (2^339)P */ 0x8e, 0x91, 0xab, 0x6b, 0x91, 0x4f, 0x89, 0x76, 0x67, 0xad, 0xb2, 0x65, 0x9d, 0xad, 0x02, 0x36, 0xdc, 0xac, 0x96, 0x93, 0x97, 0x21, 0x14, 0xd0, 0xe8, 0x11, 0x60, 0x1e, 0xeb, 0x96, 0x06, 0xf2, 0x53, 0xf2, 0x6d, 0xb7, 0x93, 0x6f, 0x26, 0x91, 0x23, 0xe3, 0x34, 0x04, 0x92, 0x91, 0x37, 0x08, 0x50, 0xd6, 0x28, 0x09, 0x27, 0xa1, 0x0c, 0x00, + /* (2^340)P */ 0x1f, 0xbb, 0x21, 0x26, 0x33, 0xcb, 0xa4, 0xd1, 0xee, 0x85, 0xf9, 0xd9, 0x3c, 0x90, 0xc3, 0xd1, 0x26, 0xa2, 0x25, 0x93, 0x43, 0x61, 0xed, 0x91, 0x6e, 0x54, 0x03, 0x2e, 0x42, 0x9d, 0xf7, 0xa6, 0x02, 0x0f, 0x2f, 0x9c, 0x7a, 0x8d, 0x12, 0xc2, 0x18, 0xfc, 0x41, 0xff, 0x85, 0x26, 0x1a, 0x44, 0x55, 0x0b, 0x89, 0xab, 0x6f, 0x62, 0x33, 0x8c, + /* (2^341)P */ 0xe0, 0x3c, 0x5d, 0x70, 0x64, 0x87, 0x81, 0x35, 0xf2, 0x37, 0xa6, 0x24, 0x3e, 0xe0, 0x62, 0xd5, 0x71, 0xe7, 0x93, 0xfb, 0xac, 0xc3, 0xe7, 0xc7, 0x04, 0xe2, 0x70, 0xd3, 0x29, 0x5b, 0x21, 0xbf, 0xf4, 0x26, 0x5d, 0xf3, 0x95, 0xb4, 0x2a, 0x6a, 0x07, 0x55, 0xa6, 0x4b, 0x3b, 0x15, 0xf2, 0x25, 0x8a, 0x95, 0x3f, 0x63, 0x2f, 0x7a, 0x23, 0x96, + /* (2^342)P */ 0x0d, 0x3d, 0xd9, 0x13, 0xa7, 0xb3, 0x5e, 0x67, 0xf7, 0x02, 0x23, 0xee, 0x84, 0xff, 0x99, 0xda, 0xb9, 0x53, 0xf8, 0xf0, 0x0e, 0x39, 0x2f, 0x3c, 0x64, 0x34, 0xe3, 0x09, 0xfd, 0x2b, 0x33, 0xc7, 0xfe, 0x62, 0x2b, 0x84, 0xdf, 0x2b, 0xd2, 0x7c, 0x26, 0x01, 0x70, 0x66, 0x5b, 0x85, 0xc2, 0xbe, 0x88, 0x37, 0xf1, 0x30, 0xac, 0xb8, 0x76, 0xa3, + /* (2^343)P */ 0x6e, 0x01, 0xf0, 0x55, 0x35, 0xe4, 0xbd, 0x43, 0x62, 0x9d, 0xd6, 0x11, 0xef, 0x6f, 0xb8, 0x8c, 0xaa, 0x98, 0x87, 0xc6, 0x6d, 0xc4, 0xcc, 0x74, 0x92, 0x53, 0x4a, 0xdf, 0xe4, 0x08, 0x89, 0x17, 0xd0, 0x0f, 0xf4, 0x00, 0x60, 0x78, 0x08, 0x44, 0xb5, 0xda, 0x18, 0xed, 0x98, 0xc8, 0x61, 0x3d, 0x39, 0xdb, 0xcf, 0x1d, 0x49, 0x40, 0x65, 0x75, + /* (2^344)P */ 0x8e, 0x10, 0xae, 0x5f, 0x06, 0xd2, 0x95, 0xfd, 0x20, 0x16, 0x49, 0x5b, 0x57, 0xbe, 0x22, 0x8b, 0x43, 0xfb, 0xe6, 0xcc, 0x26, 0xa5, 0x5d, 0xd3, 0x68, 0xc5, 0xf9, 0x5a, 0x86, 0x24, 0x87, 0x27, 0x05, 0xfd, 0xe2, 0xff, 0xb3, 0xa3, 0x7b, 0x37, 0x59, 0xc5, 0x4e, 0x14, 0x94, 0xf9, 0x3b, 0xcb, 0x7c, 0xed, 0xca, 0x1d, 0xb2, 0xac, 0x05, 0x4a, + /* (2^345)P */ 0xf4, 0xd1, 0x81, 0xeb, 0x89, 0xbf, 0xfe, 0x1e, 0x41, 0x92, 0x29, 0xee, 0xe1, 0x43, 0xf5, 0x86, 0x1d, 0x2f, 0xbb, 0x1e, 0x84, 0x5d, 0x7b, 0x8d, 0xd5, 0xda, 0xee, 0x1e, 0x8a, 0xd0, 0x27, 0xf2, 0x60, 0x51, 0x59, 0x82, 0xf4, 0x84, 0x2b, 0x5b, 0x14, 0x2d, 0x81, 0x82, 0x3e, 0x2b, 0xb4, 0x6d, 0x51, 0x4f, 0xc5, 0xcb, 0xbf, 0x74, 0xe3, 0xb4, + /* (2^346)P */ 0x19, 0x2f, 0x22, 0xb3, 0x04, 0x5f, 0x81, 0xca, 0x05, 0x60, 0xb9, 0xaa, 0xee, 0x0e, 0x2f, 0x48, 0x38, 0xf9, 0x91, 0xb4, 0x66, 0xe4, 0x57, 0x28, 0x54, 0x10, 0xe9, 0x61, 0x9d, 0xd4, 0x90, 0x75, 0xb1, 0x39, 0x23, 0xb6, 0xfc, 0x82, 0xe0, 0xfa, 0xbb, 0x5c, 0x6e, 0xc3, 0x44, 0x13, 0x00, 0x83, 0x55, 0x9e, 0x8e, 0x10, 0x61, 0x81, 0x91, 0x04, + /* (2^347)P */ 0x5f, 0x2a, 0xd7, 0x81, 0xd9, 0x9c, 0xbb, 0x79, 0xbc, 0x62, 0x56, 0x98, 0x03, 0x5a, 0x18, 0x85, 0x2a, 0x9c, 0xd0, 0xfb, 0xd2, 0xb1, 0xaf, 0xef, 0x0d, 0x24, 0xc5, 0xfa, 0x39, 0xbb, 0x6b, 0xed, 0xa4, 0xdf, 0xe4, 0x87, 0xcd, 0x41, 0xd3, 0x72, 0x32, 0xc6, 0x28, 0x21, 0xb1, 0xba, 0x8b, 0xa3, 0x91, 0x79, 0x76, 0x22, 0x25, 0x10, 0x61, 0xd1, + /* (2^348)P */ 0x73, 0xb5, 0x32, 0x97, 0xdd, 0xeb, 0xdd, 0x22, 0x22, 0xf1, 0x33, 0x3c, 0x77, 0x56, 0x7d, 0x6b, 0x48, 0x2b, 0x05, 0x81, 0x03, 0x03, 0x91, 0x9a, 0xe3, 0x5e, 0xd4, 0xee, 0x3f, 0xf8, 0xbb, 0x50, 0x21, 0x32, 0x4c, 0x4a, 0x58, 0x49, 0xde, 0x0c, 0xde, 0x30, 0x82, 0x3d, 0x92, 0xf0, 0x6c, 0xcc, 0x32, 0x3e, 0xd2, 0x78, 0x8a, 0x6e, 0x2c, 0xd0, + /* (2^349)P */ 0xf0, 0xf7, 0xa1, 0x0b, 0xc1, 0x74, 0x85, 0xa8, 0xe9, 0xdd, 0x48, 0xa1, 0xc0, 0x16, 0xd8, 0x2b, 0x61, 0x08, 0xc2, 0x2b, 0x30, 0x26, 0x79, 0xce, 0x9e, 0xfd, 0x39, 0xd7, 0x81, 0xa4, 0x63, 0x8c, 0xd5, 0x74, 0xa0, 0x88, 0xfa, 0x03, 0x30, 0xe9, 0x7f, 0x2b, 0xc6, 0x02, 0xc9, 0x5e, 0xe4, 0xd5, 0x4d, 0x92, 0xd0, 0xf6, 0xf2, 0x5b, 0x79, 0x08, + /* (2^350)P */ 0x34, 0x89, 0x81, 0x43, 0xd1, 0x94, 0x2c, 0x10, 0x54, 0x9b, 0xa0, 0xe5, 0x44, 0xe8, 0xc2, 0x2f, 0x3e, 0x0e, 0x74, 0xae, 0xba, 0xe2, 0xac, 0x85, 0x6b, 0xd3, 0x5c, 0x97, 0xf7, 0x90, 0xf1, 0x12, 0xc0, 0x03, 0xc8, 0x1f, 0x37, 0x72, 0x8c, 0x9b, 0x9c, 0x17, 0x96, 0x9d, 0xc7, 0xbf, 0xa3, 0x3f, 0x44, 0x3d, 0x87, 0x81, 0xbd, 0x81, 0xa6, 0x5f, + /* (2^351)P */ 0xe4, 0xff, 0x78, 0x62, 0x82, 0x5b, 0x76, 0x58, 0xf5, 0x5b, 0xa6, 0xc4, 0x53, 0x11, 0x3b, 0x7b, 0xaa, 0x67, 0xf8, 0xea, 0x3b, 0x5d, 0x9a, 0x2e, 0x04, 0xeb, 0x4a, 0x24, 0xfb, 0x56, 0xf0, 0xa8, 0xd4, 0x14, 0xed, 0x0f, 0xfd, 0xc5, 0x26, 0x17, 0x2a, 0xf0, 0xb9, 0x13, 0x8c, 0xbd, 0x65, 0x14, 0x24, 0x95, 0x27, 0x12, 0x63, 0x2a, 0x09, 0x18, + /* (2^352)P */ 0xe1, 0x5c, 0xe7, 0xe0, 0x00, 0x6a, 0x96, 0xf2, 0x49, 0x6a, 0x39, 0xa5, 0xe0, 0x17, 0x79, 0x4a, 0x63, 0x07, 0x62, 0x09, 0x61, 0x1b, 0x6e, 0xa9, 0xb5, 0x62, 0xb7, 0xde, 0xdf, 0x80, 0x4c, 0x5a, 0x99, 0x73, 0x59, 0x9d, 0xfb, 0xb1, 0x5e, 0xbe, 0xb8, 0xb7, 0x63, 0x93, 0xe8, 0xad, 0x5e, 0x1f, 0xae, 0x59, 0x1c, 0xcd, 0xb4, 0xc2, 0xb3, 0x8a, + /* (2^353)P */ 0x78, 0x53, 0xa1, 0x4c, 0x70, 0x9c, 0x63, 0x7e, 0xb3, 0x12, 0x40, 0x5f, 0xbb, 0x23, 0xa7, 0xf7, 0x77, 0x96, 0x5b, 0x4d, 0x91, 0x10, 0x52, 0x85, 0x9e, 0xa5, 0x38, 0x0b, 0xfd, 0x25, 0x01, 0x4b, 0xfa, 0x4d, 0xd3, 0x3f, 0x78, 0x74, 0x42, 0xff, 0x62, 0x2d, 0x27, 0xdc, 0x9d, 0xd1, 0x29, 0x76, 0x2e, 0x78, 0xb3, 0x35, 0xfa, 0x15, 0xd5, 0x38, + /* (2^354)P */ 0x8b, 0xc7, 0x43, 0xce, 0xf0, 0x5e, 0xf1, 0x0d, 0x02, 0x38, 0xe8, 0x82, 0xc9, 0x25, 0xad, 0x2d, 0x27, 0xa4, 0x54, 0x18, 0xb2, 0x30, 0x73, 0xa4, 0x41, 0x08, 0xe4, 0x86, 0xe6, 0x8c, 0xe9, 0x2a, 0x34, 0xb3, 0xd6, 0x61, 0x8f, 0x66, 0x26, 0x08, 0xb6, 0x06, 0x33, 0xaa, 0x12, 0xac, 0x72, 0xec, 0x2e, 0x52, 0xa3, 0x25, 0x3e, 0xd7, 0x62, 0xe8, + /* (2^355)P */ 0xc4, 0xbb, 0x89, 0xc8, 0x40, 0xcc, 0x84, 0xec, 0x4a, 0xd9, 0xc4, 0x55, 0x78, 0x00, 0xcf, 0xd8, 0xe9, 0x24, 0x59, 0xdc, 0x5e, 0xf0, 0x66, 0xa1, 0x83, 0xae, 0x97, 0x18, 0xc5, 0x54, 0x27, 0xa2, 0x21, 0x52, 0x03, 0x31, 0x5b, 0x11, 0x67, 0xf6, 0x12, 0x00, 0x87, 0x2f, 0xff, 0x59, 0x70, 0x8f, 0x6d, 0x71, 0xab, 0xab, 0x24, 0xb8, 0xba, 0x35, + /* (2^356)P */ 0x69, 0x43, 0xa7, 0x14, 0x06, 0x96, 0xe9, 0xc2, 0xe3, 0x2b, 0x45, 0x22, 0xc0, 0xd0, 0x2f, 0x34, 0xd1, 0x01, 0x99, 0xfc, 0x99, 0x38, 0xa1, 0x25, 0x2e, 0x59, 0x6c, 0x27, 0xc9, 0xeb, 0x7b, 0xdc, 0x4e, 0x26, 0x68, 0xba, 0xfa, 0xec, 0x02, 0x05, 0x64, 0x80, 0x30, 0x20, 0x5c, 0x26, 0x7f, 0xaf, 0x95, 0x17, 0x3d, 0x5c, 0x9e, 0x96, 0x96, 0xaf, + /* (2^357)P */ 0xa6, 0xba, 0x21, 0x29, 0x32, 0xe2, 0x98, 0xde, 0x9b, 0x6d, 0x0b, 0x44, 0x91, 0xa8, 0x3e, 0xd4, 0xb8, 0x04, 0x6c, 0xf6, 0x04, 0x39, 0xbd, 0x52, 0x05, 0x15, 0x27, 0x78, 0x8e, 0x55, 0xac, 0x79, 0xc5, 0xe6, 0x00, 0x7f, 0x90, 0xa2, 0xdd, 0x07, 0x13, 0xe0, 0x24, 0x70, 0x5c, 0x0f, 0x4d, 0xa9, 0xf9, 0xae, 0xcb, 0x34, 0x10, 0x9d, 0x89, 0x9d, + /* (2^358)P */ 0x12, 0xe0, 0xb3, 0x9f, 0xc4, 0x96, 0x1d, 0xcf, 0xed, 0x99, 0x64, 0x28, 0x8d, 0xc7, 0x31, 0x82, 0xee, 0x5e, 0x75, 0x48, 0xff, 0x3a, 0xf2, 0x09, 0x34, 0x03, 0x93, 0x52, 0x19, 0xb2, 0xc5, 0x81, 0x93, 0x45, 0x5e, 0x59, 0x21, 0x2b, 0xec, 0x89, 0xba, 0x36, 0x6e, 0xf9, 0x82, 0x75, 0x7e, 0x82, 0x3f, 0xaa, 0xe2, 0xe3, 0x3b, 0x94, 0xfd, 0x98, + /* (2^359)P */ 0x7c, 0xdb, 0x75, 0x31, 0x61, 0xfb, 0x15, 0x28, 0x94, 0xd7, 0xc3, 0x5a, 0xa9, 0xa1, 0x0a, 0x66, 0x0f, 0x2b, 0x13, 0x3e, 0x42, 0xb5, 0x28, 0x3a, 0xca, 0x83, 0xf3, 0x61, 0x22, 0xf4, 0x40, 0xc5, 0xdf, 0xe7, 0x31, 0x9f, 0x7e, 0x51, 0x75, 0x06, 0x9d, 0x51, 0xc8, 0xe7, 0x9f, 0xc3, 0x71, 0x4f, 0x3d, 0x5b, 0xfb, 0xe9, 0x8e, 0x08, 0x40, 0x8e, + /* (2^360)P */ 0xf7, 0x31, 0xad, 0x50, 0x5d, 0x25, 0x93, 0x73, 0x68, 0xf6, 0x7c, 0x89, 0x5a, 0x3d, 0x9f, 0x9b, 0x05, 0x82, 0xe7, 0x70, 0x4b, 0x19, 0xaa, 0xcf, 0xff, 0xde, 0x50, 0x8f, 0x2f, 0x69, 0xd3, 0xf0, 0x99, 0x51, 0x6b, 0x9d, 0xb6, 0x56, 0x6f, 0xf8, 0x4c, 0x74, 0x8b, 0x4c, 0x91, 0xf9, 0xa9, 0xb1, 0x3e, 0x07, 0xdf, 0x0b, 0x27, 0x8a, 0xb1, 0xed, + /* (2^361)P */ 0xfb, 0x67, 0xd9, 0x48, 0xd2, 0xe4, 0x44, 0x9b, 0x43, 0x15, 0x8a, 0xeb, 0x00, 0x53, 0xad, 0x25, 0xc7, 0x7e, 0x19, 0x30, 0x87, 0xb7, 0xd5, 0x5f, 0x04, 0xf8, 0xaa, 0xdd, 0x57, 0xae, 0x34, 0x75, 0xe2, 0x84, 0x4b, 0x54, 0x60, 0x37, 0x95, 0xe4, 0xd3, 0xec, 0xac, 0xef, 0x47, 0x31, 0xa3, 0xc8, 0x31, 0x22, 0xdb, 0x26, 0xe7, 0x6a, 0xb5, 0xad, + /* (2^362)P */ 0x44, 0x09, 0x5c, 0x95, 0xe4, 0x72, 0x3c, 0x1a, 0xd1, 0xac, 0x42, 0x51, 0x99, 0x6f, 0xfa, 0x1f, 0xf2, 0x22, 0xbe, 0xff, 0x7b, 0x66, 0xf5, 0x6c, 0xb3, 0x66, 0xc7, 0x4d, 0x78, 0x31, 0x83, 0x80, 0xf5, 0x41, 0xe9, 0x7f, 0xbe, 0xf7, 0x23, 0x49, 0x6b, 0x84, 0x4e, 0x7e, 0x47, 0x07, 0x6e, 0x74, 0xdf, 0xe5, 0x9d, 0x9e, 0x56, 0x2a, 0xc0, 0xbc, + /* (2^363)P */ 0xac, 0x10, 0x80, 0x8c, 0x7c, 0xfa, 0x83, 0xdf, 0xb3, 0xd0, 0xc4, 0xbe, 0xfb, 0x9f, 0xac, 0xc9, 0xc3, 0x40, 0x95, 0x0b, 0x09, 0x23, 0xda, 0x63, 0x67, 0xcf, 0xe7, 0x9f, 0x7d, 0x7b, 0x6b, 0xe2, 0xe6, 0x6d, 0xdb, 0x87, 0x9e, 0xa6, 0xff, 0x6d, 0xab, 0xbd, 0xfb, 0x54, 0x84, 0x68, 0xcf, 0x89, 0xf1, 0xd0, 0xe2, 0x85, 0x61, 0xdc, 0x22, 0xd1, + /* (2^364)P */ 0xa8, 0x48, 0xfb, 0x8c, 0x6a, 0x63, 0x01, 0x72, 0x43, 0x43, 0xeb, 0x21, 0xa3, 0x00, 0x8a, 0xc0, 0x87, 0x51, 0x9e, 0x86, 0x75, 0x16, 0x79, 0xf9, 0x6b, 0x11, 0x80, 0x62, 0xc2, 0x9d, 0xb8, 0x8c, 0x30, 0x8e, 0x8d, 0x03, 0x52, 0x7e, 0x31, 0x59, 0x38, 0xf9, 0x25, 0xc7, 0x0f, 0xc7, 0xa8, 0x2b, 0x5c, 0x80, 0xfa, 0x90, 0xa2, 0x63, 0xca, 0xe7, + /* (2^365)P */ 0xf1, 0x5d, 0xb5, 0xd9, 0x20, 0x10, 0x7d, 0x0f, 0xc5, 0x50, 0x46, 0x07, 0xff, 0x02, 0x75, 0x2b, 0x4a, 0xf3, 0x39, 0x91, 0x72, 0xb7, 0xd5, 0xcc, 0x38, 0xb8, 0xe7, 0x36, 0x26, 0x5e, 0x11, 0x97, 0x25, 0xfb, 0x49, 0x68, 0xdc, 0xb4, 0x46, 0x87, 0x5c, 0xc2, 0x7f, 0xaa, 0x7d, 0x36, 0x23, 0xa6, 0xc6, 0x53, 0xec, 0xbc, 0x57, 0x47, 0xc1, 0x2b, + /* (2^366)P */ 0x25, 0x5d, 0x7d, 0x95, 0xda, 0x0b, 0x8f, 0x78, 0x1e, 0x19, 0x09, 0xfa, 0x67, 0xe0, 0xa0, 0x17, 0x24, 0x76, 0x6c, 0x30, 0x1f, 0x62, 0x3d, 0xbe, 0x45, 0x70, 0xcc, 0xb6, 0x1e, 0x68, 0x06, 0x25, 0x68, 0x16, 0x1a, 0x33, 0x3f, 0x90, 0xc7, 0x78, 0x2d, 0x98, 0x3c, 0x2f, 0xb9, 0x2d, 0x94, 0x0b, 0xfb, 0x49, 0x56, 0x30, 0xd7, 0xc1, 0xe6, 0x48, + /* (2^367)P */ 0x7a, 0xd1, 0xe0, 0x8e, 0x67, 0xfc, 0x0b, 0x50, 0x1f, 0x84, 0x98, 0xfa, 0xaf, 0xae, 0x2e, 0x31, 0x27, 0xcf, 0x3f, 0xf2, 0x6e, 0x8d, 0x81, 0x8f, 0xd2, 0x5f, 0xde, 0xd3, 0x5e, 0xe9, 0xe7, 0x13, 0x48, 0x83, 0x5a, 0x4e, 0x84, 0xd1, 0x58, 0xcf, 0x6b, 0x84, 0xdf, 0x13, 0x1d, 0x91, 0x85, 0xe8, 0xcb, 0x29, 0x79, 0xd2, 0xca, 0xac, 0x6a, 0x93, + /* (2^368)P */ 0x53, 0x82, 0xce, 0x61, 0x96, 0x88, 0x6f, 0xe1, 0x4a, 0x4c, 0x1e, 0x30, 0x73, 0xe8, 0x74, 0xde, 0x40, 0x2b, 0xe0, 0xc4, 0xb5, 0xd8, 0x7c, 0x15, 0xe7, 0xe1, 0xb1, 0xe0, 0xd6, 0x88, 0xb1, 0x6a, 0x57, 0x19, 0x6a, 0x22, 0x66, 0x57, 0xf6, 0x8d, 0xfd, 0xc0, 0xf2, 0xa3, 0x03, 0x56, 0xfb, 0x2e, 0x75, 0x5e, 0xc7, 0x8e, 0x22, 0x96, 0x5c, 0x06, + /* (2^369)P */ 0x98, 0x7e, 0xbf, 0x3e, 0xbf, 0x24, 0x9d, 0x15, 0xd3, 0xf6, 0xd3, 0xd2, 0xf0, 0x11, 0xf2, 0xdb, 0x36, 0x23, 0x38, 0xf7, 0x1d, 0x71, 0x20, 0xd2, 0x54, 0x7f, 0x1e, 0x24, 0x8f, 0xe2, 0xaa, 0xf7, 0x3f, 0x6b, 0x41, 0x4e, 0xdc, 0x0e, 0xec, 0xe8, 0x35, 0x0a, 0x08, 0x6d, 0x89, 0x5b, 0x32, 0x91, 0x01, 0xb6, 0xe0, 0x2c, 0xc6, 0xa1, 0xbe, 0xb4, + /* (2^370)P */ 0x29, 0xf2, 0x1e, 0x1c, 0xdc, 0x68, 0x8a, 0x43, 0x87, 0x2c, 0x48, 0xb3, 0x9e, 0xed, 0xd2, 0x82, 0x46, 0xac, 0x2f, 0xef, 0x93, 0x34, 0x37, 0xca, 0x64, 0x8d, 0xc9, 0x06, 0x90, 0xbb, 0x78, 0x0a, 0x3c, 0x4c, 0xcf, 0x35, 0x7a, 0x0f, 0xf7, 0xa7, 0xf4, 0x2f, 0x45, 0x69, 0x3f, 0xa9, 0x5d, 0xce, 0x7b, 0x8a, 0x84, 0xc3, 0xae, 0xf4, 0xda, 0xd5, + /* (2^371)P */ 0xca, 0xba, 0x95, 0x43, 0x05, 0x7b, 0x06, 0xd9, 0x5c, 0x0a, 0x18, 0x5f, 0x6a, 0x6a, 0xce, 0xc0, 0x3d, 0x95, 0x51, 0x0e, 0x1a, 0xbe, 0x85, 0x7a, 0xf2, 0x69, 0xec, 0xc0, 0x8c, 0xca, 0xa3, 0x32, 0x0a, 0x76, 0x50, 0xc6, 0x76, 0x61, 0x00, 0x89, 0xbf, 0x6e, 0x0f, 0x48, 0x90, 0x31, 0x93, 0xec, 0x34, 0x70, 0xf0, 0xc3, 0x8d, 0xf0, 0x0f, 0xb5, + /* (2^372)P */ 0xbe, 0x23, 0xe2, 0x18, 0x99, 0xf1, 0xed, 0x8a, 0xf6, 0xc9, 0xac, 0xb8, 0x1e, 0x9a, 0x3c, 0x15, 0xae, 0xd7, 0x6d, 0xb3, 0x04, 0xee, 0x5b, 0x0d, 0x1e, 0x79, 0xb7, 0xf9, 0xf9, 0x8d, 0xad, 0xf9, 0x8f, 0x5a, 0x6a, 0x7b, 0xd7, 0x9b, 0xca, 0x62, 0xfe, 0x9c, 0xc0, 0x6f, 0x6d, 0x9d, 0x76, 0xa3, 0x69, 0xb9, 0x4c, 0xa1, 0xc4, 0x0c, 0x76, 0xaa, + /* (2^373)P */ 0x1c, 0x06, 0xfe, 0x3f, 0x45, 0x70, 0xcd, 0x97, 0xa9, 0xa2, 0xb1, 0xd3, 0xf2, 0xa5, 0x0c, 0x49, 0x2c, 0x75, 0x73, 0x1f, 0xcf, 0x00, 0xaf, 0xd5, 0x2e, 0xde, 0x0d, 0x8f, 0x8f, 0x7c, 0xc4, 0x58, 0xce, 0xd4, 0xf6, 0x24, 0x19, 0x2e, 0xd8, 0xc5, 0x1d, 0x1a, 0x3f, 0xb8, 0x4f, 0xbc, 0x7d, 0xbd, 0x68, 0xe3, 0x81, 0x98, 0x1b, 0xa8, 0xc9, 0xd9, + /* (2^374)P */ 0x39, 0x95, 0x78, 0x24, 0x6c, 0x38, 0xe4, 0xe7, 0xd0, 0x8d, 0xb9, 0x38, 0x71, 0x5e, 0xc1, 0x62, 0x80, 0xcc, 0xcb, 0x8c, 0x97, 0xca, 0xf8, 0xb9, 0xd9, 0x9c, 0xce, 0x72, 0x7b, 0x70, 0xee, 0x5f, 0xea, 0xa2, 0xdf, 0xa9, 0x14, 0x10, 0xf9, 0x6e, 0x59, 0x9f, 0x9c, 0xe0, 0x0c, 0xb2, 0x07, 0x97, 0xcd, 0xd2, 0x89, 0x16, 0xfd, 0x9c, 0xa8, 0xa5, + /* (2^375)P */ 0x5a, 0x61, 0xf1, 0x59, 0x7c, 0x38, 0xda, 0xe2, 0x85, 0x99, 0x68, 0xe9, 0xc9, 0xf7, 0x32, 0x7e, 0xc4, 0xca, 0xb7, 0x11, 0x08, 0x69, 0x2b, 0x66, 0x02, 0xf7, 0x2e, 0x18, 0xc3, 0x8e, 0xe1, 0xf9, 0xc5, 0x19, 0x9a, 0x0a, 0x9c, 0x07, 0xba, 0xc7, 0x9c, 0x03, 0x34, 0x89, 0x99, 0x67, 0x0b, 0x16, 0x4b, 0x07, 0x36, 0x16, 0x36, 0x2c, 0xe2, 0xa1, + /* (2^376)P */ 0x70, 0x10, 0x91, 0x27, 0xa8, 0x24, 0x8e, 0x29, 0x04, 0x6f, 0x79, 0x1f, 0xd3, 0xa5, 0x68, 0xd3, 0x0b, 0x7d, 0x56, 0x4d, 0x14, 0x57, 0x7b, 0x2e, 0x00, 0x9f, 0x9a, 0xfd, 0x6c, 0x63, 0x18, 0x81, 0xdb, 0x9d, 0xb7, 0xd7, 0xa4, 0x1e, 0xe8, 0x40, 0xf1, 0x4c, 0xa3, 0x01, 0xd5, 0x4b, 0x75, 0xea, 0xdd, 0x97, 0xfd, 0x5b, 0xb2, 0x66, 0x6a, 0x24, + /* (2^377)P */ 0x72, 0x11, 0xfe, 0x73, 0x1b, 0xd3, 0xea, 0x7f, 0x93, 0x15, 0x15, 0x05, 0xfe, 0x40, 0xe8, 0x28, 0xd8, 0x50, 0x47, 0x66, 0xfa, 0xb7, 0xb5, 0x04, 0xba, 0x35, 0x1e, 0x32, 0x9f, 0x5f, 0x32, 0xba, 0x3d, 0xd1, 0xed, 0x9a, 0x76, 0xca, 0xa3, 0x3e, 0x77, 0xd8, 0xd8, 0x7c, 0x5f, 0x68, 0x42, 0xb5, 0x86, 0x7f, 0x3b, 0xc9, 0xc1, 0x89, 0x64, 0xda, + /* (2^378)P */ 0xd5, 0xd4, 0x17, 0x31, 0xfc, 0x6a, 0xfd, 0xb8, 0xe8, 0xe5, 0x3e, 0x39, 0x06, 0xe4, 0xd1, 0x90, 0x2a, 0xca, 0xf6, 0x54, 0x6c, 0x1b, 0x2f, 0x49, 0x97, 0xb1, 0x2a, 0x82, 0x43, 0x3d, 0x1f, 0x8b, 0xe2, 0x47, 0xc5, 0x24, 0xa8, 0xd5, 0x53, 0x29, 0x7d, 0xc6, 0x87, 0xa6, 0x25, 0x3a, 0x64, 0xdd, 0x71, 0x08, 0x9e, 0xcd, 0xe9, 0x45, 0xc7, 0xba, + /* (2^379)P */ 0x37, 0x72, 0x6d, 0x13, 0x7a, 0x8d, 0x04, 0x31, 0xe6, 0xe3, 0x9e, 0x36, 0x71, 0x3e, 0xc0, 0x1e, 0xe3, 0x71, 0xd3, 0x49, 0x4e, 0x4a, 0x36, 0x42, 0x68, 0x68, 0x61, 0xc7, 0x3c, 0xdb, 0x81, 0x49, 0xf7, 0x91, 0x4d, 0xea, 0x4c, 0x4f, 0x98, 0xc6, 0x7e, 0x60, 0x84, 0x4b, 0x6a, 0x37, 0xbb, 0x52, 0xf7, 0xce, 0x02, 0xe4, 0xad, 0xd1, 0x3c, 0xa7, + /* (2^380)P */ 0x51, 0x06, 0x2d, 0xf8, 0x08, 0xe8, 0xf1, 0x0c, 0xe5, 0xa9, 0xac, 0x29, 0x73, 0x3b, 0xed, 0x98, 0x5f, 0x55, 0x08, 0x38, 0x51, 0x44, 0x36, 0x5d, 0xea, 0xc3, 0xb8, 0x0e, 0xa0, 0x4f, 0xd2, 0x79, 0xe9, 0x98, 0xc3, 0xf5, 0x00, 0xb9, 0x26, 0x27, 0x42, 0xa8, 0x07, 0xc1, 0x12, 0x31, 0xc1, 0xc3, 0x3c, 0x3b, 0x7a, 0x72, 0x97, 0xc2, 0x70, 0x3a, + /* (2^381)P */ 0xf4, 0xb2, 0xba, 0x32, 0xbc, 0xa9, 0x2f, 0x87, 0xc7, 0x3c, 0x45, 0xcd, 0xae, 0xe2, 0x13, 0x6d, 0x3a, 0xf2, 0xf5, 0x66, 0x97, 0x29, 0xaf, 0x53, 0x9f, 0xda, 0xea, 0x14, 0xdf, 0x04, 0x98, 0x19, 0x95, 0x9e, 0x2a, 0x00, 0x5c, 0x9d, 0x1d, 0xf0, 0x39, 0x23, 0xff, 0xfc, 0xca, 0x36, 0xb7, 0xde, 0xdf, 0x37, 0x78, 0x52, 0x21, 0xfa, 0x19, 0x10, + /* (2^382)P */ 0x50, 0x20, 0x73, 0x74, 0x62, 0x21, 0xf2, 0xf7, 0x9b, 0x66, 0x85, 0x34, 0x74, 0xd4, 0x9d, 0x60, 0xd7, 0xbc, 0xc8, 0x46, 0x3b, 0xb8, 0x80, 0x42, 0x15, 0x0a, 0x6c, 0x35, 0x1a, 0x69, 0xf0, 0x1d, 0x4b, 0x29, 0x54, 0x5a, 0x9a, 0x48, 0xec, 0x9f, 0x37, 0x74, 0x91, 0xd0, 0xd1, 0x9e, 0x00, 0xc2, 0x76, 0x56, 0xd6, 0xa0, 0x15, 0x14, 0x83, 0x59, + /* (2^383)P */ 0xc2, 0xf8, 0x22, 0x20, 0x23, 0x07, 0xbd, 0x1d, 0x6f, 0x1e, 0x8c, 0x56, 0x06, 0x6a, 0x4b, 0x9f, 0xe2, 0xa9, 0x92, 0x46, 0x4b, 0x46, 0x59, 0xd7, 0xe1, 0xda, 0x14, 0x98, 0x07, 0x65, 0x7e, 0x28, 0x20, 0xf2, 0x9d, 0x4f, 0x36, 0x5c, 0x92, 0xe0, 0x9d, 0xfe, 0x3e, 0xda, 0xe4, 0x47, 0x19, 0x3c, 0x00, 0x7f, 0x22, 0xf2, 0x9e, 0x51, 0xae, 0x4d, + /* (2^384)P */ 0xbe, 0x8c, 0x1b, 0x10, 0xb6, 0xad, 0xcc, 0xcc, 0xd8, 0x5e, 0x21, 0xa6, 0xfb, 0xf1, 0xf6, 0xbd, 0x0a, 0x24, 0x67, 0xb4, 0x57, 0x7a, 0xbc, 0xe8, 0xe9, 0xff, 0xee, 0x0a, 0x1f, 0xee, 0xbd, 0xc8, 0x44, 0xed, 0x2b, 0xbb, 0x55, 0x1f, 0xdd, 0x7c, 0xb3, 0xeb, 0x3f, 0x63, 0xa1, 0x28, 0x91, 0x21, 0xab, 0x71, 0xc6, 0x4c, 0xd0, 0xe9, 0xb0, 0x21, + /* (2^385)P */ 0xad, 0xc9, 0x77, 0x2b, 0xee, 0x89, 0xa4, 0x7b, 0xfd, 0xf9, 0xf6, 0x14, 0xe4, 0xed, 0x1a, 0x16, 0x9b, 0x78, 0x41, 0x43, 0xa8, 0x83, 0x72, 0x06, 0x2e, 0x7c, 0xdf, 0xeb, 0x7e, 0xdd, 0xd7, 0x8b, 0xea, 0x9a, 0x2b, 0x03, 0xba, 0x57, 0xf3, 0xf1, 0xd9, 0xe5, 0x09, 0xc5, 0x98, 0x61, 0x1c, 0x51, 0x6d, 0x5d, 0x6e, 0xfb, 0x5e, 0x95, 0x9f, 0xb5, + /* (2^386)P */ 0x23, 0xe2, 0x1e, 0x95, 0xa3, 0x5e, 0x42, 0x10, 0xc7, 0xc3, 0x70, 0xbf, 0x4b, 0x6b, 0x83, 0x36, 0x93, 0xb7, 0x68, 0x47, 0x88, 0x3a, 0x10, 0x88, 0x48, 0x7f, 0x8c, 0xae, 0x54, 0x10, 0x02, 0xa4, 0x52, 0x8f, 0x8d, 0xf7, 0x26, 0x4f, 0x50, 0xc3, 0x6a, 0xe2, 0x4e, 0x3b, 0x4c, 0xb9, 0x8a, 0x14, 0x15, 0x6d, 0x21, 0x29, 0xb3, 0x6e, 0x4e, 0xd0, + /* (2^387)P */ 0x4c, 0x8a, 0x18, 0x3f, 0xb7, 0x20, 0xfd, 0x3e, 0x54, 0xca, 0x68, 0x3c, 0xea, 0x6f, 0xf4, 0x6b, 0xa2, 0xbd, 0x01, 0xbd, 0xfe, 0x08, 0xa8, 0xd8, 0xc2, 0x20, 0x36, 0x05, 0xcd, 0xe9, 0xf3, 0x9e, 0xfa, 0x85, 0x66, 0x8f, 0x4b, 0x1d, 0x8c, 0x64, 0x4f, 0xb8, 0xc6, 0x0f, 0x5b, 0x57, 0xd8, 0x24, 0x19, 0x5a, 0x14, 0x4b, 0x92, 0xd3, 0x96, 0xbc, + /* (2^388)P */ 0xa9, 0x3f, 0xc9, 0x6c, 0xca, 0x64, 0x1e, 0x6f, 0xdf, 0x65, 0x7f, 0x9a, 0x47, 0x6b, 0x8a, 0x60, 0x31, 0xa6, 0x06, 0xac, 0x69, 0x30, 0xe6, 0xea, 0x63, 0x42, 0x26, 0x5f, 0xdb, 0xd0, 0xf2, 0x8e, 0x34, 0x0a, 0x3a, 0xeb, 0xf3, 0x79, 0xc8, 0xb7, 0x60, 0x56, 0x5c, 0x37, 0x95, 0x71, 0xf8, 0x7f, 0x49, 0x3e, 0x9e, 0x01, 0x26, 0x1e, 0x80, 0x9f, + /* (2^389)P */ 0xf8, 0x16, 0x9a, 0xaa, 0xb0, 0x28, 0xb5, 0x8e, 0xd0, 0x60, 0xe5, 0x26, 0xa9, 0x47, 0xc4, 0x5c, 0xa9, 0x39, 0xfe, 0x0a, 0xd8, 0x07, 0x2b, 0xb3, 0xce, 0xf1, 0xea, 0x1a, 0xf4, 0x7b, 0x98, 0x31, 0x3d, 0x13, 0x29, 0x80, 0xe8, 0x0d, 0xcf, 0x56, 0x39, 0x86, 0x50, 0x0c, 0xb3, 0x18, 0xf4, 0xc5, 0xca, 0xf2, 0x6f, 0xcd, 0x8d, 0xd5, 0x02, 0xb0, + /* (2^390)P */ 0xbf, 0x39, 0x3f, 0xac, 0x6d, 0x1a, 0x6a, 0xe4, 0x42, 0x24, 0xd6, 0x41, 0x9d, 0xb9, 0x5b, 0x46, 0x73, 0x93, 0x76, 0xaa, 0xb7, 0x37, 0x36, 0xa6, 0x09, 0xe5, 0x04, 0x3b, 0x66, 0xc4, 0x29, 0x3e, 0x41, 0xc2, 0xcb, 0xe5, 0x17, 0xd7, 0x34, 0x67, 0x1d, 0x2c, 0x12, 0xec, 0x24, 0x7a, 0x40, 0xa2, 0x45, 0x41, 0xf0, 0x75, 0xed, 0x43, 0x30, 0xc9, + /* (2^391)P */ 0x80, 0xf6, 0x47, 0x5b, 0xad, 0x54, 0x02, 0xbc, 0xdd, 0xa4, 0xb2, 0xd7, 0x42, 0x95, 0xf2, 0x0d, 0x1b, 0xef, 0x37, 0xa7, 0xb4, 0x34, 0x04, 0x08, 0x71, 0x1b, 0xd3, 0xdf, 0xa1, 0xf0, 0x2b, 0xfa, 0xc0, 0x1f, 0xf3, 0x44, 0xb5, 0xc6, 0x47, 0x3d, 0x65, 0x67, 0x45, 0x4d, 0x2f, 0xde, 0x52, 0x73, 0xfc, 0x30, 0x01, 0x6b, 0xc1, 0x03, 0xd8, 0xd7, + /* (2^392)P */ 0x1c, 0x67, 0x55, 0x3e, 0x01, 0x17, 0x0f, 0x3e, 0xe5, 0x34, 0x58, 0xfc, 0xcb, 0x71, 0x24, 0x74, 0x5d, 0x36, 0x1e, 0x89, 0x2a, 0x63, 0xf8, 0xf8, 0x9f, 0x50, 0x9f, 0x32, 0x92, 0x29, 0xd8, 0x1a, 0xec, 0x76, 0x57, 0x6c, 0x67, 0x12, 0x6a, 0x6e, 0xef, 0x97, 0x1f, 0xc3, 0x77, 0x60, 0x3c, 0x22, 0xcb, 0xc7, 0x04, 0x1a, 0x89, 0x2d, 0x10, 0xa6, + /* (2^393)P */ 0x12, 0xf5, 0xa9, 0x26, 0x16, 0xd9, 0x3c, 0x65, 0x5d, 0x83, 0xab, 0xd1, 0x70, 0x6b, 0x1c, 0xdb, 0xe7, 0x86, 0x0d, 0xfb, 0xe7, 0xf8, 0x2a, 0x58, 0x6e, 0x7a, 0x66, 0x13, 0x53, 0x3a, 0x6f, 0x8d, 0x43, 0x5f, 0x14, 0x23, 0x14, 0xff, 0x3d, 0x52, 0x7f, 0xee, 0xbd, 0x7a, 0x34, 0x8b, 0x35, 0x24, 0xc3, 0x7a, 0xdb, 0xcf, 0x22, 0x74, 0x9a, 0x8f, + /* (2^394)P */ 0xdb, 0x20, 0xfc, 0xe5, 0x39, 0x4e, 0x7d, 0x78, 0xee, 0x0b, 0xbf, 0x1d, 0x80, 0xd4, 0x05, 0x4f, 0xb9, 0xd7, 0x4e, 0x94, 0x88, 0x9a, 0x50, 0x78, 0x1a, 0x70, 0x8c, 0xcc, 0x25, 0xb6, 0x61, 0x09, 0xdc, 0x7b, 0xea, 0x3f, 0x7f, 0xea, 0x2a, 0x0d, 0x47, 0x1c, 0x8e, 0xa6, 0x5b, 0xd2, 0xa3, 0x61, 0x93, 0x3c, 0x68, 0x9f, 0x8b, 0xea, 0xb0, 0xcb, + /* (2^395)P */ 0xff, 0x54, 0x02, 0x19, 0xae, 0x8b, 0x4c, 0x2c, 0x3a, 0xe0, 0xe4, 0xac, 0x87, 0xf7, 0x51, 0x45, 0x41, 0x43, 0xdc, 0xaa, 0xcd, 0xcb, 0xdc, 0x40, 0xe3, 0x44, 0x3b, 0x1d, 0x9e, 0x3d, 0xb9, 0x82, 0xcc, 0x7a, 0xc5, 0x12, 0xf8, 0x1e, 0xdd, 0xdb, 0x8d, 0xb0, 0x2a, 0xe8, 0xe6, 0x6c, 0x94, 0x3b, 0xb7, 0x2d, 0xba, 0x79, 0x3b, 0xb5, 0x86, 0xfb, + /* (2^396)P */ 0x82, 0x88, 0x13, 0xdd, 0x6c, 0xcd, 0x85, 0x2b, 0x90, 0x86, 0xb7, 0xac, 0x16, 0xa6, 0x6e, 0x6a, 0x94, 0xd8, 0x1e, 0x4e, 0x41, 0x0f, 0xce, 0x81, 0x6a, 0xa8, 0x26, 0x56, 0x43, 0x52, 0x52, 0xe6, 0xff, 0x88, 0xcf, 0x47, 0x05, 0x1d, 0xff, 0xf3, 0xa0, 0x10, 0xb2, 0x97, 0x87, 0xeb, 0x47, 0xbb, 0xfa, 0x1f, 0xe8, 0x4c, 0xce, 0xc4, 0xcd, 0x93, + /* (2^397)P */ 0xf4, 0x11, 0xf5, 0x8d, 0x89, 0x29, 0x79, 0xb3, 0x59, 0x0b, 0x29, 0x7d, 0x9c, 0x12, 0x4a, 0x65, 0x72, 0x3a, 0xf9, 0xec, 0x37, 0x18, 0x86, 0xef, 0x44, 0x07, 0x25, 0x74, 0x76, 0x53, 0xed, 0x51, 0x01, 0xc6, 0x28, 0xc5, 0xc3, 0x4a, 0x0f, 0x99, 0xec, 0xc8, 0x40, 0x5a, 0x83, 0x30, 0x79, 0xa2, 0x3e, 0x63, 0x09, 0x2d, 0x6f, 0x23, 0x54, 0x1c, + /* (2^398)P */ 0x5c, 0x6f, 0x3b, 0x1c, 0x30, 0x77, 0x7e, 0x87, 0x66, 0x83, 0x2e, 0x7e, 0x85, 0x50, 0xfd, 0xa0, 0x7a, 0xc2, 0xf5, 0x0f, 0xc1, 0x64, 0xe7, 0x0b, 0xbd, 0x59, 0xa7, 0xe7, 0x65, 0x53, 0xc3, 0xf5, 0x55, 0x5b, 0xe1, 0x82, 0x30, 0x5a, 0x61, 0xcd, 0xa0, 0x89, 0x32, 0xdb, 0x87, 0xfc, 0x21, 0x8a, 0xab, 0x6d, 0x82, 0xa8, 0x42, 0x81, 0x4f, 0xf2, + /* (2^399)P */ 0xb3, 0xeb, 0x88, 0x18, 0xf6, 0x56, 0x96, 0xbf, 0xba, 0x5d, 0x71, 0xa1, 0x5a, 0xd1, 0x04, 0x7b, 0xd5, 0x46, 0x01, 0x74, 0xfe, 0x15, 0x25, 0xb7, 0xff, 0x0c, 0x24, 0x47, 0xac, 0xfd, 0xab, 0x47, 0x32, 0xe1, 0x6a, 0x4e, 0xca, 0xcf, 0x7f, 0xdd, 0xf8, 0xd2, 0x4b, 0x3b, 0xf5, 0x17, 0xba, 0xba, 0x8b, 0xa1, 0xec, 0x28, 0x3f, 0x97, 0xab, 0x2a, + /* (2^400)P */ 0x51, 0x38, 0xc9, 0x5e, 0xc6, 0xb3, 0x64, 0xf2, 0x24, 0x4d, 0x04, 0x7d, 0xc8, 0x39, 0x0c, 0x4a, 0xc9, 0x73, 0x74, 0x1b, 0x5c, 0xb2, 0xc5, 0x41, 0x62, 0xa0, 0x4c, 0x6d, 0x8d, 0x91, 0x9a, 0x7b, 0x88, 0xab, 0x9c, 0x7e, 0x23, 0xdb, 0x6f, 0xb5, 0x72, 0xd6, 0x47, 0x40, 0xef, 0x22, 0x58, 0x62, 0x19, 0x6c, 0x38, 0xba, 0x5b, 0x00, 0x30, 0x9f, + /* (2^401)P */ 0x65, 0xbb, 0x3b, 0x9b, 0xe9, 0xae, 0xbf, 0xbe, 0xe4, 0x13, 0x95, 0xf3, 0xe3, 0x77, 0xcb, 0xe4, 0x9a, 0x22, 0xb5, 0x4a, 0x08, 0x9d, 0xb3, 0x9e, 0x27, 0xe0, 0x15, 0x6c, 0x9f, 0x7e, 0x9a, 0x5e, 0x15, 0x45, 0x25, 0x8d, 0x01, 0x0a, 0xd2, 0x2b, 0xbd, 0x48, 0x06, 0x0d, 0x18, 0x97, 0x4b, 0xdc, 0xbc, 0xf0, 0xcd, 0xb2, 0x52, 0x3c, 0xac, 0xf5, + /* (2^402)P */ 0x3e, 0xed, 0x47, 0x6b, 0x5c, 0xf6, 0x76, 0xd0, 0xe9, 0x15, 0xa3, 0xcb, 0x36, 0x00, 0x21, 0xa3, 0x79, 0x20, 0xa5, 0x3e, 0x88, 0x03, 0xcb, 0x7e, 0x63, 0xbb, 0xed, 0xa9, 0x13, 0x35, 0x16, 0xaf, 0x2e, 0xb4, 0x70, 0x14, 0x93, 0xfb, 0xc4, 0x9b, 0xd8, 0xb1, 0xbe, 0x43, 0xd1, 0x85, 0xb8, 0x97, 0xef, 0xea, 0x88, 0xa1, 0x25, 0x52, 0x62, 0x75, + /* (2^403)P */ 0x8e, 0x4f, 0xaa, 0x23, 0x62, 0x7e, 0x2b, 0x37, 0x89, 0x00, 0x11, 0x30, 0xc5, 0x33, 0x4a, 0x89, 0x8a, 0xe2, 0xfc, 0x5c, 0x6a, 0x75, 0xe5, 0xf7, 0x02, 0x4a, 0x9b, 0xf7, 0xb5, 0x6a, 0x85, 0x31, 0xd3, 0x5a, 0xcf, 0xc3, 0xf8, 0xde, 0x2f, 0xcf, 0xb5, 0x24, 0xf4, 0xe3, 0xa1, 0xad, 0x42, 0xae, 0x09, 0xb9, 0x2e, 0x04, 0x2d, 0x01, 0x22, 0x3f, + /* (2^404)P */ 0x41, 0x16, 0xfb, 0x7d, 0x50, 0xfd, 0xb5, 0xba, 0x88, 0x24, 0xba, 0xfd, 0x3d, 0xb2, 0x90, 0x15, 0xb7, 0xfa, 0xa2, 0xe1, 0x4c, 0x7d, 0xb9, 0xc6, 0xff, 0x81, 0x57, 0xb6, 0xc2, 0x9e, 0xcb, 0xc4, 0x35, 0xbd, 0x01, 0xb7, 0xaa, 0xce, 0xd0, 0xe9, 0xb5, 0xd6, 0x72, 0xbf, 0xd2, 0xee, 0xc7, 0xac, 0x94, 0xff, 0x29, 0x57, 0x02, 0x49, 0x09, 0xad, + /* (2^405)P */ 0x27, 0xa5, 0x78, 0x1b, 0xbf, 0x6b, 0xaf, 0x0b, 0x8c, 0xd9, 0xa8, 0x37, 0xb0, 0x67, 0x18, 0xb6, 0xc7, 0x05, 0x8a, 0x67, 0x03, 0x30, 0x62, 0x6e, 0x56, 0x82, 0xa9, 0x54, 0x3e, 0x0c, 0x4e, 0x07, 0xe1, 0x5a, 0x38, 0xed, 0xfa, 0xc8, 0x55, 0x6b, 0x08, 0xa3, 0x6b, 0x64, 0x2a, 0x15, 0xd6, 0x39, 0x6f, 0x47, 0x99, 0x42, 0x3f, 0x33, 0x84, 0x8f, + /* (2^406)P */ 0xbc, 0x45, 0x29, 0x81, 0x0e, 0xa4, 0xc5, 0x72, 0x3a, 0x10, 0xe1, 0xc4, 0x1e, 0xda, 0xc3, 0xfe, 0xb0, 0xce, 0xd2, 0x13, 0x34, 0x67, 0x21, 0xc6, 0x7e, 0xf9, 0x8c, 0xff, 0x39, 0x50, 0xae, 0x92, 0x60, 0x35, 0x2f, 0x8b, 0x6e, 0xc9, 0xc1, 0x27, 0x3a, 0x94, 0x66, 0x3e, 0x26, 0x84, 0x93, 0xc8, 0x6c, 0xcf, 0xd2, 0x03, 0xa1, 0x10, 0xcf, 0xb7, + /* (2^407)P */ 0x64, 0xda, 0x19, 0xf6, 0xc5, 0x73, 0x17, 0x44, 0x88, 0x81, 0x07, 0x0d, 0x34, 0xb2, 0x75, 0xf9, 0xd9, 0xe2, 0xe0, 0x8b, 0x71, 0xcf, 0x72, 0x34, 0x83, 0xb4, 0xce, 0xfc, 0xd7, 0x29, 0x09, 0x5a, 0x98, 0xbf, 0x14, 0xac, 0x77, 0x55, 0x38, 0x47, 0x5b, 0x0f, 0x40, 0x24, 0xe5, 0xa5, 0xa6, 0xac, 0x2d, 0xa6, 0xff, 0x9c, 0x73, 0xfe, 0x5c, 0x7e, + /* (2^408)P */ 0x1e, 0x33, 0xcc, 0x68, 0xb2, 0xbc, 0x8c, 0x93, 0xaf, 0xcc, 0x38, 0xf8, 0xd9, 0x16, 0x72, 0x50, 0xac, 0xd9, 0xb5, 0x0b, 0x9a, 0xbe, 0x46, 0x7a, 0xf1, 0xee, 0xf1, 0xad, 0xec, 0x5b, 0x59, 0x27, 0x9c, 0x05, 0xa3, 0x87, 0xe0, 0x37, 0x2c, 0x83, 0xce, 0xb3, 0x65, 0x09, 0x8e, 0xc3, 0x9c, 0xbf, 0x6a, 0xa2, 0x00, 0xcc, 0x12, 0x36, 0xc5, 0x95, + /* (2^409)P */ 0x36, 0x11, 0x02, 0x14, 0x9c, 0x3c, 0xeb, 0x2f, 0x23, 0x5b, 0x6b, 0x2b, 0x08, 0x54, 0x53, 0xac, 0xb2, 0xa3, 0xe0, 0x26, 0x62, 0x3c, 0xe4, 0xe1, 0x81, 0xee, 0x13, 0x3e, 0xa4, 0x97, 0xef, 0xf9, 0x92, 0x27, 0x01, 0xce, 0x54, 0x8b, 0x3e, 0x31, 0xbe, 0xa7, 0x88, 0xcf, 0x47, 0x99, 0x3c, 0x10, 0x6f, 0x60, 0xb3, 0x06, 0x4e, 0xee, 0x1b, 0xf0, + /* (2^410)P */ 0x59, 0x49, 0x66, 0xcf, 0x22, 0xe6, 0xf6, 0x73, 0xfe, 0xa3, 0x1c, 0x09, 0xfa, 0x5f, 0x65, 0xa8, 0xf0, 0x82, 0xc2, 0xef, 0x16, 0x63, 0x6e, 0x79, 0x69, 0x51, 0x39, 0x07, 0x65, 0xc4, 0x81, 0xec, 0x73, 0x0f, 0x15, 0x93, 0xe1, 0x30, 0x33, 0xe9, 0x37, 0x86, 0x42, 0x4c, 0x1f, 0x9b, 0xad, 0xee, 0x3f, 0xf1, 0x2a, 0x8e, 0x6a, 0xa3, 0xc8, 0x35, + /* (2^411)P */ 0x1e, 0x49, 0xf1, 0xdd, 0xd2, 0x9c, 0x8e, 0x78, 0xb2, 0x06, 0xe4, 0x6a, 0xab, 0x3a, 0xdc, 0xcd, 0xf4, 0xeb, 0xe1, 0xe7, 0x2f, 0xaa, 0xeb, 0x40, 0x31, 0x9f, 0xb9, 0xab, 0x13, 0xa9, 0x78, 0xbf, 0x38, 0x89, 0x0e, 0x85, 0x14, 0x8b, 0x46, 0x76, 0x14, 0xda, 0xcf, 0x33, 0xc8, 0x79, 0xd3, 0xd5, 0xa3, 0x6a, 0x69, 0x45, 0x70, 0x34, 0xc3, 0xe9, + /* (2^412)P */ 0x5e, 0xe7, 0x78, 0xe9, 0x24, 0xcc, 0xe9, 0xf4, 0xc8, 0x6b, 0xe0, 0xfb, 0x3a, 0xbe, 0xcc, 0x42, 0x4a, 0x00, 0x22, 0xf8, 0xe6, 0x32, 0xbe, 0x6d, 0x18, 0x55, 0x60, 0xe9, 0x72, 0x69, 0x50, 0x56, 0xca, 0x04, 0x18, 0x38, 0xa1, 0xee, 0xd8, 0x38, 0x3c, 0xa7, 0x70, 0xe2, 0xb9, 0x4c, 0xa0, 0xc8, 0x89, 0x72, 0xcf, 0x49, 0x7f, 0xdf, 0xbc, 0x67, + /* (2^413)P */ 0x1d, 0x17, 0xcb, 0x0b, 0xbd, 0xb2, 0x36, 0xe3, 0xa8, 0x99, 0x31, 0xb6, 0x26, 0x9c, 0x0c, 0x74, 0xaf, 0x4d, 0x24, 0x61, 0xcf, 0x31, 0x7b, 0xed, 0xdd, 0xc3, 0xf6, 0x32, 0x70, 0xfe, 0x17, 0xf6, 0x51, 0x37, 0x65, 0xce, 0x5d, 0xaf, 0xa5, 0x2f, 0x2a, 0xfe, 0x00, 0x71, 0x7c, 0x50, 0xbe, 0x21, 0xc7, 0xed, 0xc6, 0xfc, 0x67, 0xcf, 0x9c, 0xdd, + /* (2^414)P */ 0x26, 0x3e, 0xf8, 0xbb, 0xd0, 0xb1, 0x01, 0xd8, 0xeb, 0x0b, 0x62, 0x87, 0x35, 0x4c, 0xde, 0xca, 0x99, 0x9c, 0x6d, 0xf7, 0xb6, 0xf0, 0x57, 0x0a, 0x52, 0x29, 0x6a, 0x3f, 0x26, 0x31, 0x04, 0x07, 0x2a, 0xc9, 0xfa, 0x9b, 0x0e, 0x62, 0x8e, 0x72, 0xf2, 0xad, 0xce, 0xb6, 0x35, 0x7a, 0xc1, 0xae, 0x35, 0xc7, 0xa3, 0x14, 0xcf, 0x0c, 0x28, 0xb7, + /* (2^415)P */ 0xa6, 0xf1, 0x32, 0x3a, 0x20, 0xd2, 0x24, 0x97, 0xcf, 0x5d, 0x37, 0x99, 0xaf, 0x33, 0x7a, 0x5b, 0x7a, 0xcc, 0x4e, 0x41, 0x38, 0xb1, 0x4e, 0xad, 0xc9, 0xd9, 0x71, 0x7e, 0xb2, 0xf5, 0xd5, 0x01, 0x6c, 0x4d, 0xfd, 0xa1, 0xda, 0x03, 0x38, 0x9b, 0x3d, 0x92, 0x92, 0xf2, 0xca, 0xbf, 0x1f, 0x24, 0xa4, 0xbb, 0x30, 0x6a, 0x74, 0x56, 0xc8, 0xce, + /* (2^416)P */ 0x27, 0xf4, 0xed, 0xc9, 0xc3, 0xb1, 0x79, 0x85, 0xbe, 0xf6, 0xeb, 0xf3, 0x55, 0xc7, 0xaa, 0xa6, 0xe9, 0x07, 0x5d, 0xf4, 0xeb, 0xa6, 0x81, 0xe3, 0x0e, 0xcf, 0xa3, 0xc1, 0xef, 0xe7, 0x34, 0xb2, 0x03, 0x73, 0x8a, 0x91, 0xf1, 0xad, 0x05, 0xc7, 0x0b, 0x43, 0x99, 0x12, 0x31, 0xc8, 0xc7, 0xc5, 0xa4, 0x3d, 0xcd, 0xe5, 0x4e, 0x6d, 0x24, 0xdd, + /* (2^417)P */ 0x61, 0x54, 0xd0, 0x95, 0x2c, 0x45, 0x75, 0xac, 0xb5, 0x1a, 0x9d, 0x11, 0xeb, 0xed, 0x6b, 0x57, 0xa3, 0xe6, 0xcd, 0x77, 0xd4, 0x83, 0x8e, 0x39, 0xf1, 0x0f, 0x98, 0xcb, 0x40, 0x02, 0x6e, 0x10, 0x82, 0x9e, 0xb4, 0x93, 0x76, 0xd7, 0x97, 0xa3, 0x53, 0x12, 0x86, 0xc6, 0x15, 0x78, 0x73, 0x93, 0xe7, 0x7f, 0xcf, 0x1f, 0xbf, 0xcd, 0xd2, 0x7a, + /* (2^418)P */ 0xc2, 0x21, 0xdc, 0xd5, 0x69, 0xff, 0xca, 0x49, 0x3a, 0xe1, 0xc3, 0x69, 0x41, 0x56, 0xc1, 0x76, 0x63, 0x24, 0xbd, 0x64, 0x1b, 0x3d, 0x92, 0xf9, 0x13, 0x04, 0x25, 0xeb, 0x27, 0xa6, 0xef, 0x39, 0x3a, 0x80, 0xe0, 0xf8, 0x27, 0xee, 0xc9, 0x49, 0x77, 0xef, 0x3f, 0x29, 0x3d, 0x5e, 0xe6, 0x66, 0x83, 0xd1, 0xf6, 0xfe, 0x9d, 0xbc, 0xf1, 0x96, + /* (2^419)P */ 0x6b, 0xc6, 0x99, 0x26, 0x3c, 0xf3, 0x63, 0xf9, 0xc7, 0x29, 0x8c, 0x52, 0x62, 0x2d, 0xdc, 0x8a, 0x66, 0xce, 0x2c, 0xa7, 0xe4, 0xf0, 0xd7, 0x37, 0x17, 0x1e, 0xe4, 0xa3, 0x53, 0x7b, 0x29, 0x8e, 0x60, 0x99, 0xf9, 0x0c, 0x7c, 0x6f, 0xa2, 0xcc, 0x9f, 0x80, 0xdd, 0x5e, 0x46, 0xaa, 0x0d, 0x6c, 0xc9, 0x6c, 0xf7, 0x78, 0x5b, 0x38, 0xe3, 0x24, + /* (2^420)P */ 0x4b, 0x75, 0x6a, 0x2f, 0x08, 0xe1, 0x72, 0x76, 0xab, 0x82, 0x96, 0xdf, 0x3b, 0x1f, 0x9b, 0xd8, 0xed, 0xdb, 0xcd, 0x15, 0x09, 0x5a, 0x1e, 0xb7, 0xc5, 0x26, 0x72, 0x07, 0x0c, 0x50, 0xcd, 0x3b, 0x4d, 0x3f, 0xa2, 0x67, 0xc2, 0x02, 0x61, 0x2e, 0x68, 0xe9, 0x6f, 0xf0, 0x21, 0x2a, 0xa7, 0x3b, 0x88, 0x04, 0x11, 0x64, 0x49, 0x0d, 0xb4, 0x46, + /* (2^421)P */ 0x63, 0x85, 0xf3, 0xc5, 0x2b, 0x5a, 0x9f, 0xf0, 0x17, 0xcb, 0x45, 0x0a, 0xf3, 0x6e, 0x7e, 0xb0, 0x7c, 0xbc, 0xf0, 0x4f, 0x3a, 0xb0, 0xbc, 0x36, 0x36, 0x52, 0x51, 0xcb, 0xfe, 0x9a, 0xcb, 0xe8, 0x7e, 0x4b, 0x06, 0x7f, 0xaa, 0x35, 0xc8, 0x0e, 0x7a, 0x30, 0xa3, 0xb1, 0x09, 0xbb, 0x86, 0x4c, 0xbe, 0xb8, 0xbd, 0xe0, 0x32, 0xa5, 0xd4, 0xf7, + /* (2^422)P */ 0x7d, 0x50, 0x37, 0x68, 0x4e, 0x22, 0xb2, 0x2c, 0xd5, 0x0f, 0x2b, 0x6d, 0xb1, 0x51, 0xf2, 0x82, 0xe9, 0x98, 0x7c, 0x50, 0xc7, 0x96, 0x7e, 0x0e, 0xdc, 0xb1, 0x0e, 0xb2, 0x63, 0x8c, 0x30, 0x37, 0x72, 0x21, 0x9c, 0x61, 0xc2, 0xa7, 0x33, 0xd9, 0xb2, 0x63, 0x93, 0xd1, 0x6b, 0x6a, 0x73, 0xa5, 0x58, 0x80, 0xff, 0x04, 0xc7, 0x83, 0x21, 0x29, + /* (2^423)P */ 0x29, 0x04, 0xbc, 0x99, 0x39, 0xc9, 0x58, 0xc9, 0x6b, 0x17, 0xe8, 0x90, 0xb3, 0xe6, 0xa9, 0xb6, 0x28, 0x9b, 0xcb, 0x3b, 0x28, 0x90, 0x68, 0x71, 0xff, 0xcf, 0x08, 0x78, 0xc9, 0x8d, 0xa8, 0x4e, 0x43, 0xd1, 0x1c, 0x9e, 0xa4, 0xe3, 0xdf, 0xbf, 0x92, 0xf4, 0xf9, 0x41, 0xba, 0x4d, 0x1c, 0xf9, 0xdd, 0x74, 0x76, 0x1c, 0x6e, 0x3e, 0x94, 0x87, + /* (2^424)P */ 0xe4, 0xda, 0xc5, 0xd7, 0xfb, 0x87, 0xc5, 0x4d, 0x6b, 0x19, 0xaa, 0xb9, 0xbc, 0x8c, 0xf2, 0x8a, 0xd8, 0x5d, 0xdb, 0x4d, 0xef, 0xa6, 0xf2, 0x65, 0xf1, 0x22, 0x9c, 0xf1, 0x46, 0x30, 0x71, 0x7c, 0xe4, 0x53, 0x8e, 0x55, 0x2e, 0x9c, 0x9a, 0x31, 0x2a, 0xc3, 0xab, 0x0f, 0xde, 0xe4, 0xbe, 0xd8, 0x96, 0x50, 0x6e, 0x0c, 0x54, 0x49, 0xe6, 0xec, + /* (2^425)P */ 0x3c, 0x1d, 0x5a, 0xa5, 0xda, 0xad, 0xdd, 0xc2, 0xae, 0xac, 0x6f, 0x86, 0x75, 0x31, 0x91, 0x64, 0x45, 0x9d, 0xa4, 0xf0, 0x81, 0xf1, 0x0e, 0xba, 0x74, 0xaf, 0x7b, 0xcd, 0x6f, 0xfe, 0xac, 0x4e, 0xdb, 0x4e, 0x45, 0x35, 0x36, 0xc5, 0xc0, 0x6c, 0x3d, 0x64, 0xf4, 0xd8, 0x07, 0x62, 0xd1, 0xec, 0xf3, 0xfc, 0x93, 0xc9, 0x28, 0x0c, 0x2c, 0xf3, + /* (2^426)P */ 0x0c, 0x69, 0x2b, 0x5c, 0xb6, 0x41, 0x69, 0xf1, 0xa4, 0xf1, 0x5b, 0x75, 0x4c, 0x42, 0x8b, 0x47, 0xeb, 0x69, 0xfb, 0xa8, 0xe6, 0xf9, 0x7b, 0x48, 0x50, 0xaf, 0xd3, 0xda, 0xb2, 0x35, 0x10, 0xb5, 0x5b, 0x40, 0x90, 0x39, 0xc9, 0x07, 0x06, 0x73, 0x26, 0x20, 0x95, 0x01, 0xa4, 0x2d, 0xf0, 0xe7, 0x2e, 0x00, 0x7d, 0x41, 0x09, 0x68, 0x13, 0xc4, + /* (2^427)P */ 0xbe, 0x38, 0x78, 0xcf, 0xc9, 0x4f, 0x36, 0xca, 0x09, 0x61, 0x31, 0x3c, 0x57, 0x2e, 0xec, 0x17, 0xa4, 0x7d, 0x19, 0x2b, 0x9b, 0x5b, 0xbe, 0x8f, 0xd6, 0xc5, 0x2f, 0x86, 0xf2, 0x64, 0x76, 0x17, 0x00, 0x6e, 0x1a, 0x8c, 0x67, 0x1b, 0x68, 0xeb, 0x15, 0xa2, 0xd6, 0x09, 0x91, 0xdd, 0x23, 0x0d, 0x98, 0xb2, 0x10, 0x19, 0x55, 0x9b, 0x63, 0xf2, + /* (2^428)P */ 0x51, 0x1f, 0x93, 0xea, 0x2a, 0x3a, 0xfa, 0x41, 0xc0, 0x57, 0xfb, 0x74, 0xa6, 0x65, 0x09, 0x56, 0x14, 0xb6, 0x12, 0xaa, 0xb3, 0x1a, 0x8d, 0x3b, 0x76, 0x91, 0x7a, 0x23, 0x56, 0x9c, 0x6a, 0xc0, 0xe0, 0x3c, 0x3f, 0xb5, 0x1a, 0xf4, 0x57, 0x71, 0x93, 0x2b, 0xb1, 0xa7, 0x70, 0x57, 0x22, 0x80, 0xf5, 0xb8, 0x07, 0x77, 0x87, 0x0c, 0xbe, 0x83, + /* (2^429)P */ 0x07, 0x9b, 0x0e, 0x52, 0x38, 0x63, 0x13, 0x86, 0x6a, 0xa6, 0xb4, 0xd2, 0x60, 0x68, 0x9a, 0x99, 0x82, 0x0a, 0x04, 0x5f, 0x89, 0x7a, 0x1a, 0x2a, 0xae, 0x2d, 0x35, 0x0c, 0x1e, 0xad, 0xef, 0x4f, 0x9a, 0xfc, 0xc8, 0xd9, 0xcf, 0x9d, 0x48, 0x71, 0xa5, 0x55, 0x79, 0x73, 0x39, 0x1b, 0xd8, 0x73, 0xec, 0x9b, 0x03, 0x16, 0xd8, 0x82, 0xf7, 0x67, + /* (2^430)P */ 0x52, 0x67, 0x42, 0x21, 0xc9, 0x40, 0x78, 0x82, 0x2b, 0x95, 0x2d, 0x20, 0x92, 0xd1, 0xe2, 0x61, 0x25, 0xb0, 0xc6, 0x9c, 0x20, 0x59, 0x8e, 0x28, 0x6f, 0xf3, 0xfd, 0xd3, 0xc1, 0x32, 0x43, 0xc9, 0xa6, 0x08, 0x7a, 0x77, 0x9c, 0x4c, 0x8c, 0x33, 0x71, 0x13, 0x69, 0xe3, 0x52, 0x30, 0xa7, 0xf5, 0x07, 0x67, 0xac, 0xad, 0x46, 0x8a, 0x26, 0x25, + /* (2^431)P */ 0xda, 0x86, 0xc4, 0xa2, 0x71, 0x56, 0xdd, 0xd2, 0x48, 0xd3, 0xde, 0x42, 0x63, 0x01, 0xa7, 0x2c, 0x92, 0x83, 0x6f, 0x2e, 0xd8, 0x1e, 0x3f, 0xc1, 0xc5, 0x42, 0x4e, 0x34, 0x19, 0x54, 0x6e, 0x35, 0x2c, 0x51, 0x2e, 0xfd, 0x0f, 0x9a, 0x45, 0x66, 0x5e, 0x4a, 0x83, 0xda, 0x0a, 0x53, 0x68, 0x63, 0xfa, 0xce, 0x47, 0x20, 0xd3, 0x34, 0xba, 0x0d, + /* (2^432)P */ 0xd0, 0xe9, 0x64, 0xa4, 0x61, 0x4b, 0x86, 0xe5, 0x93, 0x6f, 0xda, 0x0e, 0x31, 0x7e, 0x6e, 0xe3, 0xc6, 0x73, 0xd8, 0xa3, 0x08, 0x57, 0x52, 0xcd, 0x51, 0x63, 0x1d, 0x9f, 0x93, 0x00, 0x62, 0x91, 0x26, 0x21, 0xa7, 0xdd, 0x25, 0x0f, 0x09, 0x0d, 0x35, 0xad, 0xcf, 0x11, 0x8e, 0x6e, 0xe8, 0xae, 0x1d, 0x95, 0xcb, 0x88, 0xf8, 0x70, 0x7b, 0x91, + /* (2^433)P */ 0x0c, 0x19, 0x5c, 0xd9, 0x8d, 0xda, 0x9d, 0x2c, 0x90, 0x54, 0x65, 0xe8, 0xb6, 0x35, 0x50, 0xae, 0xea, 0xae, 0x43, 0xb7, 0x1e, 0x99, 0x8b, 0x4c, 0x36, 0x4e, 0xe4, 0x1e, 0xc4, 0x64, 0x43, 0xb6, 0xeb, 0xd4, 0xe9, 0x60, 0x22, 0xee, 0xcf, 0xb8, 0x52, 0x1b, 0xf0, 0x04, 0xce, 0xbc, 0x2b, 0xf0, 0xbe, 0xcd, 0x44, 0x74, 0x1e, 0x1f, 0x63, 0xf9, + /* (2^434)P */ 0xe1, 0x3f, 0x95, 0x94, 0xb2, 0xb6, 0x31, 0xa9, 0x1b, 0xdb, 0xfd, 0x0e, 0xdb, 0xdd, 0x1a, 0x22, 0x78, 0x60, 0x9f, 0x75, 0x5f, 0x93, 0x06, 0x0c, 0xd8, 0xbb, 0xa2, 0x85, 0x2b, 0x5e, 0xc0, 0x9b, 0xa8, 0x5d, 0xaf, 0x93, 0x91, 0x91, 0x47, 0x41, 0x1a, 0xfc, 0xb4, 0x51, 0x85, 0xad, 0x69, 0x4d, 0x73, 0x69, 0xd5, 0x4e, 0x82, 0xfb, 0x66, 0xcb, + /* (2^435)P */ 0x7c, 0xbe, 0xc7, 0x51, 0xc4, 0x74, 0x6e, 0xab, 0xfd, 0x41, 0x4f, 0x76, 0x4f, 0x24, 0x03, 0xd6, 0x2a, 0xb7, 0x42, 0xb4, 0xda, 0x41, 0x2c, 0x82, 0x48, 0x4c, 0x7f, 0x6f, 0x25, 0x5d, 0x36, 0xd4, 0x69, 0xf5, 0xef, 0x02, 0x81, 0xea, 0x6f, 0x19, 0x69, 0xe8, 0x6f, 0x5b, 0x2f, 0x14, 0x0e, 0x6f, 0x89, 0xb4, 0xb5, 0xd8, 0xae, 0xef, 0x7b, 0x87, + /* (2^436)P */ 0xe9, 0x91, 0xa0, 0x8b, 0xc9, 0xe0, 0x01, 0x90, 0x37, 0xc1, 0x6f, 0xdc, 0x5e, 0xf7, 0xbf, 0x43, 0x00, 0xaa, 0x10, 0x76, 0x76, 0x18, 0x6e, 0x19, 0x1e, 0x94, 0x50, 0x11, 0x0a, 0xd1, 0xe2, 0xdb, 0x08, 0x21, 0xa0, 0x1f, 0xdb, 0x54, 0xfe, 0xea, 0x6e, 0xa3, 0x68, 0x56, 0x87, 0x0b, 0x22, 0x4e, 0x66, 0xf3, 0x82, 0x82, 0x00, 0xcd, 0xd4, 0x12, + /* (2^437)P */ 0x25, 0x8e, 0x24, 0x77, 0x64, 0x4c, 0xe0, 0xf8, 0x18, 0xc0, 0xdc, 0xc7, 0x1b, 0x35, 0x65, 0xde, 0x67, 0x41, 0x5e, 0x6f, 0x90, 0x82, 0xa7, 0x2e, 0x6d, 0xf1, 0x47, 0xb4, 0x92, 0x9c, 0xfd, 0x6a, 0x9a, 0x41, 0x36, 0x20, 0x24, 0x58, 0xc3, 0x59, 0x07, 0x9a, 0xfa, 0x9f, 0x03, 0xcb, 0xc7, 0x69, 0x37, 0x60, 0xe1, 0xab, 0x13, 0x72, 0xee, 0xa2, + /* (2^438)P */ 0x74, 0x78, 0xfb, 0x13, 0xcb, 0x8e, 0x37, 0x1a, 0xf6, 0x1d, 0x17, 0x83, 0x06, 0xd4, 0x27, 0x06, 0x21, 0xe8, 0xda, 0xdf, 0x6b, 0xf3, 0x83, 0x6b, 0x34, 0x8a, 0x8c, 0xee, 0x01, 0x05, 0x5b, 0xed, 0xd3, 0x1b, 0xc9, 0x64, 0x83, 0xc9, 0x49, 0xc2, 0x57, 0x1b, 0xdd, 0xcf, 0xf1, 0x9d, 0x63, 0xee, 0x1c, 0x0d, 0xa0, 0x0a, 0x73, 0x1f, 0x5b, 0x32, + /* (2^439)P */ 0x29, 0xce, 0x1e, 0xc0, 0x6a, 0xf5, 0xeb, 0x99, 0x5a, 0x39, 0x23, 0xe9, 0xdd, 0xac, 0x44, 0x88, 0xbc, 0x80, 0x22, 0xde, 0x2c, 0xcb, 0xa8, 0x3b, 0xff, 0xf7, 0x6f, 0xc7, 0x71, 0x72, 0xa8, 0xa3, 0xf6, 0x4d, 0xc6, 0x75, 0xda, 0x80, 0xdc, 0xd9, 0x30, 0xd9, 0x07, 0x50, 0x5a, 0x54, 0x7d, 0xda, 0x39, 0x6f, 0x78, 0x94, 0xbf, 0x25, 0x98, 0xdc, + /* (2^440)P */ 0x01, 0x26, 0x62, 0x44, 0xfb, 0x0f, 0x11, 0x72, 0x73, 0x0a, 0x16, 0xc7, 0x16, 0x9c, 0x9b, 0x37, 0xd8, 0xff, 0x4f, 0xfe, 0x57, 0xdb, 0xae, 0xef, 0x7d, 0x94, 0x30, 0x04, 0x70, 0x83, 0xde, 0x3c, 0xd4, 0xb5, 0x70, 0xda, 0xa7, 0x55, 0xc8, 0x19, 0xe1, 0x36, 0x15, 0x61, 0xe7, 0x3b, 0x7d, 0x85, 0xbb, 0xf3, 0x42, 0x5a, 0x94, 0xf4, 0x53, 0x2a, + /* (2^441)P */ 0x14, 0x60, 0xa6, 0x0b, 0x83, 0xe1, 0x23, 0x77, 0xc0, 0xce, 0x50, 0xed, 0x35, 0x8d, 0x98, 0x99, 0x7d, 0xf5, 0x8d, 0xce, 0x94, 0x25, 0xc8, 0x0f, 0x6d, 0xfa, 0x4a, 0xa4, 0x3a, 0x1f, 0x66, 0xfb, 0x5a, 0x64, 0xaf, 0x8b, 0x54, 0x54, 0x44, 0x3f, 0x5b, 0x88, 0x61, 0xe4, 0x48, 0x45, 0x26, 0x20, 0xbe, 0x0d, 0x06, 0xbb, 0x65, 0x59, 0xe1, 0x36, + /* (2^442)P */ 0xb7, 0x98, 0xce, 0xa3, 0xe3, 0xee, 0x11, 0x1b, 0x9e, 0x24, 0x59, 0x75, 0x31, 0x37, 0x44, 0x6f, 0x6b, 0x9e, 0xec, 0xb7, 0x44, 0x01, 0x7e, 0xab, 0xbb, 0x69, 0x5d, 0x11, 0xb0, 0x30, 0x64, 0xea, 0x91, 0xb4, 0x7a, 0x8c, 0x02, 0x4c, 0xb9, 0x10, 0xa7, 0xc7, 0x79, 0xe6, 0xdc, 0x77, 0xe3, 0xc8, 0xef, 0x3e, 0xf9, 0x38, 0x81, 0xce, 0x9a, 0xb2, + /* (2^443)P */ 0x91, 0x12, 0x76, 0xd0, 0x10, 0xb4, 0xaf, 0xe1, 0x89, 0x3a, 0x93, 0x6b, 0x5c, 0x19, 0x5f, 0x24, 0xed, 0x04, 0x92, 0xc7, 0xf0, 0x00, 0x08, 0xc1, 0x92, 0xff, 0x90, 0xdb, 0xb2, 0xbf, 0xdf, 0x49, 0xcd, 0xbd, 0x5c, 0x6e, 0xbf, 0x16, 0xbb, 0x61, 0xf9, 0x20, 0x33, 0x35, 0x93, 0x11, 0xbc, 0x59, 0x69, 0xce, 0x18, 0x9f, 0xf8, 0x7b, 0xa1, 0x6e, + /* (2^444)P */ 0xa1, 0xf4, 0xaf, 0xad, 0xf8, 0xe6, 0x99, 0xd2, 0xa1, 0x4d, 0xde, 0x56, 0xc9, 0x7b, 0x0b, 0x11, 0x3e, 0xbf, 0x89, 0x1a, 0x9a, 0x90, 0xe5, 0xe2, 0xa6, 0x37, 0x88, 0xa1, 0x68, 0x59, 0xae, 0x8c, 0xec, 0x02, 0x14, 0x8d, 0xb7, 0x2e, 0x25, 0x75, 0x7f, 0x76, 0x1a, 0xd3, 0x4d, 0xad, 0x8a, 0x00, 0x6c, 0x96, 0x49, 0xa4, 0xc3, 0x2e, 0x5c, 0x7b, + /* (2^445)P */ 0x26, 0x53, 0xf7, 0xda, 0xa8, 0x01, 0x14, 0xb1, 0x63, 0xe3, 0xc3, 0x89, 0x88, 0xb0, 0x85, 0x40, 0x2b, 0x26, 0x9a, 0x10, 0x1a, 0x70, 0x33, 0xf4, 0x50, 0x9d, 0x4d, 0xd8, 0x64, 0xc6, 0x0f, 0xe1, 0x17, 0xc8, 0x10, 0x4b, 0xfc, 0xa0, 0xc9, 0xba, 0x2c, 0x98, 0x09, 0xf5, 0x84, 0xb6, 0x7c, 0x4e, 0xa3, 0xe3, 0x81, 0x1b, 0x32, 0x60, 0x02, 0xdd, + /* (2^446)P */ 0xa3, 0xe5, 0x86, 0xd4, 0x43, 0xa8, 0xd1, 0x98, 0x9d, 0x9d, 0xdb, 0x04, 0xcf, 0x6e, 0x35, 0x05, 0x30, 0x53, 0x3b, 0xbc, 0x90, 0x00, 0x4a, 0xc5, 0x40, 0x2a, 0x0f, 0xde, 0x1a, 0xd7, 0x36, 0x27, 0x44, 0x62, 0xa6, 0xac, 0x9d, 0xd2, 0x70, 0x69, 0x14, 0x39, 0x9b, 0xd1, 0xc3, 0x0a, 0x3a, 0x82, 0x0e, 0xf1, 0x94, 0xd7, 0x42, 0x94, 0xd5, 0x7d, + /* (2^447)P */ 0x04, 0xc0, 0x6e, 0x12, 0x90, 0x70, 0xf9, 0xdf, 0xf7, 0xc9, 0x86, 0xc0, 0xe6, 0x92, 0x8b, 0x0a, 0xa1, 0xc1, 0x3b, 0xcc, 0x33, 0xb7, 0xf0, 0xeb, 0x51, 0x50, 0x80, 0x20, 0x69, 0x1c, 0x4f, 0x89, 0x05, 0x1e, 0xe4, 0x7a, 0x0a, 0xc2, 0xf0, 0xf5, 0x78, 0x91, 0x76, 0x34, 0x45, 0xdc, 0x24, 0x53, 0x24, 0x98, 0xe2, 0x73, 0x6f, 0xe6, 0x46, 0x67, +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go new file mode 100644 index 00000000000..b6b236e5d3d --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go @@ -0,0 +1,71 @@ +package goldilocks + +import fp "github.com/cloudflare/circl/math/fp448" + +var ( + // genX is the x-coordinate of the generator of Goldilocks curve. + genX = fp.Elt{ + 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, + 0x8e, 0x93, 0x00, 0x8b, 0xe1, 0x80, 0x3b, 0x43, + 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12, + 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, + 0x67, 0x17, 0x0f, 0x47, 0x70, 0x65, 0x14, 0x9e, + 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22, + 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, + } + // genY is the y-coordinate of the generator of Goldilocks curve. + genY = fp.Elt{ + 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, + 0xad, 0xc8, 0xd7, 0x4e, 0x2c, 0x13, 0xbd, 0xfd, + 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a, + 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, + 0x40, 0x98, 0xa3, 0x6c, 0x73, 0x73, 0xea, 0x4b, + 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88, + 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, + } + // paramD is -39081 in Fp. + paramD = fp.Elt{ + 0x56, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + } + // order is 2^446-0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d, + // which is the number of points in the prime subgroup. + order = Scalar{ + 0xf3, 0x44, 0x58, 0xab, 0x92, 0xc2, 0x78, 0x23, + 0x55, 0x8f, 0xc5, 0x8d, 0x72, 0xc2, 0x6c, 0x21, + 0x90, 0x36, 0xd6, 0xae, 0x49, 0xdb, 0x4e, 0xc4, + 0xe9, 0x23, 0xca, 0x7c, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + } + // residue448 is 2^448 mod order. + residue448 = [4]uint64{ + 0x721cf5b5529eec34, 0x7a4cf635c8e9c2ab, 0xeec492d944a725bf, 0x20cd77058, + } + // invFour is 1/4 mod order. + invFour = Scalar{ + 0x3d, 0x11, 0xd6, 0xaa, 0xa4, 0x30, 0xde, 0x48, + 0xd5, 0x63, 0x71, 0xa3, 0x9c, 0x30, 0x5b, 0x08, + 0xa4, 0x8d, 0xb5, 0x6b, 0xd2, 0xb6, 0x13, 0x71, + 0xfa, 0x88, 0x32, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, + } + // paramDTwist is -39082 in Fp. The D parameter of the twist curve. + paramDTwist = fp.Elt{ + 0x55, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + } +) diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go new file mode 100644 index 00000000000..5a939100d2c --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go @@ -0,0 +1,80 @@ +// Package goldilocks provides elliptic curve operations over the goldilocks curve. +package goldilocks + +import fp "github.com/cloudflare/circl/math/fp448" + +// Curve is the Goldilocks curve x^2+y^2=z^2-39081x^2y^2. +type Curve struct{} + +// Identity returns the identity point. +func (Curve) Identity() *Point { + return &Point{ + y: fp.One(), + z: fp.One(), + } +} + +// IsOnCurve returns true if the point lies on the curve. +func (Curve) IsOnCurve(P *Point) bool { + x2, y2, t, t2, z2 := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{} + rhs, lhs := &fp.Elt{}, &fp.Elt{} + fp.Mul(t, &P.ta, &P.tb) // t = ta*tb + fp.Sqr(x2, &P.x) // x^2 + fp.Sqr(y2, &P.y) // y^2 + fp.Sqr(z2, &P.z) // z^2 + fp.Sqr(t2, t) // t^2 + fp.Add(lhs, x2, y2) // x^2 + y^2 + fp.Mul(rhs, t2, ¶mD) // dt^2 + fp.Add(rhs, rhs, z2) // z^2 + dt^2 + fp.Sub(lhs, lhs, rhs) // x^2 + y^2 - (z^2 + dt^2) + eq0 := fp.IsZero(lhs) + + fp.Mul(lhs, &P.x, &P.y) // xy + fp.Mul(rhs, t, &P.z) // tz + fp.Sub(lhs, lhs, rhs) // xy - tz + eq1 := fp.IsZero(lhs) + return eq0 && eq1 +} + +// Generator returns the generator point. +func (Curve) Generator() *Point { + return &Point{ + x: genX, + y: genY, + z: fp.One(), + ta: genX, + tb: genY, + } +} + +// Order returns the number of points in the prime subgroup. +func (Curve) Order() Scalar { return order } + +// Double returns 2P. +func (Curve) Double(P *Point) *Point { R := *P; R.Double(); return &R } + +// Add returns P+Q. +func (Curve) Add(P, Q *Point) *Point { R := *P; R.Add(Q); return &R } + +// ScalarMult returns kP. This function runs in constant time. +func (e Curve) ScalarMult(k *Scalar, P *Point) *Point { + k4 := &Scalar{} + k4.divBy4(k) + return e.pull(twistCurve{}.ScalarMult(k4, e.push(P))) +} + +// ScalarBaseMult returns kG where G is the generator point. This function runs in constant time. +func (e Curve) ScalarBaseMult(k *Scalar) *Point { + k4 := &Scalar{} + k4.divBy4(k) + return e.pull(twistCurve{}.ScalarBaseMult(k4)) +} + +// CombinedMult returns mG+nP, where G is the generator point. This function is non-constant time. +func (e Curve) CombinedMult(m, n *Scalar, P *Point) *Point { + m4 := &Scalar{} + n4 := &Scalar{} + m4.divBy4(m) + n4.divBy4(n) + return e.pull(twistCurve{}.CombinedMult(m4, n4, twistCurve{}.pull(P))) +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go new file mode 100644 index 00000000000..b1daab851c5 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go @@ -0,0 +1,52 @@ +package goldilocks + +import fp "github.com/cloudflare/circl/math/fp448" + +func (Curve) pull(P *twistPoint) *Point { return twistCurve{}.push(P) } +func (twistCurve) pull(P *Point) *twistPoint { return Curve{}.push(P) } + +// push sends a point on the Goldilocks curve to a point on the twist curve. +func (Curve) push(P *Point) *twistPoint { + Q := &twistPoint{} + Px, Py, Pz := &P.x, &P.y, &P.z + a, b, c, d, e, f, g, h := &Q.x, &Q.y, &Q.z, &fp.Elt{}, &Q.ta, &Q.x, &Q.y, &Q.tb + fp.Add(e, Px, Py) // x+y + fp.Sqr(a, Px) // A = x^2 + fp.Sqr(b, Py) // B = y^2 + fp.Sqr(c, Pz) // z^2 + fp.Add(c, c, c) // C = 2*z^2 + *d = *a // D = A + fp.Sqr(e, e) // (x+y)^2 + fp.Sub(e, e, a) // (x+y)^2-A + fp.Sub(e, e, b) // E = (x+y)^2-A-B + fp.Add(h, b, d) // H = B+D + fp.Sub(g, b, d) // G = B-D + fp.Sub(f, c, h) // F = C-H + fp.Mul(&Q.z, f, g) // Z = F * G + fp.Mul(&Q.x, e, f) // X = E * F + fp.Mul(&Q.y, g, h) // Y = G * H, // T = E * H + return Q +} + +// push sends a point on the twist curve to a point on the Goldilocks curve. +func (twistCurve) push(P *twistPoint) *Point { + Q := &Point{} + Px, Py, Pz := &P.x, &P.y, &P.z + a, b, c, d, e, f, g, h := &Q.x, &Q.y, &Q.z, &fp.Elt{}, &Q.ta, &Q.x, &Q.y, &Q.tb + fp.Add(e, Px, Py) // x+y + fp.Sqr(a, Px) // A = x^2 + fp.Sqr(b, Py) // B = y^2 + fp.Sqr(c, Pz) // z^2 + fp.Add(c, c, c) // C = 2*z^2 + fp.Neg(d, a) // D = -A + fp.Sqr(e, e) // (x+y)^2 + fp.Sub(e, e, a) // (x+y)^2-A + fp.Sub(e, e, b) // E = (x+y)^2-A-B + fp.Add(h, b, d) // H = B+D + fp.Sub(g, b, d) // G = B-D + fp.Sub(f, c, h) // F = C-H + fp.Mul(&Q.z, f, g) // Z = F * G + fp.Mul(&Q.x, e, f) // X = E * F + fp.Mul(&Q.y, g, h) // Y = G * H, // T = E * H + return Q +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go new file mode 100644 index 00000000000..11f73de0542 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go @@ -0,0 +1,171 @@ +package goldilocks + +import ( + "errors" + "fmt" + + fp "github.com/cloudflare/circl/math/fp448" +) + +// Point is a point on the Goldilocks Curve. +type Point struct{ x, y, z, ta, tb fp.Elt } + +func (P Point) String() string { + return fmt.Sprintf("x: %v\ny: %v\nz: %v\nta: %v\ntb: %v", P.x, P.y, P.z, P.ta, P.tb) +} + +// FromAffine creates a point from affine coordinates. +func FromAffine(x, y *fp.Elt) (*Point, error) { + P := &Point{ + x: *x, + y: *y, + z: fp.One(), + ta: *x, + tb: *y, + } + if !(Curve{}).IsOnCurve(P) { + return P, errors.New("point not on curve") + } + return P, nil +} + +// isLessThan returns true if 0 <= x < y, and assumes that slices are of the +// same length and are interpreted in little-endian order. +func isLessThan(x, y []byte) bool { + i := len(x) - 1 + for i > 0 && x[i] == y[i] { + i-- + } + return x[i] < y[i] +} + +// FromBytes returns a point from the input buffer. +func FromBytes(in []byte) (*Point, error) { + if len(in) < fp.Size+1 { + return nil, errors.New("wrong input length") + } + err := errors.New("invalid decoding") + P := &Point{} + signX := in[fp.Size] >> 7 + copy(P.y[:], in[:fp.Size]) + p := fp.P() + if !isLessThan(P.y[:], p[:]) { + return nil, err + } + + u, v := &fp.Elt{}, &fp.Elt{} + one := fp.One() + fp.Sqr(u, &P.y) // u = y^2 + fp.Mul(v, u, ¶mD) // v = dy^2 + fp.Sub(u, u, &one) // u = y^2-1 + fp.Sub(v, v, &one) // v = dy^2-1 + isQR := fp.InvSqrt(&P.x, u, v) // x = sqrt(u/v) + if !isQR { + return nil, err + } + fp.Modp(&P.x) // x = x mod p + if fp.IsZero(&P.x) && signX == 1 { + return nil, err + } + if signX != (P.x[0] & 1) { + fp.Neg(&P.x, &P.x) + } + P.ta = P.x + P.tb = P.y + P.z = fp.One() + return P, nil +} + +// IsIdentity returns true is P is the identity Point. +func (P *Point) IsIdentity() bool { + return fp.IsZero(&P.x) && !fp.IsZero(&P.y) && !fp.IsZero(&P.z) && P.y == P.z +} + +// IsEqual returns true if P is equivalent to Q. +func (P *Point) IsEqual(Q *Point) bool { + l, r := &fp.Elt{}, &fp.Elt{} + fp.Mul(l, &P.x, &Q.z) + fp.Mul(r, &Q.x, &P.z) + fp.Sub(l, l, r) + b := fp.IsZero(l) + fp.Mul(l, &P.y, &Q.z) + fp.Mul(r, &Q.y, &P.z) + fp.Sub(l, l, r) + b = b && fp.IsZero(l) + fp.Mul(l, &P.ta, &P.tb) + fp.Mul(l, l, &Q.z) + fp.Mul(r, &Q.ta, &Q.tb) + fp.Mul(r, r, &P.z) + fp.Sub(l, l, r) + b = b && fp.IsZero(l) + return b +} + +// Neg obtains the inverse of the Point. +func (P *Point) Neg() { fp.Neg(&P.x, &P.x); fp.Neg(&P.ta, &P.ta) } + +// ToAffine returns the x,y affine coordinates of P. +func (P *Point) ToAffine() (x, y fp.Elt) { + fp.Inv(&P.z, &P.z) // 1/z + fp.Mul(&P.x, &P.x, &P.z) // x/z + fp.Mul(&P.y, &P.y, &P.z) // y/z + fp.Modp(&P.x) + fp.Modp(&P.y) + fp.SetOne(&P.z) + P.ta = P.x + P.tb = P.y + return P.x, P.y +} + +// ToBytes stores P into a slice of bytes. +func (P *Point) ToBytes(out []byte) error { + if len(out) < fp.Size+1 { + return errors.New("invalid decoding") + } + x, y := P.ToAffine() + out[fp.Size] = (x[0] & 1) << 7 + return fp.ToBytes(out[:fp.Size], &y) +} + +// MarshalBinary encodes the receiver into a binary form and returns the result. +func (P *Point) MarshalBinary() (data []byte, err error) { + data = make([]byte, fp.Size+1) + err = P.ToBytes(data[:fp.Size+1]) + return data, err +} + +// UnmarshalBinary must be able to decode the form generated by MarshalBinary. +func (P *Point) UnmarshalBinary(data []byte) error { Q, err := FromBytes(data); *P = *Q; return err } + +// Double sets P = 2Q. +func (P *Point) Double() { P.Add(P) } + +// Add sets P =P+Q.. +func (P *Point) Add(Q *Point) { + // This is formula (5) from "Twisted Edwards Curves Revisited" by + // Hisil H., Wong K.KH., Carter G., Dawson E. (2008) + // https://doi.org/10.1007/978-3-540-89255-7_20 + x1, y1, z1, ta1, tb1 := &P.x, &P.y, &P.z, &P.ta, &P.tb + x2, y2, z2, ta2, tb2 := &Q.x, &Q.y, &Q.z, &Q.ta, &Q.tb + x3, y3, z3, E, H := &P.x, &P.y, &P.z, &P.ta, &P.tb + A, B, C, D := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{} + t1, t2, F, G := C, D, &fp.Elt{}, &fp.Elt{} + fp.Mul(t1, ta1, tb1) // t1 = ta1*tb1 + fp.Mul(t2, ta2, tb2) // t2 = ta2*tb2 + fp.Mul(A, x1, x2) // A = x1*x2 + fp.Mul(B, y1, y2) // B = y1*y2 + fp.Mul(C, t1, t2) // t1*t2 + fp.Mul(C, C, ¶mD) // C = d*t1*t2 + fp.Mul(D, z1, z2) // D = z1*z2 + fp.Add(F, x1, y1) // x1+y1 + fp.Add(E, x2, y2) // x2+y2 + fp.Mul(E, E, F) // (x1+y1)*(x2+y2) + fp.Sub(E, E, A) // (x1+y1)*(x2+y2)-A + fp.Sub(E, E, B) // E = (x1+y1)*(x2+y2)-A-B + fp.Sub(F, D, C) // F = D-C + fp.Add(G, D, C) // G = D+C + fp.Sub(H, B, A) // H = B-A + fp.Mul(z3, F, G) // Z = F * G + fp.Mul(x3, E, F) // X = E * F + fp.Mul(y3, G, H) // Y = G * H, T = E * H +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go new file mode 100644 index 00000000000..f98117b2527 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go @@ -0,0 +1,203 @@ +package goldilocks + +import ( + "encoding/binary" + "math/bits" +) + +// ScalarSize is the size (in bytes) of scalars. +const ScalarSize = 56 // 448 / 8 + +// _N is the number of 64-bit words to store scalars. +const _N = 7 // 448 / 64 + +// Scalar represents a positive integer stored in little-endian order. +type Scalar [ScalarSize]byte + +type scalar64 [_N]uint64 + +func (z *scalar64) fromScalar(x *Scalar) { + z[0] = binary.LittleEndian.Uint64(x[0*8 : 1*8]) + z[1] = binary.LittleEndian.Uint64(x[1*8 : 2*8]) + z[2] = binary.LittleEndian.Uint64(x[2*8 : 3*8]) + z[3] = binary.LittleEndian.Uint64(x[3*8 : 4*8]) + z[4] = binary.LittleEndian.Uint64(x[4*8 : 5*8]) + z[5] = binary.LittleEndian.Uint64(x[5*8 : 6*8]) + z[6] = binary.LittleEndian.Uint64(x[6*8 : 7*8]) +} + +func (z *scalar64) toScalar(x *Scalar) { + binary.LittleEndian.PutUint64(x[0*8:1*8], z[0]) + binary.LittleEndian.PutUint64(x[1*8:2*8], z[1]) + binary.LittleEndian.PutUint64(x[2*8:3*8], z[2]) + binary.LittleEndian.PutUint64(x[3*8:4*8], z[3]) + binary.LittleEndian.PutUint64(x[4*8:5*8], z[4]) + binary.LittleEndian.PutUint64(x[5*8:6*8], z[5]) + binary.LittleEndian.PutUint64(x[6*8:7*8], z[6]) +} + +// add calculates z = x + y. Assumes len(z) > max(len(x),len(y)). +func add(z, x, y []uint64) uint64 { + l, L, zz := len(x), len(y), y + if l > L { + l, L, zz = L, l, x + } + c := uint64(0) + for i := 0; i < l; i++ { + z[i], c = bits.Add64(x[i], y[i], c) + } + for i := l; i < L; i++ { + z[i], c = bits.Add64(zz[i], 0, c) + } + return c +} + +// sub calculates z = x - y. Assumes len(z) > max(len(x),len(y)). +func sub(z, x, y []uint64) uint64 { + l, L, zz := len(x), len(y), y + if l > L { + l, L, zz = L, l, x + } + c := uint64(0) + for i := 0; i < l; i++ { + z[i], c = bits.Sub64(x[i], y[i], c) + } + for i := l; i < L; i++ { + z[i], c = bits.Sub64(zz[i], 0, c) + } + return c +} + +// mulWord calculates z = x * y. Assumes len(z) >= len(x)+1. +func mulWord(z, x []uint64, y uint64) { + for i := range z { + z[i] = 0 + } + carry := uint64(0) + for i := range x { + hi, lo := bits.Mul64(x[i], y) + lo, cc := bits.Add64(lo, z[i], 0) + hi, _ = bits.Add64(hi, 0, cc) + z[i], cc = bits.Add64(lo, carry, 0) + carry, _ = bits.Add64(hi, 0, cc) + } + z[len(x)] = carry +} + +// Cmov moves x into z if b=1. +func (z *scalar64) Cmov(b uint64, x *scalar64) { + m := uint64(0) - b + for i := range z { + z[i] = (z[i] &^ m) | (x[i] & m) + } +} + +// leftShift shifts to the left the words of z returning the more significant word. +func (z *scalar64) leftShift(low uint64) uint64 { + high := z[_N-1] + for i := _N - 1; i > 0; i-- { + z[i] = z[i-1] + } + z[0] = low + return high +} + +// reduceOneWord calculates z = z + 2^448*x such that the result fits in a Scalar. +func (z *scalar64) reduceOneWord(x uint64) { + prod := (&scalar64{})[:] + mulWord(prod, residue448[:], x) + cc := add(z[:], z[:], prod) + mulWord(prod, residue448[:], cc) + add(z[:], z[:], prod) +} + +// modOrder reduces z mod order. +func (z *scalar64) modOrder() { + var o64, x scalar64 + o64.fromScalar(&order) + // Performs: while (z >= order) { z = z-order } + // At most 8 (eight) iterations reduce 3 bits by subtracting. + for i := 0; i < 8; i++ { + c := sub(x[:], z[:], o64[:]) // (c || x) = z-order + z.Cmov(1-c, &x) // if c != 0 { z = x } + } +} + +// FromBytes stores z = x mod order, where x is a number stored in little-endian order. +func (z *Scalar) FromBytes(x []byte) { + n := len(x) + nCeil := (n + 7) >> 3 + for i := range z { + z[i] = 0 + } + if nCeil < _N { + copy(z[:], x) + return + } + copy(z[:], x[8*(nCeil-_N):]) + var z64 scalar64 + z64.fromScalar(z) + for i := nCeil - _N - 1; i >= 0; i-- { + low := binary.LittleEndian.Uint64(x[8*i:]) + high := z64.leftShift(low) + z64.reduceOneWord(high) + } + z64.modOrder() + z64.toScalar(z) +} + +// divBy4 calculates z = x/4 mod order. +func (z *Scalar) divBy4(x *Scalar) { z.Mul(x, &invFour) } + +// Red reduces z mod order. +func (z *Scalar) Red() { var t scalar64; t.fromScalar(z); t.modOrder(); t.toScalar(z) } + +// Neg calculates z = -z mod order. +func (z *Scalar) Neg() { z.Sub(&order, z) } + +// Add calculates z = x+y mod order. +func (z *Scalar) Add(x, y *Scalar) { + var z64, x64, y64, t scalar64 + x64.fromScalar(x) + y64.fromScalar(y) + c := add(z64[:], x64[:], y64[:]) + add(t[:], z64[:], residue448[:]) + z64.Cmov(c, &t) + z64.modOrder() + z64.toScalar(z) +} + +// Sub calculates z = x-y mod order. +func (z *Scalar) Sub(x, y *Scalar) { + var z64, x64, y64, t scalar64 + x64.fromScalar(x) + y64.fromScalar(y) + c := sub(z64[:], x64[:], y64[:]) + sub(t[:], z64[:], residue448[:]) + z64.Cmov(c, &t) + z64.modOrder() + z64.toScalar(z) +} + +// Mul calculates z = x*y mod order. +func (z *Scalar) Mul(x, y *Scalar) { + var z64, x64, y64 scalar64 + prod := (&[_N + 1]uint64{})[:] + x64.fromScalar(x) + y64.fromScalar(y) + mulWord(prod, x64[:], y64[_N-1]) + copy(z64[:], prod[:_N]) + z64.reduceOneWord(prod[_N]) + for i := _N - 2; i >= 0; i-- { + h := z64.leftShift(0) + z64.reduceOneWord(h) + mulWord(prod, x64[:], y64[i]) + c := add(z64[:], z64[:], prod[:_N]) + z64.reduceOneWord(prod[_N] + c) + } + z64.modOrder() + z64.toScalar(z) +} + +// IsZero returns true if z=0. +func (z *Scalar) IsZero() bool { z.Red(); return *z == Scalar{} } diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go new file mode 100644 index 00000000000..83d7cdadd3e --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go @@ -0,0 +1,138 @@ +package goldilocks + +import ( + "crypto/subtle" + "math/bits" + + "github.com/cloudflare/circl/internal/conv" + "github.com/cloudflare/circl/math" + fp "github.com/cloudflare/circl/math/fp448" +) + +// twistCurve is -x^2+y^2=1-39082x^2y^2 and is 4-isogenous to Goldilocks. +type twistCurve struct{} + +// Identity returns the identity point. +func (twistCurve) Identity() *twistPoint { + return &twistPoint{ + y: fp.One(), + z: fp.One(), + } +} + +// subYDiv16 update x = (x - y) / 16. +func subYDiv16(x *scalar64, y int64) { + s := uint64(y >> 63) + x0, b0 := bits.Sub64((*x)[0], uint64(y), 0) + x1, b1 := bits.Sub64((*x)[1], s, b0) + x2, b2 := bits.Sub64((*x)[2], s, b1) + x3, b3 := bits.Sub64((*x)[3], s, b2) + x4, b4 := bits.Sub64((*x)[4], s, b3) + x5, b5 := bits.Sub64((*x)[5], s, b4) + x6, _ := bits.Sub64((*x)[6], s, b5) + x[0] = (x0 >> 4) | (x1 << 60) + x[1] = (x1 >> 4) | (x2 << 60) + x[2] = (x2 >> 4) | (x3 << 60) + x[3] = (x3 >> 4) | (x4 << 60) + x[4] = (x4 >> 4) | (x5 << 60) + x[5] = (x5 >> 4) | (x6 << 60) + x[6] = (x6 >> 4) +} + +func recodeScalar(d *[113]int8, k *Scalar) { + var k64 scalar64 + k64.fromScalar(k) + for i := 0; i < 112; i++ { + d[i] = int8((k64[0] & 0x1f) - 16) + subYDiv16(&k64, int64(d[i])) + } + d[112] = int8(k64[0]) +} + +// ScalarMult returns kP. +func (e twistCurve) ScalarMult(k *Scalar, P *twistPoint) *twistPoint { + var TabP [8]preTwistPointProy + var S preTwistPointProy + var d [113]int8 + + var isZero int + if k.IsZero() { + isZero = 1 + } + subtle.ConstantTimeCopy(isZero, k[:], order[:]) + + minusK := *k + isEven := 1 - int(k[0]&0x1) + minusK.Neg() + subtle.ConstantTimeCopy(isEven, k[:], minusK[:]) + recodeScalar(&d, k) + + P.oddMultiples(TabP[:]) + Q := e.Identity() + for i := 112; i >= 0; i-- { + Q.Double() + Q.Double() + Q.Double() + Q.Double() + mask := d[i] >> 7 + absDi := (d[i] + mask) ^ mask + inx := int32((absDi - 1) >> 1) + sig := int((d[i] >> 7) & 0x1) + for j := range TabP { + S.cmov(&TabP[j], uint(subtle.ConstantTimeEq(inx, int32(j)))) + } + S.cneg(sig) + Q.mixAdd(&S) + } + Q.cneg(uint(isEven)) + return Q +} + +const ( + omegaFix = 7 + omegaVar = 5 +) + +// CombinedMult returns mG+nP. +func (e twistCurve) CombinedMult(m, n *Scalar, P *twistPoint) *twistPoint { + nafFix := math.OmegaNAF(conv.BytesLe2BigInt(m[:]), omegaFix) + nafVar := math.OmegaNAF(conv.BytesLe2BigInt(n[:]), omegaVar) + + if len(nafFix) > len(nafVar) { + nafVar = append(nafVar, make([]int32, len(nafFix)-len(nafVar))...) + } else if len(nafFix) < len(nafVar) { + nafFix = append(nafFix, make([]int32, len(nafVar)-len(nafFix))...) + } + + var TabQ [1 << (omegaVar - 2)]preTwistPointProy + P.oddMultiples(TabQ[:]) + Q := e.Identity() + for i := len(nafFix) - 1; i >= 0; i-- { + Q.Double() + // Generator point + if nafFix[i] != 0 { + idxM := absolute(nafFix[i]) >> 1 + R := tabVerif[idxM] + if nafFix[i] < 0 { + R.neg() + } + Q.mixAddZ1(&R) + } + // Variable input point + if nafVar[i] != 0 { + idxN := absolute(nafVar[i]) >> 1 + S := TabQ[idxN] + if nafVar[i] < 0 { + S.neg() + } + Q.mixAdd(&S) + } + } + return Q +} + +// absolute returns always a positive value. +func absolute(x int32) int32 { + mask := x >> 31 + return (x + mask) ^ mask +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go new file mode 100644 index 00000000000..c55db77b069 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go @@ -0,0 +1,135 @@ +package goldilocks + +import ( + "fmt" + + fp "github.com/cloudflare/circl/math/fp448" +) + +type twistPoint struct{ x, y, z, ta, tb fp.Elt } + +type preTwistPointAffine struct{ addYX, subYX, dt2 fp.Elt } + +type preTwistPointProy struct { + preTwistPointAffine + z2 fp.Elt +} + +func (P *twistPoint) String() string { + return fmt.Sprintf("x: %v\ny: %v\nz: %v\nta: %v\ntb: %v", P.x, P.y, P.z, P.ta, P.tb) +} + +// cneg conditionally negates the point if b=1. +func (P *twistPoint) cneg(b uint) { + t := &fp.Elt{} + fp.Neg(t, &P.x) + fp.Cmov(&P.x, t, b) + fp.Neg(t, &P.ta) + fp.Cmov(&P.ta, t, b) +} + +// Double updates P with 2P. +func (P *twistPoint) Double() { + // This is formula (7) from "Twisted Edwards Curves Revisited" by + // Hisil H., Wong K.KH., Carter G., Dawson E. (2008) + // https://doi.org/10.1007/978-3-540-89255-7_20 + Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb + a, b, c, e, f, g, h := Px, Py, Pz, Pta, Px, Py, Ptb + fp.Add(e, Px, Py) // x+y + fp.Sqr(a, Px) // A = x^2 + fp.Sqr(b, Py) // B = y^2 + fp.Sqr(c, Pz) // z^2 + fp.Add(c, c, c) // C = 2*z^2 + fp.Add(h, a, b) // H = A+B + fp.Sqr(e, e) // (x+y)^2 + fp.Sub(e, e, h) // E = (x+y)^2-A-B + fp.Sub(g, b, a) // G = B-A + fp.Sub(f, c, g) // F = C-G + fp.Mul(Pz, f, g) // Z = F * G + fp.Mul(Px, e, f) // X = E * F + fp.Mul(Py, g, h) // Y = G * H, T = E * H +} + +// mixAdd calculates P= P+Q, where Q is a precomputed point with Z_Q = 1. +func (P *twistPoint) mixAddZ1(Q *preTwistPointAffine) { + fp.Add(&P.z, &P.z, &P.z) // D = 2*z1 (z2=1) + P.coreAddition(Q) +} + +// coreAddition calculates P=P+Q for curves with A=-1. +func (P *twistPoint) coreAddition(Q *preTwistPointAffine) { + // This is the formula following (5) from "Twisted Edwards Curves Revisited" by + // Hisil H., Wong K.KH., Carter G., Dawson E. (2008) + // https://doi.org/10.1007/978-3-540-89255-7_20 + Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb + addYX2, subYX2, dt2 := &Q.addYX, &Q.subYX, &Q.dt2 + a, b, c, d, e, f, g, h := Px, Py, &fp.Elt{}, Pz, Pta, Px, Py, Ptb + fp.Mul(c, Pta, Ptb) // t1 = ta*tb + fp.Sub(h, Py, Px) // y1-x1 + fp.Add(b, Py, Px) // y1+x1 + fp.Mul(a, h, subYX2) // A = (y1-x1)*(y2-x2) + fp.Mul(b, b, addYX2) // B = (y1+x1)*(y2+x2) + fp.Mul(c, c, dt2) // C = 2*D*t1*t2 + fp.Sub(e, b, a) // E = B-A + fp.Add(h, b, a) // H = B+A + fp.Sub(f, d, c) // F = D-C + fp.Add(g, d, c) // G = D+C + fp.Mul(Pz, f, g) // Z = F * G + fp.Mul(Px, e, f) // X = E * F + fp.Mul(Py, g, h) // Y = G * H, T = E * H +} + +func (P *preTwistPointAffine) neg() { + P.addYX, P.subYX = P.subYX, P.addYX + fp.Neg(&P.dt2, &P.dt2) +} + +func (P *preTwistPointAffine) cneg(b int) { + t := &fp.Elt{} + fp.Cswap(&P.addYX, &P.subYX, uint(b)) + fp.Neg(t, &P.dt2) + fp.Cmov(&P.dt2, t, uint(b)) +} + +func (P *preTwistPointAffine) cmov(Q *preTwistPointAffine, b uint) { + fp.Cmov(&P.addYX, &Q.addYX, b) + fp.Cmov(&P.subYX, &Q.subYX, b) + fp.Cmov(&P.dt2, &Q.dt2, b) +} + +// mixAdd calculates P= P+Q, where Q is a precomputed point with Z_Q != 1. +func (P *twistPoint) mixAdd(Q *preTwistPointProy) { + fp.Mul(&P.z, &P.z, &Q.z2) // D = 2*z1*z2 + P.coreAddition(&Q.preTwistPointAffine) +} + +// oddMultiples calculates T[i] = (2*i-1)P for 0 < i < len(T). +func (P *twistPoint) oddMultiples(T []preTwistPointProy) { + if n := len(T); n > 0 { + T[0].FromTwistPoint(P) + _2P := *P + _2P.Double() + R := &preTwistPointProy{} + R.FromTwistPoint(&_2P) + for i := 1; i < n; i++ { + P.mixAdd(R) + T[i].FromTwistPoint(P) + } + } +} + +// cmov conditionally moves Q into P if b=1. +func (P *preTwistPointProy) cmov(Q *preTwistPointProy, b uint) { + P.preTwistPointAffine.cmov(&Q.preTwistPointAffine, b) + fp.Cmov(&P.z2, &Q.z2, b) +} + +// FromTwistPoint precomputes some coordinates of Q for missed addition. +func (P *preTwistPointProy) FromTwistPoint(Q *twistPoint) { + fp.Add(&P.addYX, &Q.y, &Q.x) // addYX = X + Y + fp.Sub(&P.subYX, &Q.y, &Q.x) // subYX = Y - X + fp.Mul(&P.dt2, &Q.ta, &Q.tb) // T = ta*tb + fp.Mul(&P.dt2, &P.dt2, ¶mDTwist) // D*T + fp.Add(&P.dt2, &P.dt2, &P.dt2) // dt2 = 2*D*T + fp.Add(&P.z2, &Q.z, &Q.z) // z2 = 2*Z +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go new file mode 100644 index 00000000000..ed432e02c78 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go @@ -0,0 +1,216 @@ +package goldilocks + +import fp "github.com/cloudflare/circl/math/fp448" + +var tabFixMult = [fxV][fx2w1]preTwistPointAffine{ + { + { + addYX: fp.Elt{0x65, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2b, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, + subYX: fp.Elt{0x64, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2d, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, + dt2: fp.Elt{0x1a, 0x33, 0xea, 0x64, 0x45, 0x1c, 0xdf, 0x17, 0x1d, 0x16, 0x34, 0x28, 0xd6, 0x61, 0x19, 0x67, 0x79, 0xb4, 0x13, 0xcf, 0x3e, 0x7c, 0x0e, 0x72, 0xda, 0xf1, 0x5f, 0xda, 0xe6, 0xcf, 0x42, 0xd3, 0xb6, 0x17, 0xc2, 0x68, 0x13, 0x2d, 0xd9, 0x60, 0x3e, 0xae, 0xf0, 0x5b, 0x96, 0xf0, 0xcd, 0xaf, 0xea, 0xb7, 0x0d, 0x59, 0x16, 0xa7, 0xff, 0x55}, + }, + { + addYX: fp.Elt{0xca, 0xd8, 0x7d, 0x86, 0x1a, 0xef, 0xad, 0x11, 0xe3, 0x27, 0x41, 0x7e, 0x7f, 0x3e, 0xa9, 0xd2, 0xb5, 0x4e, 0x50, 0xe0, 0x77, 0x91, 0xc2, 0x13, 0x52, 0x73, 0x41, 0x09, 0xa6, 0x57, 0x9a, 0xc8, 0xa8, 0x90, 0x9d, 0x26, 0x14, 0xbb, 0xa1, 0x2a, 0xf7, 0x45, 0x43, 0x4e, 0xea, 0x35, 0x62, 0xe1, 0x08, 0x85, 0x46, 0xb8, 0x24, 0x05, 0x2d, 0xab}, + subYX: fp.Elt{0x9b, 0xe6, 0xd3, 0xe5, 0xfe, 0x50, 0x36, 0x3c, 0x3c, 0x6d, 0x74, 0x1d, 0x74, 0xc0, 0xde, 0x5b, 0x45, 0x27, 0xe5, 0x12, 0xee, 0x63, 0x35, 0x6b, 0x13, 0xe2, 0x41, 0x6b, 0x3a, 0x05, 0x2b, 0xb1, 0x89, 0x26, 0xb6, 0xc6, 0xd1, 0x84, 0xff, 0x0e, 0x9b, 0xa3, 0xfb, 0x21, 0x36, 0x6b, 0x01, 0xf7, 0x9f, 0x7c, 0xeb, 0xf5, 0x18, 0x7a, 0x2a, 0x70}, + dt2: fp.Elt{0x09, 0xad, 0x99, 0x1a, 0x38, 0xd3, 0xdf, 0x22, 0x37, 0x32, 0x61, 0x8b, 0xf3, 0x19, 0x48, 0x08, 0xe8, 0x49, 0xb6, 0x4a, 0xa7, 0xed, 0xa4, 0xa2, 0xee, 0x86, 0xd7, 0x31, 0x5e, 0xce, 0x95, 0x76, 0x86, 0x42, 0x1c, 0x9d, 0x07, 0x14, 0x8c, 0x34, 0x18, 0x9c, 0x6d, 0x3a, 0xdf, 0xa9, 0xe8, 0x36, 0x7e, 0xe4, 0x95, 0xbe, 0xb5, 0x09, 0xf8, 0x9c}, + }, + { + addYX: fp.Elt{0x51, 0xdb, 0x49, 0xa8, 0x9f, 0xe3, 0xd7, 0xec, 0x0d, 0x0f, 0x49, 0xe8, 0xb6, 0xc5, 0x0f, 0x5a, 0x1c, 0xce, 0x54, 0x0d, 0xb1, 0x8d, 0x5b, 0xbf, 0xf4, 0xaa, 0x34, 0x77, 0xc4, 0x5d, 0x59, 0xb6, 0xc5, 0x0e, 0x5a, 0xd8, 0x5b, 0x30, 0xc2, 0x1d, 0xec, 0x85, 0x1c, 0x42, 0xbe, 0x24, 0x2e, 0x50, 0x55, 0x44, 0xb2, 0x3a, 0x01, 0xaa, 0x98, 0xfb}, + subYX: fp.Elt{0xe7, 0x29, 0xb7, 0xd0, 0xaa, 0x4f, 0x32, 0x53, 0x56, 0xde, 0xbc, 0xd1, 0x92, 0x5d, 0x19, 0xbe, 0xa3, 0xe3, 0x75, 0x48, 0xe0, 0x7a, 0x1b, 0x54, 0x7a, 0xb7, 0x41, 0x77, 0x84, 0x38, 0xdd, 0x14, 0x9f, 0xca, 0x3f, 0xa3, 0xc8, 0xa7, 0x04, 0x70, 0xf1, 0x4d, 0x3d, 0xb3, 0x84, 0x79, 0xcb, 0xdb, 0xe4, 0xc5, 0x42, 0x9b, 0x57, 0x19, 0xf1, 0x2d}, + dt2: fp.Elt{0x20, 0xb4, 0x94, 0x9e, 0xdf, 0x31, 0x44, 0x0b, 0xc9, 0x7b, 0x75, 0x40, 0x9d, 0xd1, 0x96, 0x39, 0x70, 0x71, 0x15, 0xc8, 0x93, 0xd5, 0xc5, 0xe5, 0xba, 0xfe, 0xee, 0x08, 0x6a, 0x98, 0x0a, 0x1b, 0xb2, 0xaa, 0x3a, 0xf4, 0xa4, 0x79, 0xf9, 0x8e, 0x4d, 0x65, 0x10, 0x9b, 0x3a, 0x6e, 0x7c, 0x87, 0x94, 0x92, 0x11, 0x65, 0xbf, 0x1a, 0x09, 0xde}, + }, + { + addYX: fp.Elt{0xf3, 0x84, 0x76, 0x77, 0xa5, 0x6b, 0x27, 0x3b, 0x83, 0x3d, 0xdf, 0xa0, 0xeb, 0x32, 0x6d, 0x58, 0x81, 0x57, 0x64, 0xc2, 0x21, 0x7c, 0x9b, 0xea, 0xe6, 0xb0, 0x93, 0xf9, 0xe7, 0xc3, 0xed, 0x5a, 0x8e, 0xe2, 0xb4, 0x72, 0x76, 0x66, 0x0f, 0x22, 0x29, 0x94, 0x3e, 0x63, 0x48, 0x5e, 0x80, 0xcb, 0xac, 0xfa, 0x95, 0xb6, 0x4b, 0xc4, 0x95, 0x33}, + subYX: fp.Elt{0x0c, 0x55, 0xd1, 0x5e, 0x5f, 0xbf, 0xbf, 0xe2, 0x4c, 0xfc, 0x37, 0x4a, 0xc4, 0xb1, 0xf4, 0x83, 0x61, 0x93, 0x60, 0x8e, 0x9f, 0x31, 0xf0, 0xa0, 0x41, 0xff, 0x1d, 0xe2, 0x7f, 0xca, 0x40, 0xd6, 0x88, 0xe8, 0x91, 0x61, 0xe2, 0x11, 0x18, 0x83, 0xf3, 0x25, 0x2f, 0x3f, 0x49, 0x40, 0xd4, 0x83, 0xe2, 0xd7, 0x74, 0x6a, 0x16, 0x86, 0x4e, 0xab}, + dt2: fp.Elt{0xdd, 0x58, 0x65, 0xd8, 0x9f, 0xdd, 0x70, 0x7f, 0x0f, 0xec, 0xbd, 0x5c, 0x5c, 0x9b, 0x7e, 0x1b, 0x9f, 0x79, 0x36, 0x1f, 0xfd, 0x79, 0x10, 0x1c, 0x52, 0xf3, 0x22, 0xa4, 0x1f, 0x71, 0x6e, 0x63, 0x14, 0xf4, 0xa7, 0x3e, 0xbe, 0xad, 0x43, 0x30, 0x38, 0x8c, 0x29, 0xc6, 0xcf, 0x50, 0x75, 0x21, 0xe5, 0x78, 0xfd, 0xb0, 0x9a, 0xc4, 0x6d, 0xd4}, + }, + }, + { + { + addYX: fp.Elt{0x7a, 0xa1, 0x38, 0xa6, 0xfd, 0x0e, 0x96, 0xd5, 0x26, 0x76, 0x86, 0x70, 0x80, 0x30, 0xa6, 0x67, 0xeb, 0xf4, 0x39, 0xdb, 0x22, 0xf5, 0x9f, 0x98, 0xe4, 0xb5, 0x3a, 0x0c, 0x59, 0xbf, 0x85, 0xc6, 0xf0, 0x0b, 0x1c, 0x41, 0x38, 0x09, 0x01, 0xdb, 0xd6, 0x3c, 0xb7, 0xf1, 0x08, 0x6b, 0x4b, 0x9e, 0x63, 0x53, 0x83, 0xd3, 0xab, 0xa3, 0x72, 0x0d}, + subYX: fp.Elt{0x84, 0x68, 0x25, 0xe8, 0xe9, 0x8f, 0x91, 0xbf, 0xf7, 0xa4, 0x30, 0xae, 0xea, 0x9f, 0xdd, 0x56, 0x64, 0x09, 0xc9, 0x54, 0x68, 0x4e, 0x33, 0xc5, 0x6f, 0x7b, 0x2d, 0x52, 0x2e, 0x42, 0xbe, 0xbe, 0xf5, 0x64, 0xbf, 0x77, 0x54, 0xdf, 0xb0, 0x10, 0xd2, 0x16, 0x5d, 0xce, 0xaf, 0x9f, 0xfb, 0xa3, 0x63, 0x50, 0xcb, 0xc0, 0xd0, 0x88, 0x44, 0xa3}, + dt2: fp.Elt{0xc3, 0x8b, 0xa5, 0xf1, 0x44, 0xe4, 0x41, 0xcd, 0x75, 0xe3, 0x17, 0x69, 0x5b, 0xb9, 0xbb, 0xee, 0x82, 0xbb, 0xce, 0x57, 0xdf, 0x2a, 0x9c, 0x12, 0xab, 0x66, 0x08, 0x68, 0x05, 0x1b, 0x87, 0xee, 0x5d, 0x1e, 0x18, 0x14, 0x22, 0x4b, 0x99, 0x61, 0x75, 0x28, 0xe7, 0x65, 0x1c, 0x36, 0xb6, 0x18, 0x09, 0xa8, 0xdf, 0xef, 0x30, 0x35, 0xbc, 0x58}, + }, + { + addYX: fp.Elt{0xc5, 0xd3, 0x0e, 0x6f, 0xaf, 0x06, 0x69, 0xc4, 0x07, 0x9e, 0x58, 0x6e, 0x3f, 0x49, 0xd9, 0x0a, 0x3c, 0x2c, 0x37, 0xcd, 0x27, 0x4d, 0x87, 0x91, 0x7a, 0xb0, 0x28, 0xad, 0x2f, 0x68, 0x92, 0x05, 0x97, 0xf1, 0x30, 0x5f, 0x4c, 0x10, 0x20, 0x30, 0xd3, 0x08, 0x3f, 0xc1, 0xc6, 0xb7, 0xb5, 0xd1, 0x71, 0x7b, 0xa8, 0x0a, 0xd8, 0xf5, 0x17, 0xcf}, + subYX: fp.Elt{0x64, 0xd4, 0x8f, 0x91, 0x40, 0xab, 0x6e, 0x1a, 0x62, 0x83, 0xdc, 0xd7, 0x30, 0x1a, 0x4a, 0x2a, 0x4c, 0x54, 0x86, 0x19, 0x81, 0x5d, 0x04, 0x52, 0xa3, 0xca, 0x82, 0x38, 0xdc, 0x1e, 0xf0, 0x7a, 0x78, 0x76, 0x49, 0x4f, 0x71, 0xc4, 0x74, 0x2f, 0xf0, 0x5b, 0x2e, 0x5e, 0xac, 0xef, 0x17, 0xe4, 0x8e, 0x6e, 0xed, 0x43, 0x23, 0x61, 0x99, 0x49}, + dt2: fp.Elt{0x64, 0x90, 0x72, 0x76, 0xf8, 0x2c, 0x7d, 0x57, 0xf9, 0x30, 0x5e, 0x7a, 0x10, 0x74, 0x19, 0x39, 0xd9, 0xaf, 0x0a, 0xf1, 0x43, 0xed, 0x88, 0x9c, 0x8b, 0xdc, 0x9b, 0x1c, 0x90, 0xe7, 0xf7, 0xa3, 0xa5, 0x0d, 0xc6, 0xbc, 0x30, 0xfb, 0x91, 0x1a, 0x51, 0xba, 0x2d, 0xbe, 0x89, 0xdf, 0x1d, 0xdc, 0x53, 0xa8, 0x82, 0x8a, 0xd3, 0x8d, 0x16, 0x68}, + }, + { + addYX: fp.Elt{0xef, 0x5c, 0xe3, 0x74, 0xbf, 0x13, 0x4a, 0xbf, 0x66, 0x73, 0x64, 0xb7, 0xd4, 0xce, 0x98, 0x82, 0x05, 0xfa, 0x98, 0x0c, 0x0a, 0xae, 0xe5, 0x6b, 0x9f, 0xac, 0xbb, 0x6e, 0x1f, 0xcf, 0xff, 0xa6, 0x71, 0x9a, 0xa8, 0x7a, 0x9e, 0x64, 0x1f, 0x20, 0x4a, 0x61, 0xa2, 0xd6, 0x50, 0xe3, 0xba, 0x81, 0x0c, 0x50, 0x59, 0x69, 0x59, 0x15, 0x55, 0xdb}, + subYX: fp.Elt{0xe8, 0x77, 0x4d, 0xe8, 0x66, 0x3d, 0xc1, 0x00, 0x3c, 0xf2, 0x25, 0x00, 0xdc, 0xb2, 0xe5, 0x9b, 0x12, 0x89, 0xf3, 0xd6, 0xea, 0x85, 0x60, 0xfe, 0x67, 0x91, 0xfd, 0x04, 0x7c, 0xe0, 0xf1, 0x86, 0x06, 0x11, 0x66, 0xee, 0xd4, 0xd5, 0xbe, 0x3b, 0x0f, 0xe3, 0x59, 0xb3, 0x4f, 0x00, 0xb6, 0xce, 0x80, 0xc1, 0x61, 0xf7, 0xaf, 0x04, 0x6a, 0x3c}, + dt2: fp.Elt{0x00, 0xd7, 0x32, 0x93, 0x67, 0x70, 0x6f, 0xd7, 0x69, 0xab, 0xb1, 0xd3, 0xdc, 0xd6, 0xa8, 0xdd, 0x35, 0x25, 0xca, 0xd3, 0x8a, 0x6d, 0xce, 0xfb, 0xfd, 0x2b, 0x83, 0xf0, 0xd4, 0xac, 0x66, 0xfb, 0x72, 0x87, 0x7e, 0x55, 0xb7, 0x91, 0x58, 0x10, 0xc3, 0x11, 0x7e, 0x15, 0xfe, 0x7c, 0x55, 0x90, 0xa3, 0x9e, 0xed, 0x9a, 0x7f, 0xa7, 0xb7, 0xeb}, + }, + { + addYX: fp.Elt{0x25, 0x0f, 0xc2, 0x09, 0x9c, 0x10, 0xc8, 0x7c, 0x93, 0xa7, 0xbe, 0xe9, 0x26, 0x25, 0x7c, 0x21, 0xfe, 0xe7, 0x5f, 0x3c, 0x02, 0x83, 0xa7, 0x9e, 0xdf, 0xc0, 0x94, 0x2b, 0x7d, 0x1a, 0xd0, 0x1d, 0xcc, 0x2e, 0x7d, 0xd4, 0x85, 0xe7, 0xc1, 0x15, 0x66, 0xd6, 0xd6, 0x32, 0xb8, 0xf7, 0x63, 0xaa, 0x3b, 0xa5, 0xea, 0x49, 0xad, 0x88, 0x9b, 0x66}, + subYX: fp.Elt{0x09, 0x97, 0x79, 0x36, 0x41, 0x56, 0x9b, 0xdf, 0x15, 0xd8, 0x43, 0x28, 0x17, 0x5b, 0x96, 0xc9, 0xcf, 0x39, 0x1f, 0x13, 0xf7, 0x4d, 0x1d, 0x1f, 0xda, 0x51, 0x56, 0xe7, 0x0a, 0x5a, 0x65, 0xb6, 0x2a, 0x87, 0x49, 0x86, 0xc2, 0x2b, 0xcd, 0xfe, 0x07, 0xf6, 0x4c, 0xe2, 0x1d, 0x9b, 0xd8, 0x82, 0x09, 0x5b, 0x11, 0x10, 0x62, 0x56, 0x89, 0xbd}, + dt2: fp.Elt{0xd9, 0x15, 0x73, 0xf2, 0x96, 0x35, 0x53, 0xb0, 0xe7, 0xa8, 0x0b, 0x93, 0x35, 0x0b, 0x3a, 0x00, 0xf5, 0x18, 0xb1, 0xc3, 0x12, 0x3f, 0x91, 0x17, 0xc1, 0x4c, 0x15, 0x5a, 0x86, 0x92, 0x11, 0xbd, 0x44, 0x40, 0x5a, 0x7b, 0x15, 0x89, 0xba, 0xc1, 0xc1, 0xbc, 0x43, 0x45, 0xe6, 0x52, 0x02, 0x73, 0x0a, 0xd0, 0x2a, 0x19, 0xda, 0x47, 0xa8, 0xff}, + }, + }, +} + +// tabVerif contains the odd multiples of P. The entry T[i] = (2i+1)P, where +// P = phi(G) and G is the generator of the Goldilocks curve, and phi is a +// 4-degree isogeny. +var tabVerif = [1 << (omegaFix - 2)]preTwistPointAffine{ + { /* 1P*/ + addYX: fp.Elt{0x65, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2b, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, + subYX: fp.Elt{0x64, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2d, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, + dt2: fp.Elt{0x1a, 0x33, 0xea, 0x64, 0x45, 0x1c, 0xdf, 0x17, 0x1d, 0x16, 0x34, 0x28, 0xd6, 0x61, 0x19, 0x67, 0x79, 0xb4, 0x13, 0xcf, 0x3e, 0x7c, 0x0e, 0x72, 0xda, 0xf1, 0x5f, 0xda, 0xe6, 0xcf, 0x42, 0xd3, 0xb6, 0x17, 0xc2, 0x68, 0x13, 0x2d, 0xd9, 0x60, 0x3e, 0xae, 0xf0, 0x5b, 0x96, 0xf0, 0xcd, 0xaf, 0xea, 0xb7, 0x0d, 0x59, 0x16, 0xa7, 0xff, 0x55}, + }, + { /* 3P*/ + addYX: fp.Elt{0xd1, 0xe9, 0xa8, 0x33, 0x20, 0x76, 0x18, 0x08, 0x45, 0x2a, 0xc9, 0x67, 0x2a, 0xc3, 0x15, 0x24, 0xf9, 0x74, 0x21, 0x30, 0x99, 0x59, 0x8b, 0xb2, 0xf0, 0xa4, 0x07, 0xe2, 0x6a, 0x36, 0x8d, 0xd9, 0xd2, 0x4a, 0x7f, 0x73, 0x50, 0x39, 0x3d, 0xaa, 0xa7, 0x51, 0x73, 0x0d, 0x2b, 0x8b, 0x96, 0x47, 0xac, 0x3c, 0x5d, 0xaa, 0x39, 0x9c, 0xcf, 0xd5}, + subYX: fp.Elt{0x6b, 0x11, 0x5d, 0x1a, 0xf9, 0x41, 0x9d, 0xc5, 0x30, 0x3e, 0xad, 0x25, 0x2c, 0x04, 0x45, 0xea, 0xcc, 0x67, 0x07, 0x85, 0xe9, 0xda, 0x0e, 0xb5, 0x40, 0xb7, 0x32, 0xb4, 0x49, 0xdd, 0xff, 0xaa, 0xfc, 0xbb, 0x19, 0xca, 0x8b, 0x79, 0x2b, 0x8f, 0x8d, 0x00, 0x33, 0xc2, 0xad, 0xe9, 0xd3, 0x12, 0xa8, 0xaa, 0x87, 0x62, 0xad, 0x2d, 0xff, 0xa4}, + dt2: fp.Elt{0xb0, 0xaf, 0x3b, 0xea, 0xf0, 0x42, 0x0b, 0x5e, 0x88, 0xd3, 0x98, 0x08, 0x87, 0x59, 0x72, 0x0a, 0xc2, 0xdf, 0xcb, 0x7f, 0x59, 0xb5, 0x4c, 0x63, 0x68, 0xe8, 0x41, 0x38, 0x67, 0x4f, 0xe9, 0xc6, 0xb2, 0x6b, 0x08, 0xa7, 0xf7, 0x0e, 0xcd, 0xea, 0xca, 0x3d, 0xaf, 0x8e, 0xda, 0x4b, 0x2e, 0xd2, 0x88, 0x64, 0x8d, 0xc5, 0x5f, 0x76, 0x0f, 0x3d}, + }, + { /* 5P*/ + addYX: fp.Elt{0xe5, 0x65, 0xc9, 0xe2, 0x75, 0xf0, 0x7d, 0x1a, 0xba, 0xa4, 0x40, 0x4b, 0x93, 0x12, 0xa2, 0x80, 0x95, 0x0d, 0x03, 0x93, 0xe8, 0xa5, 0x4d, 0xe2, 0x3d, 0x81, 0xf5, 0xce, 0xd4, 0x2d, 0x25, 0x59, 0x16, 0x5c, 0xe7, 0xda, 0xc7, 0x45, 0xd2, 0x7e, 0x2c, 0x38, 0xd4, 0x37, 0x64, 0xb2, 0xc2, 0x28, 0xc5, 0x72, 0x16, 0x32, 0x45, 0x36, 0x6f, 0x9f}, + subYX: fp.Elt{0x09, 0xf4, 0x7e, 0xbd, 0x89, 0xdb, 0x19, 0x58, 0xe1, 0x08, 0x00, 0x8a, 0xf4, 0x5f, 0x2a, 0x32, 0x40, 0xf0, 0x2c, 0x3f, 0x5d, 0xe4, 0xfc, 0x89, 0x11, 0x24, 0xb4, 0x2f, 0x97, 0xad, 0xac, 0x8f, 0x19, 0xab, 0xfa, 0x12, 0xe5, 0xf9, 0x50, 0x4e, 0x50, 0x6f, 0x32, 0x30, 0x88, 0xa6, 0xe5, 0x48, 0x28, 0xa2, 0x1b, 0x9f, 0xcd, 0xe2, 0x43, 0x38}, + dt2: fp.Elt{0xa9, 0xcc, 0x53, 0x39, 0x86, 0x02, 0x60, 0x75, 0x34, 0x99, 0x57, 0xbd, 0xfc, 0x5a, 0x8e, 0xce, 0x5e, 0x98, 0x22, 0xd0, 0xa5, 0x24, 0xff, 0x90, 0x28, 0x9f, 0x58, 0xf3, 0x39, 0xe9, 0xba, 0x36, 0x23, 0xfb, 0x7f, 0x41, 0xcc, 0x2b, 0x5a, 0x25, 0x3f, 0x4c, 0x2a, 0xf1, 0x52, 0x6f, 0x2f, 0x07, 0xe3, 0x88, 0x81, 0x77, 0xdd, 0x7c, 0x88, 0x82}, + }, + { /* 7P*/ + addYX: fp.Elt{0xf7, 0xee, 0x88, 0xfd, 0x3a, 0xbf, 0x7e, 0x28, 0x39, 0x23, 0x79, 0xe6, 0x5c, 0x56, 0xcb, 0xb5, 0x48, 0x6a, 0x80, 0x6d, 0x37, 0x60, 0x6c, 0x10, 0x35, 0x49, 0x4b, 0x46, 0x60, 0xd4, 0x79, 0xd4, 0x53, 0xd3, 0x67, 0x88, 0xd0, 0x41, 0xd5, 0x43, 0x85, 0xc8, 0x71, 0xe3, 0x1c, 0xb6, 0xda, 0x22, 0x64, 0x8f, 0x80, 0xac, 0xad, 0x7d, 0xd5, 0x82}, + subYX: fp.Elt{0x92, 0x40, 0xc1, 0x83, 0x21, 0x9b, 0xd5, 0x7d, 0x3f, 0x29, 0xb6, 0x26, 0xef, 0x12, 0xb9, 0x27, 0x39, 0x42, 0x37, 0x97, 0x09, 0x9a, 0x08, 0xe1, 0x68, 0xb6, 0x7a, 0x3f, 0x9f, 0x45, 0xf8, 0x37, 0x19, 0x83, 0x97, 0xe6, 0x73, 0x30, 0x32, 0x35, 0xcf, 0xae, 0x5c, 0x12, 0x68, 0xdf, 0x6e, 0x2b, 0xde, 0x83, 0xa0, 0x44, 0x74, 0x2e, 0x4a, 0xe9}, + dt2: fp.Elt{0xcb, 0x22, 0x0a, 0xda, 0x6b, 0xc1, 0x8a, 0x29, 0xa1, 0xac, 0x8b, 0x5b, 0x8b, 0x32, 0x20, 0xf2, 0x21, 0xae, 0x0c, 0x43, 0xc4, 0xd7, 0x19, 0x37, 0x3d, 0x79, 0x25, 0x98, 0x6c, 0x9c, 0x22, 0x31, 0x2a, 0x55, 0x9f, 0xda, 0x5e, 0xa8, 0x13, 0xdb, 0x8e, 0x2e, 0x16, 0x39, 0xf4, 0x91, 0x6f, 0xec, 0x71, 0x71, 0xc9, 0x10, 0xf2, 0xa4, 0x8f, 0x11}, + }, + { /* 9P*/ + addYX: fp.Elt{0x85, 0xdd, 0x37, 0x62, 0x74, 0x8e, 0x33, 0x5b, 0x25, 0x12, 0x1b, 0xe7, 0xdf, 0x47, 0xe5, 0x12, 0xfd, 0x3a, 0x3a, 0xf5, 0x5d, 0x4c, 0xa2, 0x29, 0x3c, 0x5c, 0x2f, 0xee, 0x18, 0x19, 0x0a, 0x2b, 0xef, 0x67, 0x50, 0x7a, 0x0d, 0x29, 0xae, 0x55, 0x82, 0xcd, 0xd6, 0x41, 0x90, 0xb4, 0x13, 0x31, 0x5d, 0x11, 0xb8, 0xaa, 0x12, 0x86, 0x08, 0xac}, + subYX: fp.Elt{0xcc, 0x37, 0x8d, 0x83, 0x5f, 0xfd, 0xde, 0xd5, 0xf7, 0xf1, 0xae, 0x0a, 0xa7, 0x0b, 0xeb, 0x6d, 0x19, 0x8a, 0xb6, 0x1a, 0x59, 0xd8, 0xff, 0x3c, 0xbc, 0xbc, 0xef, 0x9c, 0xda, 0x7b, 0x75, 0x12, 0xaf, 0x80, 0x8f, 0x2c, 0x3c, 0xaa, 0x0b, 0x17, 0x86, 0x36, 0x78, 0x18, 0xc8, 0x8a, 0xf6, 0xb8, 0x2c, 0x2f, 0x57, 0x2c, 0x62, 0x57, 0xf6, 0x90}, + dt2: fp.Elt{0x83, 0xbc, 0xa2, 0x07, 0xa5, 0x38, 0x96, 0xea, 0xfe, 0x11, 0x46, 0x1d, 0x3b, 0xcd, 0x42, 0xc5, 0xee, 0x67, 0x04, 0x72, 0x08, 0xd8, 0xd9, 0x96, 0x07, 0xf7, 0xac, 0xc3, 0x64, 0xf1, 0x98, 0x2c, 0x55, 0xd7, 0x7d, 0xc8, 0x6c, 0xbd, 0x2c, 0xff, 0x15, 0xd6, 0x6e, 0xb8, 0x17, 0x8e, 0xa8, 0x27, 0x66, 0xb1, 0x73, 0x79, 0x96, 0xff, 0x29, 0x10}, + }, + { /* 11P*/ + addYX: fp.Elt{0x76, 0xcb, 0x9b, 0x0c, 0x5b, 0xfe, 0xe1, 0x2a, 0xdd, 0x6f, 0x6c, 0xdd, 0x6f, 0xb4, 0xc0, 0xc2, 0x1b, 0x4b, 0x38, 0xe8, 0x66, 0x8c, 0x1e, 0x31, 0x63, 0xb9, 0x94, 0xcd, 0xc3, 0x8c, 0x44, 0x25, 0x7b, 0xd5, 0x39, 0x80, 0xfc, 0x01, 0xaa, 0xf7, 0x2a, 0x61, 0x8a, 0x25, 0xd2, 0x5f, 0xc5, 0x66, 0x38, 0xa4, 0x17, 0xcf, 0x3e, 0x11, 0x0f, 0xa3}, + subYX: fp.Elt{0xe0, 0xb6, 0xd1, 0x9c, 0x71, 0x49, 0x2e, 0x7b, 0xde, 0x00, 0xda, 0x6b, 0xf1, 0xec, 0xe6, 0x7a, 0x15, 0x38, 0x71, 0xe9, 0x7b, 0xdb, 0xf8, 0x98, 0xc0, 0x91, 0x2e, 0x53, 0xee, 0x92, 0x87, 0x25, 0xc9, 0xb0, 0xbb, 0x33, 0x15, 0x46, 0x7f, 0xfd, 0x4f, 0x8b, 0x77, 0x05, 0x96, 0xb6, 0xe2, 0x08, 0xdb, 0x0d, 0x09, 0xee, 0x5b, 0xd1, 0x2a, 0x63}, + dt2: fp.Elt{0x8f, 0x7b, 0x57, 0x8c, 0xbf, 0x06, 0x0d, 0x43, 0x21, 0x92, 0x94, 0x2d, 0x6a, 0x38, 0x07, 0x0f, 0xa0, 0xf1, 0xe3, 0xd8, 0x2a, 0xbf, 0x46, 0xc6, 0x9e, 0x1f, 0x8f, 0x2b, 0x46, 0x84, 0x0b, 0x74, 0xed, 0xff, 0xf8, 0xa5, 0x94, 0xae, 0xf1, 0x67, 0xb1, 0x9b, 0xdd, 0x4a, 0xd0, 0xdb, 0xc2, 0xb5, 0x58, 0x49, 0x0c, 0xa9, 0x1d, 0x7d, 0xa9, 0xd3}, + }, + { /* 13P*/ + addYX: fp.Elt{0x73, 0x84, 0x2e, 0x31, 0x1f, 0xdc, 0xed, 0x9f, 0x74, 0xfa, 0xe0, 0x35, 0xb1, 0x85, 0x6a, 0x8d, 0x86, 0xd0, 0xff, 0xd6, 0x08, 0x43, 0x73, 0x1a, 0xd5, 0xf8, 0x43, 0xd4, 0xb3, 0xe5, 0x3f, 0xa8, 0x84, 0x17, 0x59, 0x65, 0x4e, 0xe6, 0xee, 0x54, 0x9c, 0xda, 0x5e, 0x7e, 0x98, 0x29, 0x6d, 0x73, 0x34, 0x1f, 0x99, 0x80, 0x54, 0x54, 0x81, 0x0b}, + subYX: fp.Elt{0xb1, 0xe5, 0xbb, 0x80, 0x22, 0x9c, 0x81, 0x6d, 0xaf, 0x27, 0x65, 0x6f, 0x7e, 0x9c, 0xb6, 0x8d, 0x35, 0x5c, 0x2e, 0x20, 0x48, 0x7a, 0x28, 0xf0, 0x97, 0xfe, 0xb7, 0x71, 0xce, 0xd6, 0xad, 0x3a, 0x81, 0xf6, 0x74, 0x5e, 0xf3, 0xfd, 0x1b, 0xd4, 0x1e, 0x7c, 0xc2, 0xb7, 0xc8, 0xa6, 0xc9, 0x89, 0x03, 0x47, 0xec, 0x24, 0xd6, 0x0e, 0xec, 0x9c}, + dt2: fp.Elt{0x91, 0x0a, 0x43, 0x34, 0x20, 0xc2, 0x64, 0xf7, 0x4e, 0x48, 0xc8, 0xd2, 0x95, 0x83, 0xd1, 0xa4, 0xfb, 0x4e, 0x41, 0x3b, 0x0d, 0xd5, 0x07, 0xd9, 0xf1, 0x13, 0x16, 0x78, 0x54, 0x57, 0xd0, 0xf1, 0x4f, 0x20, 0xac, 0xcf, 0x9c, 0x3b, 0x33, 0x0b, 0x99, 0x54, 0xc3, 0x7f, 0x3e, 0x57, 0x26, 0x86, 0xd5, 0xa5, 0x2b, 0x8d, 0xe3, 0x19, 0x36, 0xf7}, + }, + { /* 15P*/ + addYX: fp.Elt{0x23, 0x69, 0x47, 0x14, 0xf9, 0x9a, 0x50, 0xff, 0x64, 0xd1, 0x50, 0x35, 0xc3, 0x11, 0xd3, 0x19, 0xcf, 0x87, 0xda, 0x30, 0x0b, 0x50, 0xda, 0xc0, 0xe0, 0x25, 0x00, 0xe5, 0x68, 0x93, 0x04, 0xc2, 0xaf, 0xbd, 0x2f, 0x36, 0x5f, 0x47, 0x96, 0x10, 0xa8, 0xbd, 0xe4, 0x88, 0xac, 0x80, 0x52, 0x61, 0x73, 0xe9, 0x63, 0xdd, 0x99, 0xad, 0x20, 0x5b}, + subYX: fp.Elt{0x1b, 0x5e, 0xa2, 0x2a, 0x25, 0x0f, 0x86, 0xc0, 0xb1, 0x2e, 0x0c, 0x13, 0x40, 0x8d, 0xf0, 0xe6, 0x00, 0x55, 0x08, 0xc5, 0x7d, 0xf4, 0xc9, 0x31, 0x25, 0x3a, 0x99, 0x69, 0xdd, 0x67, 0x63, 0x9a, 0xd6, 0x89, 0x2e, 0xa1, 0x19, 0xca, 0x2c, 0xd9, 0x59, 0x5f, 0x5d, 0xc3, 0x6e, 0x62, 0x36, 0x12, 0x59, 0x15, 0xe1, 0xdc, 0xa4, 0xad, 0xc9, 0xd0}, + dt2: fp.Elt{0xbc, 0xea, 0xfc, 0xaf, 0x66, 0x23, 0xb7, 0x39, 0x6b, 0x2a, 0x96, 0xa8, 0x54, 0x43, 0xe9, 0xaa, 0x32, 0x40, 0x63, 0x92, 0x5e, 0xdf, 0x35, 0xc2, 0x9f, 0x24, 0x0c, 0xed, 0xfc, 0xde, 0x73, 0x8f, 0xa7, 0xd5, 0xa3, 0x2b, 0x18, 0x1f, 0xb0, 0xf8, 0xeb, 0x55, 0xd9, 0xc3, 0xfd, 0x28, 0x7c, 0x4f, 0xce, 0x0d, 0xf7, 0xae, 0xc2, 0x83, 0xc3, 0x78}, + }, + { /* 17P*/ + addYX: fp.Elt{0x71, 0xe6, 0x60, 0x93, 0x37, 0xdb, 0x01, 0xa5, 0x4c, 0xba, 0xe8, 0x8e, 0xd5, 0xf9, 0xd3, 0x98, 0xe5, 0xeb, 0xab, 0x3a, 0x15, 0x8b, 0x35, 0x60, 0xbe, 0xe5, 0x9c, 0x2d, 0x10, 0x9b, 0x2e, 0xcf, 0x65, 0x64, 0xea, 0x8f, 0x72, 0xce, 0xf5, 0x18, 0xe5, 0xe2, 0xf0, 0x0e, 0xae, 0x04, 0xec, 0xa0, 0x20, 0x65, 0x63, 0x07, 0xb1, 0x9f, 0x03, 0x97}, + subYX: fp.Elt{0x9e, 0x41, 0x64, 0x30, 0x95, 0x7f, 0x3a, 0x89, 0x7b, 0x0a, 0x79, 0x59, 0x23, 0x9a, 0x3b, 0xfe, 0xa4, 0x13, 0x08, 0xb2, 0x2e, 0x04, 0x50, 0x10, 0x30, 0xcd, 0x2e, 0xa4, 0x91, 0x71, 0x50, 0x36, 0x4a, 0x02, 0xf4, 0x8d, 0xa3, 0x36, 0x1b, 0xf4, 0x52, 0xba, 0x15, 0x04, 0x8b, 0x80, 0x25, 0xd9, 0xae, 0x67, 0x20, 0xd9, 0x88, 0x8f, 0x97, 0xa6}, + dt2: fp.Elt{0xb5, 0xe7, 0x46, 0xbd, 0x55, 0x23, 0xa0, 0x68, 0xc0, 0x12, 0xd9, 0xf1, 0x0a, 0x75, 0xe2, 0xda, 0xf4, 0x6b, 0xca, 0x14, 0xe4, 0x9f, 0x0f, 0xb5, 0x3c, 0xa6, 0xa5, 0xa2, 0x63, 0x94, 0xd1, 0x1c, 0x39, 0x58, 0x57, 0x02, 0x27, 0x98, 0xb6, 0x47, 0xc6, 0x61, 0x4b, 0x5c, 0xab, 0x6f, 0x2d, 0xab, 0xe3, 0xc1, 0x69, 0xf9, 0x12, 0xb0, 0xc8, 0xd5}, + }, + { /* 19P*/ + addYX: fp.Elt{0x19, 0x7d, 0xd5, 0xac, 0x79, 0xa2, 0x82, 0x9b, 0x28, 0x31, 0x22, 0xc0, 0x73, 0x02, 0x76, 0x17, 0x10, 0x70, 0x79, 0x57, 0xc9, 0x84, 0x62, 0x8e, 0x04, 0x04, 0x61, 0x67, 0x08, 0x48, 0xb4, 0x4b, 0xde, 0x53, 0x8c, 0xff, 0x36, 0x1b, 0x62, 0x86, 0x5d, 0xe1, 0x9b, 0xb1, 0xe5, 0xe8, 0x44, 0x64, 0xa1, 0x68, 0x3f, 0xa8, 0x45, 0x52, 0x91, 0xed}, + subYX: fp.Elt{0x42, 0x1a, 0x36, 0x1f, 0x90, 0x15, 0x24, 0x8d, 0x24, 0x80, 0xe6, 0xfe, 0x1e, 0xf0, 0xad, 0xaf, 0x6a, 0x93, 0xf0, 0xa6, 0x0d, 0x5d, 0xea, 0xf6, 0x62, 0x96, 0x7a, 0x05, 0x76, 0x85, 0x74, 0x32, 0xc7, 0xc8, 0x64, 0x53, 0x62, 0xe7, 0x54, 0x84, 0xe0, 0x40, 0x66, 0x19, 0x70, 0x40, 0x95, 0x35, 0x68, 0x64, 0x43, 0xcd, 0xba, 0x29, 0x32, 0xa8}, + dt2: fp.Elt{0x3e, 0xf6, 0xd6, 0xe4, 0x99, 0xeb, 0x20, 0x66, 0x08, 0x2e, 0x26, 0x64, 0xd7, 0x76, 0xf3, 0xb4, 0xc5, 0xa4, 0x35, 0x92, 0xd2, 0x99, 0x70, 0x5a, 0x1a, 0xe9, 0xe9, 0x3d, 0x3b, 0xe1, 0xcd, 0x0e, 0xee, 0x24, 0x13, 0x03, 0x22, 0xd6, 0xd6, 0x72, 0x08, 0x2b, 0xde, 0xfd, 0x93, 0xed, 0x0c, 0x7f, 0x5e, 0x31, 0x22, 0x4d, 0x80, 0x78, 0xc0, 0x48}, + }, + { /* 21P*/ + addYX: fp.Elt{0x8f, 0x72, 0xd2, 0x9e, 0xc4, 0xcd, 0x2c, 0xbf, 0xa8, 0xd3, 0x24, 0x62, 0x28, 0xee, 0x39, 0x0a, 0x19, 0x3a, 0x58, 0xff, 0x21, 0x2e, 0x69, 0x6c, 0x6e, 0x18, 0xd0, 0xcd, 0x61, 0xc1, 0x18, 0x02, 0x5a, 0xe9, 0xe3, 0xef, 0x1f, 0x8e, 0x10, 0xe8, 0x90, 0x2b, 0x48, 0xcd, 0xee, 0x38, 0xbd, 0x3a, 0xca, 0xbc, 0x2d, 0xe2, 0x3a, 0x03, 0x71, 0x02}, + subYX: fp.Elt{0xf8, 0xa4, 0x32, 0x26, 0x66, 0xaf, 0x3b, 0x53, 0xe7, 0xb0, 0x91, 0x92, 0xf5, 0x3c, 0x74, 0xce, 0xf2, 0xdd, 0x68, 0xa9, 0xf4, 0xcd, 0x5f, 0x60, 0xab, 0x71, 0xdf, 0xcd, 0x5c, 0x5d, 0x51, 0x72, 0x3a, 0x96, 0xea, 0xd6, 0xde, 0x54, 0x8e, 0x55, 0x4c, 0x08, 0x4c, 0x60, 0xdd, 0x34, 0xa9, 0x6f, 0xf3, 0x04, 0x02, 0xa8, 0xa6, 0x4e, 0x4d, 0x62}, + dt2: fp.Elt{0x76, 0x4a, 0xae, 0x38, 0x62, 0x69, 0x72, 0xdc, 0xe8, 0x43, 0xbe, 0x1d, 0x61, 0xde, 0x31, 0xc3, 0x42, 0x8f, 0x33, 0x9d, 0xca, 0xc7, 0x9c, 0xec, 0x6a, 0xe2, 0xaa, 0x01, 0x49, 0x78, 0x8d, 0x72, 0x4f, 0x38, 0xea, 0x52, 0xc2, 0xd3, 0xc9, 0x39, 0x71, 0xba, 0xb9, 0x09, 0x9b, 0xa3, 0x7f, 0x45, 0x43, 0x65, 0x36, 0x29, 0xca, 0xe7, 0x5c, 0x5f}, + }, + { /* 23P*/ + addYX: fp.Elt{0x89, 0x42, 0x35, 0x48, 0x6d, 0x74, 0xe5, 0x1f, 0xc3, 0xdd, 0x28, 0x5b, 0x84, 0x41, 0x33, 0x9f, 0x42, 0xf3, 0x1d, 0x5d, 0x15, 0x6d, 0x76, 0x33, 0x36, 0xaf, 0xe9, 0xdd, 0xfa, 0x63, 0x4f, 0x7a, 0x9c, 0xeb, 0x1c, 0x4f, 0x34, 0x65, 0x07, 0x54, 0xbb, 0x4c, 0x8b, 0x62, 0x9d, 0xd0, 0x06, 0x99, 0xb3, 0xe9, 0xda, 0x85, 0x19, 0xb0, 0x3d, 0x3c}, + subYX: fp.Elt{0xbb, 0x99, 0xf6, 0xbf, 0xaf, 0x2c, 0x22, 0x0d, 0x7a, 0xaa, 0x98, 0x6f, 0x01, 0x82, 0x99, 0xcf, 0x88, 0xbd, 0x0e, 0x3a, 0x89, 0xe0, 0x9c, 0x8c, 0x17, 0x20, 0xc4, 0xe0, 0xcf, 0x43, 0x7a, 0xef, 0x0d, 0x9f, 0x87, 0xd4, 0xfb, 0xf2, 0x96, 0xb8, 0x03, 0xe8, 0xcb, 0x5c, 0xec, 0x65, 0x5f, 0x49, 0xa4, 0x7c, 0x85, 0xb4, 0xf6, 0xc7, 0xdb, 0xa3}, + dt2: fp.Elt{0x11, 0xf3, 0x32, 0xa3, 0xa7, 0xb2, 0x7d, 0x51, 0x82, 0x44, 0xeb, 0xa2, 0x7d, 0x72, 0xcb, 0xc6, 0xf6, 0xc7, 0xb2, 0x38, 0x0e, 0x0f, 0x4f, 0x29, 0x00, 0xe4, 0x5b, 0x94, 0x46, 0x86, 0x66, 0xa1, 0x83, 0xb3, 0xeb, 0x15, 0xb6, 0x31, 0x50, 0x28, 0xeb, 0xed, 0x0d, 0x32, 0x39, 0xe9, 0x23, 0x81, 0x99, 0x3e, 0xff, 0x17, 0x4c, 0x11, 0x43, 0xd1}, + }, + { /* 25P*/ + addYX: fp.Elt{0xce, 0xe7, 0xf8, 0x94, 0x8f, 0x96, 0xf8, 0x96, 0xe6, 0x72, 0x20, 0x44, 0x2c, 0xa7, 0xfc, 0xba, 0xc8, 0xe1, 0xbb, 0xc9, 0x16, 0x85, 0xcd, 0x0b, 0xe5, 0xb5, 0x5a, 0x7f, 0x51, 0x43, 0x63, 0x8b, 0x23, 0x8e, 0x1d, 0x31, 0xff, 0x46, 0x02, 0x66, 0xcc, 0x9e, 0x4d, 0xa2, 0xca, 0xe2, 0xc7, 0xfd, 0x22, 0xb1, 0xdb, 0xdf, 0x6f, 0xe6, 0xa5, 0x82}, + subYX: fp.Elt{0xd0, 0xf5, 0x65, 0x40, 0xec, 0x8e, 0x65, 0x42, 0x78, 0xc1, 0x65, 0xe4, 0x10, 0xc8, 0x0b, 0x1b, 0xdd, 0x96, 0x68, 0xce, 0xee, 0x45, 0x55, 0xd8, 0x6e, 0xd3, 0xe6, 0x77, 0x19, 0xae, 0xc2, 0x8d, 0x8d, 0x3e, 0x14, 0x3f, 0x6d, 0x00, 0x2f, 0x9b, 0xd1, 0x26, 0x60, 0x28, 0x0f, 0x3a, 0x47, 0xb3, 0xe6, 0x68, 0x28, 0x24, 0x25, 0xca, 0xc8, 0x06}, + dt2: fp.Elt{0x54, 0xbb, 0x60, 0x92, 0xdb, 0x8f, 0x0f, 0x38, 0xe0, 0xe6, 0xe4, 0xc9, 0xcc, 0x14, 0x62, 0x01, 0xc4, 0x2b, 0x0f, 0xcf, 0xed, 0x7d, 0x8e, 0xa4, 0xd9, 0x73, 0x0b, 0xba, 0x0c, 0xaf, 0x0c, 0xf9, 0xe2, 0xeb, 0x29, 0x2a, 0x53, 0xdf, 0x2c, 0x5a, 0xfa, 0x8f, 0xc1, 0x01, 0xd7, 0xb1, 0x45, 0x73, 0x92, 0x32, 0x83, 0x85, 0x12, 0x74, 0x89, 0x44}, + }, + { /* 27P*/ + addYX: fp.Elt{0x0b, 0x73, 0x3c, 0xc2, 0xb1, 0x2e, 0xe1, 0xa7, 0xf5, 0xc9, 0x7a, 0xfb, 0x3d, 0x2d, 0xac, 0x59, 0xdb, 0xfa, 0x36, 0x11, 0xd1, 0x13, 0x04, 0x51, 0x1d, 0xab, 0x9b, 0x6b, 0x93, 0xfe, 0xda, 0xb0, 0x8e, 0xb4, 0x79, 0x11, 0x21, 0x0f, 0x65, 0xb9, 0xbb, 0x79, 0x96, 0x2a, 0xfd, 0x30, 0xe0, 0xb4, 0x2d, 0x9a, 0x55, 0x25, 0x5d, 0xd4, 0xad, 0x2a}, + subYX: fp.Elt{0x9e, 0xc5, 0x04, 0xfe, 0xec, 0x3c, 0x64, 0x1c, 0xed, 0x95, 0xed, 0xae, 0xaf, 0x5c, 0x6e, 0x08, 0x9e, 0x02, 0x29, 0x59, 0x7e, 0x5f, 0xc4, 0x9a, 0xd5, 0x32, 0x72, 0x86, 0xe1, 0x4e, 0x3c, 0xce, 0x99, 0x69, 0x3b, 0xc4, 0xdd, 0x4d, 0xb7, 0xbb, 0xda, 0x3b, 0x1a, 0x99, 0xaa, 0x62, 0x15, 0xc1, 0xf0, 0xb6, 0x6c, 0xec, 0x56, 0xc1, 0xff, 0x0c}, + dt2: fp.Elt{0x2f, 0xf1, 0x3f, 0x7a, 0x2d, 0x56, 0x19, 0x7f, 0xea, 0xbe, 0x59, 0x2e, 0x13, 0x67, 0x81, 0xfb, 0xdb, 0xc8, 0xa3, 0x1d, 0xd5, 0xe9, 0x13, 0x8b, 0x29, 0xdf, 0xcf, 0x9f, 0xe7, 0xd9, 0x0b, 0x70, 0xd3, 0x15, 0x57, 0x4a, 0xe9, 0x50, 0x12, 0x1b, 0x81, 0x4b, 0x98, 0x98, 0xa8, 0x31, 0x1d, 0x27, 0x47, 0x38, 0xed, 0x57, 0x99, 0x26, 0xb2, 0xee}, + }, + { /* 29P*/ + addYX: fp.Elt{0x1c, 0xb2, 0xb2, 0x67, 0x3b, 0x8b, 0x3d, 0x5a, 0x30, 0x7e, 0x38, 0x7e, 0x3c, 0x3d, 0x28, 0x56, 0x59, 0xd8, 0x87, 0x53, 0x8b, 0xe6, 0x6c, 0x5d, 0xe5, 0x0a, 0x33, 0x10, 0xce, 0xa2, 0x17, 0x0d, 0xe8, 0x76, 0xee, 0x68, 0xa8, 0x72, 0x54, 0xbd, 0xa6, 0x24, 0x94, 0x6e, 0x77, 0xc7, 0x53, 0xb7, 0x89, 0x1c, 0x7a, 0xe9, 0x78, 0x9a, 0x74, 0x5f}, + subYX: fp.Elt{0x76, 0x96, 0x1c, 0xcf, 0x08, 0x55, 0xd8, 0x1e, 0x0d, 0xa3, 0x59, 0x95, 0x32, 0xf4, 0xc2, 0x8e, 0x84, 0x5e, 0x4b, 0x04, 0xda, 0x71, 0xc9, 0x78, 0x52, 0xde, 0x14, 0xb4, 0x31, 0xf4, 0xd4, 0xb8, 0x58, 0xc5, 0x20, 0xe8, 0xdd, 0x15, 0xb5, 0xee, 0xea, 0x61, 0xe0, 0xf5, 0xd6, 0xae, 0x55, 0x59, 0x05, 0x3e, 0xaf, 0x74, 0xac, 0x1f, 0x17, 0x82}, + dt2: fp.Elt{0x59, 0x24, 0xcd, 0xfc, 0x11, 0x7e, 0x85, 0x18, 0x3d, 0x69, 0xf7, 0x71, 0x31, 0x66, 0x98, 0x42, 0x95, 0x00, 0x8c, 0xb2, 0xae, 0x39, 0x7e, 0x85, 0xd6, 0xb0, 0x02, 0xec, 0xce, 0xfc, 0x25, 0xb2, 0xe3, 0x99, 0x8e, 0x5b, 0x61, 0x96, 0x2e, 0x6d, 0x96, 0x57, 0x71, 0xa5, 0x93, 0x41, 0x0e, 0x6f, 0xfd, 0x0a, 0xbf, 0xa9, 0xf7, 0x56, 0xa9, 0x3e}, + }, + { /* 31P*/ + addYX: fp.Elt{0xa2, 0x2e, 0x0c, 0x17, 0x4d, 0xcc, 0x85, 0x2c, 0x18, 0xa0, 0xd2, 0x08, 0xba, 0x11, 0xfa, 0x47, 0x71, 0x86, 0xaf, 0x36, 0x6a, 0xd7, 0xfe, 0xb9, 0xb0, 0x2f, 0x89, 0x98, 0x49, 0x69, 0xf8, 0x6a, 0xad, 0x27, 0x5e, 0x0a, 0x22, 0x60, 0x5e, 0x5d, 0xca, 0x06, 0x51, 0x27, 0x99, 0x29, 0x85, 0x68, 0x98, 0xe1, 0xc4, 0x21, 0x50, 0xa0, 0xe9, 0xc1}, + subYX: fp.Elt{0x4d, 0x70, 0xee, 0x91, 0x92, 0x3f, 0xb7, 0xd3, 0x1d, 0xdb, 0x8d, 0x6e, 0x16, 0xf5, 0x65, 0x7d, 0x5f, 0xb5, 0x6c, 0x59, 0x26, 0x70, 0x4b, 0xf2, 0xfc, 0xe7, 0xdf, 0x86, 0xfe, 0xa5, 0xa7, 0xa6, 0x5d, 0xfb, 0x06, 0xe9, 0xf9, 0xcc, 0xc0, 0x37, 0xcc, 0xd8, 0x09, 0x04, 0xd2, 0xa5, 0x1d, 0xd7, 0xb7, 0xce, 0x92, 0xac, 0x3c, 0xad, 0xfb, 0xae}, + dt2: fp.Elt{0x17, 0xa3, 0x9a, 0xc7, 0x86, 0x2a, 0x51, 0xf7, 0x96, 0x79, 0x49, 0x22, 0x2e, 0x5a, 0x01, 0x5c, 0xb5, 0x95, 0xd4, 0xe8, 0xcb, 0x00, 0xca, 0x2d, 0x55, 0xb6, 0x34, 0x36, 0x0b, 0x65, 0x46, 0xf0, 0x49, 0xfc, 0x87, 0x86, 0xe5, 0xc3, 0x15, 0xdb, 0x32, 0xcd, 0xf2, 0xd3, 0x82, 0x4c, 0xe6, 0x61, 0x8a, 0xaf, 0xd4, 0x9e, 0x0f, 0x5a, 0xf2, 0x81}, + }, + { /* 33P*/ + addYX: fp.Elt{0x88, 0x10, 0xc0, 0xcb, 0xf5, 0x77, 0xae, 0xa5, 0xbe, 0xf6, 0xcd, 0x2e, 0x8b, 0x7e, 0xbd, 0x79, 0x62, 0x4a, 0xeb, 0x69, 0xc3, 0x28, 0xaa, 0x72, 0x87, 0xa9, 0x25, 0x87, 0x46, 0xea, 0x0e, 0x62, 0xa3, 0x6a, 0x1a, 0xe2, 0xba, 0xdc, 0x81, 0x10, 0x33, 0x01, 0xf6, 0x16, 0x89, 0x80, 0xc6, 0xcd, 0xdb, 0xdc, 0xba, 0x0e, 0x09, 0x4a, 0x35, 0x4a}, + subYX: fp.Elt{0x86, 0xb2, 0x2b, 0xd0, 0xb8, 0x4a, 0x6d, 0x66, 0x7b, 0x32, 0xdf, 0x3b, 0x1a, 0x19, 0x1f, 0x63, 0xee, 0x1f, 0x3d, 0x1c, 0x5c, 0x14, 0x60, 0x5b, 0x72, 0x49, 0x07, 0xb1, 0x0d, 0x72, 0xc6, 0x35, 0xf0, 0xbc, 0x5e, 0xda, 0x80, 0x6b, 0x64, 0x5b, 0xe5, 0x34, 0x54, 0x39, 0xdd, 0xe6, 0x3c, 0xcb, 0xe5, 0x29, 0x32, 0x06, 0xc6, 0xb1, 0x96, 0x34}, + dt2: fp.Elt{0x85, 0x86, 0xf5, 0x84, 0x86, 0xe6, 0x77, 0x8a, 0x71, 0x85, 0x0c, 0x4f, 0x81, 0x5b, 0x29, 0x06, 0xb5, 0x2e, 0x26, 0x71, 0x07, 0x78, 0x07, 0xae, 0xbc, 0x95, 0x46, 0xc3, 0x65, 0xac, 0xe3, 0x76, 0x51, 0x7d, 0xd4, 0x85, 0x31, 0xe3, 0x43, 0xf3, 0x1b, 0x7c, 0xf7, 0x6b, 0x2c, 0xf8, 0x1c, 0xbb, 0x8d, 0xca, 0xab, 0x4b, 0xba, 0x7f, 0xa4, 0xe2}, + }, + { /* 35P*/ + addYX: fp.Elt{0x1a, 0xee, 0xe7, 0xa4, 0x8a, 0x9d, 0x53, 0x80, 0xc6, 0xb8, 0x4e, 0xdc, 0x89, 0xe0, 0xc4, 0x2b, 0x60, 0x52, 0x6f, 0xec, 0x81, 0xd2, 0x55, 0x6b, 0x1b, 0x6f, 0x17, 0x67, 0x8e, 0x42, 0x26, 0x4c, 0x65, 0x23, 0x29, 0xc6, 0x7b, 0xcd, 0x9f, 0xad, 0x4b, 0x42, 0xd3, 0x0c, 0x75, 0xc3, 0x8a, 0xf5, 0xbe, 0x9e, 0x55, 0xf7, 0x47, 0x5d, 0xbd, 0x3a}, + subYX: fp.Elt{0x0d, 0xa8, 0x3b, 0xf9, 0xc7, 0x7e, 0xc6, 0x86, 0x94, 0xc0, 0x01, 0xff, 0x27, 0xce, 0x43, 0xac, 0xe5, 0xe1, 0xd2, 0x8d, 0xc1, 0x22, 0x31, 0xbe, 0xe1, 0xaf, 0xf9, 0x4a, 0x78, 0xa1, 0x0c, 0xaa, 0xd4, 0x80, 0xe4, 0x09, 0x8d, 0xfb, 0x1d, 0x52, 0xc8, 0x60, 0x2d, 0xf2, 0xa2, 0x89, 0x02, 0x56, 0x3d, 0x56, 0x27, 0x85, 0xc7, 0xf0, 0x2b, 0x9a}, + dt2: fp.Elt{0x62, 0x7c, 0xc7, 0x6b, 0x2c, 0x9d, 0x0a, 0x7c, 0xe5, 0x50, 0x3c, 0xe6, 0x87, 0x1c, 0x82, 0x30, 0x67, 0x3c, 0x39, 0xb6, 0xa0, 0x31, 0xfb, 0x03, 0x7b, 0xa1, 0x58, 0xdf, 0x12, 0x76, 0x5d, 0x5d, 0x0a, 0x8f, 0x9b, 0x37, 0x32, 0xc3, 0x60, 0x33, 0xea, 0x9f, 0x0a, 0x99, 0xfa, 0x20, 0xd0, 0x33, 0x21, 0xc3, 0x94, 0xd4, 0x86, 0x49, 0x7c, 0x4e}, + }, + { /* 37P*/ + addYX: fp.Elt{0xc7, 0x0c, 0x71, 0xfe, 0x55, 0xd1, 0x95, 0x8f, 0x43, 0xbb, 0x6b, 0x74, 0x30, 0xbd, 0xe8, 0x6f, 0x1c, 0x1b, 0x06, 0x62, 0xf5, 0xfc, 0x65, 0xa0, 0xeb, 0x81, 0x12, 0xc9, 0x64, 0x66, 0x61, 0xde, 0xf3, 0x6d, 0xd4, 0xae, 0x8e, 0xb1, 0x72, 0xe0, 0xcd, 0x37, 0x01, 0x28, 0x52, 0xd7, 0x39, 0x46, 0x0c, 0x55, 0xcf, 0x47, 0x70, 0xef, 0xa1, 0x17}, + subYX: fp.Elt{0x8d, 0x58, 0xde, 0x83, 0x88, 0x16, 0x0e, 0x12, 0x42, 0x03, 0x50, 0x60, 0x4b, 0xdf, 0xbf, 0x95, 0xcc, 0x7d, 0x18, 0x17, 0x7e, 0x31, 0x5d, 0x8a, 0x66, 0xc1, 0xcf, 0x14, 0xea, 0xf4, 0xf4, 0xe5, 0x63, 0x2d, 0x32, 0x86, 0x9b, 0xed, 0x1f, 0x4f, 0x03, 0xaf, 0x33, 0x92, 0xcb, 0xaf, 0x9c, 0x05, 0x0d, 0x47, 0x1b, 0x42, 0xba, 0x13, 0x22, 0x98}, + dt2: fp.Elt{0xb5, 0x48, 0xeb, 0x7d, 0x3d, 0x10, 0x9f, 0x59, 0xde, 0xf8, 0x1c, 0x4f, 0x7d, 0x9d, 0x40, 0x4d, 0x9e, 0x13, 0x24, 0xb5, 0x21, 0x09, 0xb7, 0xee, 0x98, 0x5c, 0x56, 0xbc, 0x5e, 0x2b, 0x78, 0x38, 0x06, 0xac, 0xe3, 0xe0, 0xfa, 0x2e, 0xde, 0x4f, 0xd2, 0xb3, 0xfb, 0x2d, 0x71, 0x84, 0xd1, 0x9d, 0x12, 0x5b, 0x35, 0xc8, 0x03, 0x68, 0x67, 0xc7}, + }, + { /* 39P*/ + addYX: fp.Elt{0xb6, 0x65, 0xfb, 0xa7, 0x06, 0x35, 0xbb, 0xe0, 0x31, 0x8d, 0x91, 0x40, 0x98, 0xab, 0x30, 0xe4, 0xca, 0x12, 0x59, 0x89, 0xed, 0x65, 0x5d, 0x7f, 0xae, 0x69, 0xa0, 0xa4, 0xfa, 0x78, 0xb4, 0xf7, 0xed, 0xae, 0x86, 0x78, 0x79, 0x64, 0x24, 0xa6, 0xd4, 0xe1, 0xf6, 0xd3, 0xa0, 0x89, 0xba, 0x20, 0xf4, 0x54, 0x0d, 0x8f, 0xdb, 0x1a, 0x79, 0xdb}, + subYX: fp.Elt{0xe1, 0x82, 0x0c, 0x4d, 0xde, 0x9f, 0x40, 0xf0, 0xc1, 0xbd, 0x8b, 0xd3, 0x24, 0x03, 0xcd, 0xf2, 0x92, 0x7d, 0xe2, 0x68, 0x7f, 0xf1, 0xbe, 0x69, 0xde, 0x34, 0x67, 0x4c, 0x85, 0x3b, 0xec, 0x98, 0xcc, 0x4d, 0x3e, 0xc0, 0x96, 0x27, 0xe6, 0x75, 0xfc, 0xdf, 0x37, 0xc0, 0x1e, 0x27, 0xe0, 0xf6, 0xc2, 0xbd, 0xbc, 0x3d, 0x9b, 0x39, 0xdc, 0xe2}, + dt2: fp.Elt{0xd8, 0x29, 0xa7, 0x39, 0xe3, 0x9f, 0x2f, 0x0e, 0x4b, 0x24, 0x21, 0x70, 0xef, 0xfd, 0x91, 0xea, 0xbf, 0xe1, 0x72, 0x90, 0xcc, 0xc9, 0x84, 0x0e, 0xad, 0xd5, 0xe6, 0xbb, 0xc5, 0x99, 0x7f, 0xa4, 0xf0, 0x2e, 0xcc, 0x95, 0x64, 0x27, 0x19, 0xd8, 0x4c, 0x27, 0x0d, 0xff, 0xb6, 0x29, 0xe2, 0x6c, 0xfa, 0xbb, 0x4d, 0x9c, 0xbb, 0xaf, 0xa5, 0xec}, + }, + { /* 41P*/ + addYX: fp.Elt{0xd6, 0x33, 0x3f, 0x9f, 0xcf, 0xfd, 0x4c, 0xd1, 0xfe, 0xe5, 0xeb, 0x64, 0x27, 0xae, 0x7a, 0xa2, 0x82, 0x50, 0x6d, 0xaa, 0xe3, 0x5d, 0xe2, 0x48, 0x60, 0xb3, 0x76, 0x04, 0xd9, 0x19, 0xa7, 0xa1, 0x73, 0x8d, 0x38, 0xa9, 0xaf, 0x45, 0xb5, 0xb2, 0x62, 0x9b, 0xf1, 0x35, 0x7b, 0x84, 0x66, 0xeb, 0x06, 0xef, 0xf1, 0xb2, 0x2d, 0x6a, 0x61, 0x15}, + subYX: fp.Elt{0x86, 0x50, 0x42, 0xf7, 0xda, 0x59, 0xb2, 0xcf, 0x0d, 0x3d, 0xee, 0x8e, 0x53, 0x5d, 0xf7, 0x9e, 0x6a, 0x26, 0x2d, 0xc7, 0x8c, 0x8e, 0x18, 0x50, 0x6d, 0xb7, 0x51, 0x4c, 0xa7, 0x52, 0x6e, 0x0e, 0x0a, 0x16, 0x74, 0xb2, 0x81, 0x8b, 0x56, 0x27, 0x22, 0x84, 0xf4, 0x56, 0xc5, 0x06, 0xe1, 0x8b, 0xca, 0x2d, 0xdb, 0x9a, 0xf6, 0x10, 0x9c, 0x51}, + dt2: fp.Elt{0x1f, 0x16, 0xa2, 0x78, 0x96, 0x1b, 0x85, 0x9c, 0x76, 0x49, 0xd4, 0x0f, 0xac, 0xb0, 0xf4, 0xd0, 0x06, 0x2c, 0x7e, 0x6d, 0x6e, 0x8e, 0xc7, 0x9f, 0x18, 0xad, 0xfc, 0x88, 0x0c, 0x0c, 0x09, 0x05, 0x05, 0xa0, 0x79, 0x72, 0x32, 0x72, 0x87, 0x0f, 0x49, 0x87, 0x0c, 0xb4, 0x12, 0xc2, 0x09, 0xf8, 0x9f, 0x30, 0x72, 0xa9, 0x47, 0x13, 0x93, 0x49}, + }, + { /* 43P*/ + addYX: fp.Elt{0xcc, 0xb1, 0x4c, 0xd3, 0xc0, 0x9e, 0x9e, 0x4d, 0x6d, 0x28, 0x0b, 0xa5, 0x94, 0xa7, 0x2e, 0xc2, 0xc7, 0xaf, 0x29, 0x73, 0xc9, 0x68, 0xea, 0x0f, 0x34, 0x37, 0x8d, 0x96, 0x8f, 0x3a, 0x3d, 0x73, 0x1e, 0x6d, 0x9f, 0xcf, 0x8d, 0x83, 0xb5, 0x71, 0xb9, 0xe1, 0x4b, 0x67, 0x71, 0xea, 0xcf, 0x56, 0xe5, 0xeb, 0x72, 0x15, 0x2f, 0x9e, 0xa8, 0xaa}, + subYX: fp.Elt{0xf4, 0x3e, 0x85, 0x1c, 0x1a, 0xef, 0x50, 0xd1, 0xb4, 0x20, 0xb2, 0x60, 0x05, 0x98, 0xfe, 0x47, 0x3b, 0xc1, 0x76, 0xca, 0x2c, 0x4e, 0x5a, 0x42, 0xa3, 0xf7, 0x20, 0xaa, 0x57, 0x39, 0xee, 0x34, 0x1f, 0xe1, 0x68, 0xd3, 0x7e, 0x06, 0xc4, 0x6c, 0xc7, 0x76, 0x2b, 0xe4, 0x1c, 0x48, 0x44, 0xe6, 0xe5, 0x44, 0x24, 0x8d, 0xb3, 0xb6, 0x88, 0x32}, + dt2: fp.Elt{0x18, 0xa7, 0xba, 0xd0, 0x44, 0x6f, 0x33, 0x31, 0x00, 0xf8, 0xf6, 0x12, 0xe3, 0xc5, 0xc7, 0xb5, 0x91, 0x9c, 0x91, 0xb5, 0x75, 0x18, 0x18, 0x8a, 0xab, 0xed, 0x24, 0x11, 0x2e, 0xce, 0x5a, 0x0f, 0x94, 0x5f, 0x2e, 0xca, 0xd3, 0x80, 0xea, 0xe5, 0x34, 0x96, 0x67, 0x8b, 0x6a, 0x26, 0x5e, 0xc8, 0x9d, 0x2c, 0x5e, 0x6c, 0xa2, 0x0c, 0xbf, 0xf0}, + }, + { /* 45P*/ + addYX: fp.Elt{0xb3, 0xbf, 0xa3, 0x85, 0xee, 0xf6, 0x58, 0x02, 0x78, 0xc4, 0x30, 0xd6, 0x57, 0x59, 0x8c, 0x88, 0x08, 0x7c, 0xbc, 0xbe, 0x0a, 0x74, 0xa9, 0xde, 0x69, 0xe7, 0x41, 0xd8, 0xbf, 0x66, 0x8d, 0x3d, 0x28, 0x00, 0x8c, 0x47, 0x65, 0x34, 0xfe, 0x86, 0x9e, 0x6a, 0xf2, 0x41, 0x6a, 0x94, 0xc4, 0x88, 0x75, 0x23, 0x0d, 0x52, 0x69, 0xee, 0x07, 0x89}, + subYX: fp.Elt{0x22, 0x3c, 0xa1, 0x70, 0x58, 0x97, 0x93, 0xbe, 0x59, 0xa8, 0x0b, 0x8a, 0x46, 0x2a, 0x38, 0x1e, 0x08, 0x6b, 0x61, 0x9f, 0xf2, 0x4a, 0x8b, 0x80, 0x68, 0x6e, 0xc8, 0x92, 0x60, 0xf3, 0xc9, 0x89, 0xb2, 0x6d, 0x63, 0xb0, 0xeb, 0x83, 0x15, 0x63, 0x0e, 0x64, 0xbb, 0xb8, 0xfe, 0xb4, 0x81, 0x90, 0x01, 0x28, 0x10, 0xb9, 0x74, 0x6e, 0xde, 0xa4}, + dt2: fp.Elt{0x1a, 0x23, 0x45, 0xa8, 0x6f, 0x4e, 0xa7, 0x4a, 0x0c, 0xeb, 0xb0, 0x43, 0xf9, 0xef, 0x99, 0x60, 0x5b, 0xdb, 0x66, 0xc0, 0x86, 0x71, 0x43, 0xb1, 0x22, 0x7b, 0x1c, 0xe7, 0x8d, 0x09, 0x1d, 0x83, 0x76, 0x9c, 0xd3, 0x5a, 0xdd, 0x42, 0xd9, 0x2f, 0x2d, 0xba, 0x7a, 0xc2, 0xd9, 0x6b, 0xd4, 0x7a, 0xf1, 0xd5, 0x5f, 0x6b, 0x85, 0xbf, 0x0b, 0xf1}, + }, + { /* 47P*/ + addYX: fp.Elt{0xb2, 0x83, 0xfa, 0x1f, 0xd2, 0xce, 0xb6, 0xf2, 0x2d, 0xea, 0x1b, 0xe5, 0x29, 0xa5, 0x72, 0xf9, 0x25, 0x48, 0x4e, 0xf2, 0x50, 0x1b, 0x39, 0xda, 0x34, 0xc5, 0x16, 0x13, 0xb4, 0x0c, 0xa1, 0x00, 0x79, 0x7a, 0xf5, 0x8b, 0xf3, 0x70, 0x14, 0xb6, 0xfc, 0x9a, 0x47, 0x68, 0x1e, 0x42, 0x70, 0x64, 0x2a, 0x84, 0x3e, 0x3d, 0x20, 0x58, 0xf9, 0x6a}, + subYX: fp.Elt{0xd9, 0xee, 0xc0, 0xc4, 0xf5, 0xc2, 0x86, 0xaf, 0x45, 0xd2, 0xd2, 0x87, 0x1b, 0x64, 0xd5, 0xe0, 0x8c, 0x44, 0x00, 0x4f, 0x43, 0x89, 0x04, 0x48, 0x4a, 0x0b, 0xca, 0x94, 0x06, 0x2f, 0x23, 0x5b, 0x6c, 0x8d, 0x44, 0x66, 0x53, 0xf5, 0x5a, 0x20, 0x72, 0x28, 0x58, 0x84, 0xcc, 0x73, 0x22, 0x5e, 0xd1, 0x0b, 0x56, 0x5e, 0x6a, 0xa3, 0x11, 0x91}, + dt2: fp.Elt{0x6e, 0x9f, 0x88, 0xa8, 0x68, 0x2f, 0x12, 0x37, 0x88, 0xfc, 0x92, 0x8f, 0x24, 0xeb, 0x5b, 0x2a, 0x2a, 0xd0, 0x14, 0x40, 0x4c, 0xa9, 0xa4, 0x03, 0x0c, 0x45, 0x48, 0x13, 0xe8, 0xa6, 0x37, 0xab, 0xc0, 0x06, 0x38, 0x6c, 0x96, 0x73, 0x40, 0x6c, 0xc6, 0xea, 0x56, 0xc6, 0xe9, 0x1a, 0x69, 0xeb, 0x7a, 0xd1, 0x33, 0x69, 0x58, 0x2b, 0xea, 0x2f}, + }, + { /* 49P*/ + addYX: fp.Elt{0x58, 0xa8, 0x05, 0x41, 0x00, 0x9d, 0xaa, 0xd9, 0x98, 0xcf, 0xb9, 0x41, 0xb5, 0x4a, 0x8d, 0xe2, 0xe7, 0xc0, 0x72, 0xef, 0xc8, 0x28, 0x6b, 0x68, 0x9d, 0xc9, 0xdf, 0x05, 0x8b, 0xd0, 0x04, 0x74, 0x79, 0x45, 0x52, 0x05, 0xa3, 0x6e, 0x35, 0x3a, 0xe3, 0xef, 0xb2, 0xdc, 0x08, 0x6f, 0x4e, 0x76, 0x85, 0x67, 0xba, 0x23, 0x8f, 0xdd, 0xaf, 0x09}, + subYX: fp.Elt{0xb4, 0x38, 0xc8, 0xff, 0x4f, 0x65, 0x2a, 0x7e, 0xad, 0xb1, 0xc6, 0xb9, 0x3d, 0xd6, 0xf7, 0x14, 0xcf, 0xf6, 0x98, 0x75, 0xbb, 0x47, 0x83, 0x90, 0xe7, 0xe1, 0xf6, 0x14, 0x99, 0x7e, 0xfa, 0xe4, 0x77, 0x24, 0xe3, 0xe7, 0xf0, 0x1e, 0xdb, 0x27, 0x4e, 0x16, 0x04, 0xf2, 0x08, 0x52, 0xfc, 0xec, 0x55, 0xdb, 0x2e, 0x67, 0xe1, 0x94, 0x32, 0x89}, + dt2: fp.Elt{0x00, 0xad, 0x03, 0x35, 0x1a, 0xb1, 0x88, 0xf0, 0xc9, 0x11, 0xe4, 0x12, 0x52, 0x61, 0xfd, 0x8a, 0x1b, 0x6a, 0x0a, 0x4c, 0x42, 0x46, 0x22, 0x0e, 0xa5, 0xf9, 0xe2, 0x50, 0xf2, 0xb2, 0x1f, 0x20, 0x78, 0x10, 0xf6, 0xbf, 0x7f, 0x0c, 0x9c, 0xad, 0x40, 0x8b, 0x82, 0xd4, 0xba, 0x69, 0x09, 0xac, 0x4b, 0x6d, 0xc4, 0x49, 0x17, 0x81, 0x57, 0x3b}, + }, + { /* 51P*/ + addYX: fp.Elt{0x0d, 0xfe, 0xb4, 0x35, 0x11, 0xbd, 0x1d, 0x6b, 0xc2, 0xc5, 0x3b, 0xd2, 0x23, 0x2c, 0x72, 0xe3, 0x48, 0xb1, 0x48, 0x73, 0xfb, 0xa3, 0x21, 0x6e, 0xc0, 0x09, 0x69, 0xac, 0xe1, 0x60, 0xbc, 0x24, 0x03, 0x99, 0x63, 0x0a, 0x00, 0xf0, 0x75, 0xf6, 0x92, 0xc5, 0xd6, 0xdb, 0x51, 0xd4, 0x7d, 0xe6, 0xf4, 0x11, 0x79, 0xd7, 0xc3, 0xaf, 0x48, 0xd0}, + subYX: fp.Elt{0xf4, 0x4f, 0xaf, 0x31, 0xe3, 0x10, 0x89, 0x95, 0xf0, 0x8a, 0xf6, 0x31, 0x9f, 0x48, 0x02, 0xba, 0x42, 0x2b, 0x3c, 0x22, 0x8b, 0xcc, 0x12, 0x98, 0x6e, 0x7a, 0x64, 0x3a, 0xc4, 0xca, 0x32, 0x2a, 0x72, 0xf8, 0x2c, 0xcf, 0x78, 0x5e, 0x7a, 0x75, 0x6e, 0x72, 0x46, 0x48, 0x62, 0x28, 0xac, 0x58, 0x1a, 0xc6, 0x59, 0x88, 0x2a, 0x44, 0x9e, 0x83}, + dt2: fp.Elt{0xb3, 0xde, 0x36, 0xfd, 0xeb, 0x1b, 0xd4, 0x24, 0x1b, 0x08, 0x8c, 0xfe, 0xa9, 0x41, 0xa1, 0x64, 0xf2, 0x6d, 0xdb, 0xf9, 0x94, 0xae, 0x86, 0x71, 0xab, 0x10, 0xbf, 0xa3, 0xb2, 0xa0, 0xdf, 0x10, 0x8c, 0x74, 0xce, 0xb3, 0xfc, 0xdb, 0xba, 0x15, 0xf6, 0x91, 0x7a, 0x9c, 0x36, 0x1e, 0x45, 0x07, 0x3c, 0xec, 0x1a, 0x61, 0x26, 0x93, 0xe3, 0x50}, + }, + { /* 53P*/ + addYX: fp.Elt{0xc5, 0x50, 0xc5, 0x83, 0xb0, 0xbd, 0xd9, 0xf6, 0x6d, 0x15, 0x5e, 0xc1, 0x1a, 0x33, 0xa0, 0xce, 0x13, 0x70, 0x3b, 0xe1, 0x31, 0xc6, 0xc4, 0x02, 0xec, 0x8c, 0xd5, 0x9c, 0x97, 0xd3, 0x12, 0xc4, 0xa2, 0xf9, 0xd5, 0xfb, 0x22, 0x69, 0x94, 0x09, 0x2f, 0x59, 0xce, 0xdb, 0xf2, 0xf2, 0x00, 0xe0, 0xa9, 0x08, 0x44, 0x2e, 0x8b, 0x6b, 0xf5, 0xb3}, + subYX: fp.Elt{0x90, 0xdd, 0xec, 0xa2, 0x65, 0xb7, 0x61, 0xbc, 0xaa, 0x70, 0xa2, 0x15, 0xd8, 0xb0, 0xf8, 0x8e, 0x23, 0x3d, 0x9f, 0x46, 0xa3, 0x29, 0x20, 0xd1, 0xa1, 0x15, 0x81, 0xc6, 0xb6, 0xde, 0xbe, 0x60, 0x63, 0x24, 0xac, 0x15, 0xfb, 0xeb, 0xd3, 0xea, 0x57, 0x13, 0x86, 0x38, 0x1e, 0x22, 0xf4, 0x8c, 0x5d, 0xaf, 0x1b, 0x27, 0x21, 0x4f, 0xa3, 0x63}, + dt2: fp.Elt{0x07, 0x15, 0x87, 0xc4, 0xfd, 0xa1, 0x97, 0x7a, 0x07, 0x1f, 0x56, 0xcc, 0xe3, 0x6a, 0x01, 0x90, 0xce, 0xf9, 0xfa, 0x50, 0xb2, 0xe0, 0x87, 0x8b, 0x6c, 0x63, 0x6c, 0xf6, 0x2a, 0x09, 0xef, 0xef, 0xd2, 0x31, 0x40, 0x25, 0xf6, 0x84, 0xcb, 0xe0, 0xc4, 0x23, 0xc1, 0xcb, 0xe2, 0x02, 0x83, 0x2d, 0xed, 0x74, 0x74, 0x8b, 0xf8, 0x7c, 0x81, 0x18}, + }, + { /* 55P*/ + addYX: fp.Elt{0x9e, 0xe5, 0x59, 0x95, 0x63, 0x2e, 0xac, 0x8b, 0x03, 0x3c, 0xc1, 0x8e, 0xe1, 0x5b, 0x56, 0x3c, 0x16, 0x41, 0xe4, 0xc2, 0x60, 0x0c, 0x6d, 0x65, 0x9f, 0xfc, 0x27, 0x68, 0x43, 0x44, 0x05, 0x12, 0x6c, 0xda, 0x04, 0xef, 0xcf, 0xcf, 0xdc, 0x0a, 0x1a, 0x7f, 0x12, 0xd3, 0xeb, 0x02, 0xb6, 0x04, 0xca, 0xd6, 0xcb, 0xf0, 0x22, 0xba, 0x35, 0x6d}, + subYX: fp.Elt{0x09, 0x6d, 0xf9, 0x64, 0x4c, 0xe6, 0x41, 0xff, 0x01, 0x4d, 0xce, 0x1e, 0xfa, 0x38, 0xa2, 0x25, 0x62, 0xff, 0x03, 0x39, 0x18, 0x91, 0xbb, 0x9d, 0xce, 0x02, 0xf0, 0xf1, 0x3c, 0x55, 0x18, 0xa9, 0xab, 0x4d, 0xd2, 0x35, 0xfd, 0x8d, 0xa9, 0xb2, 0xad, 0xb7, 0x06, 0x6e, 0xc6, 0x69, 0x49, 0xd6, 0x98, 0x98, 0x0b, 0x22, 0x81, 0x6b, 0xbd, 0xa0}, + dt2: fp.Elt{0x22, 0xf4, 0x85, 0x5d, 0x2b, 0xf1, 0x55, 0xa5, 0xd6, 0x27, 0x86, 0x57, 0x12, 0x1f, 0x16, 0x0a, 0x5a, 0x9b, 0xf2, 0x38, 0xb6, 0x28, 0xd8, 0x99, 0x0c, 0x89, 0x1d, 0x7f, 0xca, 0x21, 0x17, 0x1a, 0x0b, 0x02, 0x5f, 0x77, 0x2f, 0x73, 0x30, 0x7c, 0xc8, 0xd7, 0x2b, 0xcc, 0xe7, 0xf3, 0x21, 0xac, 0x53, 0xa7, 0x11, 0x5d, 0xd8, 0x1d, 0x9b, 0xf5}, + }, + { /* 57P*/ + addYX: fp.Elt{0x94, 0x63, 0x5d, 0xef, 0xfd, 0x6d, 0x25, 0x4e, 0x6d, 0x29, 0x03, 0xed, 0x24, 0x28, 0x27, 0x57, 0x47, 0x3e, 0x6a, 0x1a, 0xfe, 0x37, 0xee, 0x5f, 0x83, 0x29, 0x14, 0xfd, 0x78, 0x25, 0x8a, 0xe1, 0x02, 0x38, 0xd8, 0xca, 0x65, 0x55, 0x40, 0x7d, 0x48, 0x2c, 0x7c, 0x7e, 0x60, 0xb6, 0x0c, 0x6d, 0xf7, 0xe8, 0xb3, 0x62, 0x53, 0xd6, 0x9c, 0x2b}, + subYX: fp.Elt{0x47, 0x25, 0x70, 0x62, 0xf5, 0x65, 0x93, 0x62, 0x08, 0xac, 0x59, 0x66, 0xdb, 0x08, 0xd9, 0x1a, 0x19, 0xaf, 0xf4, 0xef, 0x02, 0xa2, 0x78, 0xa9, 0x55, 0x1c, 0xfa, 0x08, 0x11, 0xcb, 0xa3, 0x71, 0x74, 0xb1, 0x62, 0xe7, 0xc7, 0xf3, 0x5a, 0xb5, 0x8b, 0xd4, 0xf6, 0x10, 0x57, 0x79, 0x72, 0x2f, 0x13, 0x86, 0x7b, 0x44, 0x5f, 0x48, 0xfd, 0x88}, + dt2: fp.Elt{0x10, 0x02, 0xcd, 0x05, 0x9a, 0xc3, 0x32, 0x6d, 0x10, 0x3a, 0x74, 0xba, 0x06, 0xc4, 0x3b, 0x34, 0xbc, 0x36, 0xed, 0xa3, 0xba, 0x9a, 0xdb, 0x6d, 0xd4, 0x69, 0x99, 0x97, 0xd0, 0xe4, 0xdd, 0xf5, 0xd4, 0x7c, 0xd3, 0x4e, 0xab, 0xd1, 0x3b, 0xbb, 0xe9, 0xc7, 0x6a, 0x94, 0x25, 0x61, 0xf0, 0x06, 0xc5, 0x12, 0xa8, 0x86, 0xe5, 0x35, 0x46, 0xeb}, + }, + { /* 59P*/ + addYX: fp.Elt{0x9e, 0x95, 0x11, 0xc6, 0xc7, 0xe8, 0xee, 0x5a, 0x26, 0xa0, 0x72, 0x72, 0x59, 0x91, 0x59, 0x16, 0x49, 0x99, 0x7e, 0xbb, 0xd7, 0x15, 0xb4, 0xf2, 0x40, 0xf9, 0x5a, 0x4d, 0xc8, 0xa0, 0xe2, 0x34, 0x7b, 0x34, 0xf3, 0x99, 0xbf, 0xa9, 0xf3, 0x79, 0xc1, 0x1a, 0x0c, 0xf4, 0x86, 0x74, 0x4e, 0xcb, 0xbc, 0x90, 0xad, 0xb6, 0x51, 0x6d, 0xaa, 0x33}, + subYX: fp.Elt{0x9f, 0xd1, 0xc5, 0xa2, 0x6c, 0x24, 0x88, 0x15, 0x71, 0x68, 0xf6, 0x07, 0x45, 0x02, 0xc4, 0x73, 0x7e, 0x75, 0x87, 0xca, 0x7c, 0xf0, 0x92, 0x00, 0x75, 0xd6, 0x5a, 0xdd, 0xe0, 0x64, 0x16, 0x9d, 0x62, 0x80, 0x33, 0x9f, 0xf4, 0x8e, 0x1a, 0x15, 0x1c, 0xd3, 0x0f, 0x4d, 0x4f, 0x62, 0x2d, 0xd7, 0xa5, 0x77, 0xe3, 0xea, 0xf0, 0xfb, 0x1a, 0xdb}, + dt2: fp.Elt{0x6a, 0xa2, 0xb1, 0xaa, 0xfb, 0x5a, 0x32, 0x4e, 0xff, 0x47, 0x06, 0xd5, 0x9a, 0x4f, 0xce, 0x83, 0x5b, 0x82, 0x34, 0x3e, 0x47, 0xb8, 0xf8, 0xe9, 0x7c, 0x67, 0x69, 0x8d, 0x9c, 0xb7, 0xde, 0x57, 0xf4, 0x88, 0x41, 0x56, 0x0c, 0x87, 0x1e, 0xc9, 0x2f, 0x54, 0xbf, 0x5c, 0x68, 0x2c, 0xd9, 0xc4, 0xef, 0x53, 0x73, 0x1e, 0xa6, 0x38, 0x02, 0x10}, + }, + { /* 61P*/ + addYX: fp.Elt{0x08, 0x80, 0x4a, 0xc9, 0xb7, 0xa8, 0x88, 0xd9, 0xfc, 0x6a, 0xc0, 0x3e, 0xc2, 0x33, 0x4d, 0x2b, 0x2a, 0xa3, 0x6d, 0x72, 0x3e, 0xdc, 0x34, 0x68, 0x08, 0xbf, 0x27, 0xef, 0xf4, 0xff, 0xe2, 0x0c, 0x31, 0x0c, 0xa2, 0x0a, 0x1f, 0x65, 0xc1, 0x4c, 0x61, 0xd3, 0x1b, 0xbc, 0x25, 0xb1, 0xd0, 0xd4, 0x89, 0xb2, 0x53, 0xfb, 0x43, 0xa5, 0xaf, 0x04}, + subYX: fp.Elt{0xe3, 0xe1, 0x37, 0xad, 0x58, 0xa9, 0x55, 0x81, 0xee, 0x64, 0x21, 0xb9, 0xf5, 0x4c, 0x35, 0xea, 0x4a, 0xd3, 0x26, 0xaa, 0x90, 0xd4, 0x60, 0x46, 0x09, 0x4b, 0x4a, 0x62, 0xf9, 0xcd, 0xe1, 0xee, 0xbb, 0xc2, 0x09, 0x0b, 0xb0, 0x96, 0x8e, 0x43, 0x77, 0xaf, 0x25, 0x20, 0x5e, 0x47, 0xe4, 0x1d, 0x50, 0x69, 0x74, 0x08, 0xd7, 0xb9, 0x90, 0x13}, + dt2: fp.Elt{0x51, 0x91, 0x95, 0x64, 0x03, 0x16, 0xfd, 0x6e, 0x26, 0x94, 0x6b, 0x61, 0xe7, 0xd9, 0xe0, 0x4a, 0x6d, 0x7c, 0xfa, 0xc0, 0xe2, 0x43, 0x23, 0x53, 0x70, 0xf5, 0x6f, 0x73, 0x8b, 0x81, 0xb0, 0x0c, 0xee, 0x2e, 0x46, 0xf2, 0x8d, 0xa6, 0xfb, 0xb5, 0x1c, 0x33, 0xbf, 0x90, 0x59, 0xc9, 0x7c, 0xb8, 0x6f, 0xad, 0x75, 0x02, 0x90, 0x8e, 0x59, 0x75}, + }, + { /* 63P*/ + addYX: fp.Elt{0x36, 0x4d, 0x77, 0x04, 0xb8, 0x7d, 0x4a, 0xd1, 0xc5, 0xbb, 0x7b, 0x50, 0x5f, 0x8d, 0x9d, 0x62, 0x0f, 0x66, 0x71, 0xec, 0x87, 0xc5, 0x80, 0x82, 0xc8, 0xf4, 0x6a, 0x94, 0x92, 0x5b, 0xb0, 0x16, 0x9b, 0xb2, 0xc9, 0x6f, 0x2b, 0x2d, 0xee, 0x95, 0x73, 0x2e, 0xc2, 0x1b, 0xc5, 0x55, 0x36, 0x86, 0x24, 0xf8, 0x20, 0x05, 0x0d, 0x93, 0xd7, 0x76}, + subYX: fp.Elt{0x7f, 0x01, 0xeb, 0x2e, 0x48, 0x4d, 0x1d, 0xf1, 0x06, 0x7e, 0x7c, 0x2a, 0x43, 0xbf, 0x28, 0xac, 0xe9, 0x58, 0x13, 0xc8, 0xbf, 0x8e, 0xc0, 0xef, 0xe8, 0x4f, 0x46, 0x8a, 0xe7, 0xc0, 0xf6, 0x0f, 0x0a, 0x03, 0x48, 0x91, 0x55, 0x39, 0x2a, 0xe3, 0xdc, 0xf6, 0x22, 0x9d, 0x4d, 0x71, 0x55, 0x68, 0x25, 0x6e, 0x95, 0x52, 0xee, 0x4c, 0xd9, 0x01}, + dt2: fp.Elt{0xac, 0x33, 0x3f, 0x7c, 0x27, 0x35, 0x15, 0x91, 0x33, 0x8d, 0xf9, 0xc4, 0xf4, 0xf3, 0x90, 0x09, 0x75, 0x69, 0x62, 0x9f, 0x61, 0x35, 0x83, 0x92, 0x04, 0xef, 0x96, 0x38, 0x80, 0x9e, 0x88, 0xb3, 0x67, 0x95, 0xbe, 0x79, 0x3c, 0x35, 0xd8, 0xdc, 0xb2, 0x3e, 0x2d, 0xe6, 0x46, 0xbe, 0x81, 0xf3, 0x32, 0x0e, 0x37, 0x23, 0x75, 0x2a, 0x3d, 0xa0}, + }, +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go new file mode 100644 index 00000000000..f6ac5edbbbc --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go @@ -0,0 +1,62 @@ +package goldilocks + +import ( + "crypto/subtle" + + mlsb "github.com/cloudflare/circl/math/mlsbset" +) + +const ( + // MLSBRecoding parameters + fxT = 448 + fxV = 2 + fxW = 3 + fx2w1 = 1 << (uint(fxW) - 1) +) + +// ScalarBaseMult returns kG where G is the generator point. +func (e twistCurve) ScalarBaseMult(k *Scalar) *twistPoint { + m, err := mlsb.New(fxT, fxV, fxW) + if err != nil { + panic(err) + } + if m.IsExtended() { + panic("not extended") + } + + var isZero int + if k.IsZero() { + isZero = 1 + } + subtle.ConstantTimeCopy(isZero, k[:], order[:]) + + minusK := *k + isEven := 1 - int(k[0]&0x1) + minusK.Neg() + subtle.ConstantTimeCopy(isEven, k[:], minusK[:]) + c, err := m.Encode(k[:]) + if err != nil { + panic(err) + } + + gP := c.Exp(groupMLSB{}) + P := gP.(*twistPoint) + P.cneg(uint(isEven)) + return P +} + +type groupMLSB struct{} + +func (e groupMLSB) ExtendedEltP() mlsb.EltP { return nil } +func (e groupMLSB) Sqr(x mlsb.EltG) { x.(*twistPoint).Double() } +func (e groupMLSB) Mul(x mlsb.EltG, y mlsb.EltP) { x.(*twistPoint).mixAddZ1(y.(*preTwistPointAffine)) } +func (e groupMLSB) Identity() mlsb.EltG { return twistCurve{}.Identity() } +func (e groupMLSB) NewEltP() mlsb.EltP { return &preTwistPointAffine{} } +func (e groupMLSB) Lookup(a mlsb.EltP, v uint, s, u int32) { + Tabj := &tabFixMult[v] + P := a.(*preTwistPointAffine) + for k := range Tabj { + P.cmov(&Tabj[k], uint(subtle.ConstantTimeEq(int32(k), u))) + } + P.cneg(int(s >> 31)) +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/LICENSE b/src/vendor/github.com/cloudflare/circl/ecc/p384/LICENSE new file mode 100644 index 00000000000..4e5596db89d --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2018, Brendan McMillion. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go new file mode 100644 index 00000000000..889e7771f1d --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go @@ -0,0 +1,149 @@ +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 + +package p384 + +import ( + "math/big" + + "github.com/cloudflare/circl/internal/conv" +) + +const sizeFp = 48 + +type fp384 [sizeFp]byte + +func (e fp384) BigInt() *big.Int { return conv.BytesLe2BigInt(e[:]) } +func (e fp384) String() string { return conv.BytesLe2Hex(e[:]) } + +func (e *fp384) SetBigInt(b *big.Int) { + if b.BitLen() > 384 || b.Sign() < 0 { + b = new(big.Int).Mod(b, p.BigInt()) + } + conv.BigInt2BytesLe(e[:], b) +} + +func montEncode(c, a *fp384) { fp384Mul(c, a, &r2) } +func montDecode(c, a *fp384) { fp384Mul(c, a, &fp384{1}) } +func fp384Sqr(c, a *fp384) { fp384Mul(c, a, a) } + +func fp384Inv(z, x *fp384) { + t0, t1, t2, t3, t4 := &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{} + /* alpha_1 */ + fp384Sqr(t4, x) + /* alpha_2 */ + fp384Mul(t4, t4, x) + /* alpha_3 */ + fp384Sqr(t0, t4) + fp384Mul(t0, t0, x) + /* alpha_6 */ + fp384Sqr(t1, t0) + fp384Sqr(t1, t1) + fp384Sqr(t1, t1) + fp384Mul(t1, t1, t0) + /* alpha_12 */ + fp384Sqr(t2, t1) + for i := 0; i < 5; i++ { + fp384Sqr(t2, t2) + } + fp384Mul(t2, t2, t1) + /* alpha_15 */ + for i := 0; i < 3; i++ { + fp384Sqr(t2, t2) + } + fp384Mul(t2, t2, t0) + /* alpha_30 */ + fp384Sqr(t1, t2) + for i := 0; i < 14; i++ { + fp384Sqr(t1, t1) + } + fp384Mul(t1, t1, t2) + /* alpha_60 */ + fp384Sqr(t3, t1) + for i := 0; i < 29; i++ { + fp384Sqr(t3, t3) + } + fp384Mul(t3, t3, t1) + /* T_3 = alpha_30^(2^2) */ + fp384Sqr(t1, t1) + fp384Sqr(t1, t1) + /* alpha_32 */ + *t0 = *t1 + fp384Mul(t0, t0, t4) + /* T_3 = a^(2^32-3) = (alpha_30)^(2^2)*alpha_1 */ + fp384Mul(t1, t1, x) + /* alpha_120 */ + fp384Sqr(t4, t3) + for i := 0; i < 59; i++ { + fp384Sqr(t4, t4) + } + fp384Mul(t4, t4, t3) + /* alpha_240 */ + fp384Sqr(t3, t4) + for i := 0; i < 119; i++ { + fp384Sqr(t3, t3) + } + fp384Mul(t3, t3, t4) + /* alpha_255 */ + for i := 0; i < 15; i++ { + fp384Sqr(t3, t3) + } + fp384Mul(t3, t3, t2) + /* T_5 = a^(2^288-2^32-1) = (alpha_255)^(2^33)*alpha_32 */ + for i := 0; i < 33; i++ { + fp384Sqr(t3, t3) + } + fp384Mul(t3, t3, t0) + /* T_1 = a^(2^384-2^128-2^96+2^32-3) = (T_1)^(2^96)*T_3 */ + fp384Sqr(t4, t3) + for i := 0; i < 95; i++ { + fp384Sqr(t4, t4) + } + fp384Mul(z, t4, t1) +} + +//go:noescape +func fp384Cmov(x, y *fp384, b int) + +//go:noescape +func fp384Neg(c, a *fp384) + +//go:noescape +func fp384Add(c, a, b *fp384) + +//go:noescape +func fp384Sub(c, a, b *fp384) + +//go:noescape +func fp384Mul(c, a, b *fp384) + +var ( + // p is the order of the base field, represented as little-endian 64-bit words. + p = fp384{ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + } + // pp satisfies r*rp - p*pp = 1 where rp and pp are both integers. + pp = fp384{ //nolint + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, + 0xfa, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + } + // r2 is R^2 where R = 2^384 mod p. + r2 = fp384{ + 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + } + // bb is the Montgomery encoding of the curve parameter B. + bb = fp384{ + 0xcc, 0x2d, 0x41, 0x9d, 0x71, 0x88, 0x11, 0x08, 0xec, 0x32, 0x4c, 0x7a, + 0xd8, 0xad, 0x29, 0xf7, 0x2e, 0x02, 0x20, 0x19, 0x9b, 0x20, 0xf2, 0x77, + 0xe2, 0x8a, 0x93, 0x94, 0xee, 0x4b, 0x37, 0xe3, 0x94, 0x20, 0x02, 0x1f, + 0xf4, 0x21, 0x2b, 0xb6, 0xf9, 0xbf, 0x4f, 0x60, 0x4b, 0x11, 0x08, 0xcd, + } +) diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.go new file mode 100644 index 00000000000..2e9d8fddb5e --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.go @@ -0,0 +1,8 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package p384 + +import "golang.org/x/sys/cpu" + +var hasBMI2 = cpu.X86.HasBMI2 //nolint diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.s b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.s new file mode 100644 index 00000000000..eaf6fb7a771 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.s @@ -0,0 +1,730 @@ +// +build amd64,!purego + +#include "textflag.h" + +#define storeBlock(a0,a1,a2,a3,a4,a5, r) \ + MOVQ a0, 0+r \ + MOVQ a1, 8+r \ + MOVQ a2, 16+r \ + MOVQ a3, 24+r \ + MOVQ a4, 32+r \ + MOVQ a5, 40+r + +#define loadBlock(r, a0,a1,a2,a3,a4,a5) \ + MOVQ 0+r, a0 \ + MOVQ 8+r, a1 \ + MOVQ 16+r, a2 \ + MOVQ 24+r, a3 \ + MOVQ 32+r, a4 \ + MOVQ 40+r, a5 + +#define fp384Carry(a0,a1,a2,a3,a4,a5,a6, b0,b1,b2,b3,b4,b5,b6) \ + \ // b = a-p + MOVQ a0, b0 \ + MOVQ a1, b1 \ + MOVQ a2, b2 \ + MOVQ a3, b3 \ + MOVQ a4, b4 \ + MOVQ a5, b5 \ + MOVQ a6, b6 \ + \ + SUBQ ·p+0(SB), b0 \ + SBBQ ·p+8(SB), b1 \ + SBBQ ·p+16(SB), b2 \ + SBBQ ·p+24(SB), b3 \ + SBBQ ·p+32(SB), b4 \ + SBBQ ·p+40(SB), b5 \ + SBBQ $0, b6 \ + \ + \ // if b is negative then return a + \ // else return b + CMOVQCC b0, a0 \ + CMOVQCC b1, a1 \ + CMOVQCC b2, a2 \ + CMOVQCC b3, a3 \ + CMOVQCC b4, a4 \ + CMOVQCC b5, a5 + +#define mul(a0,a1,a2,a3,a4,a5, rb, stack) \ + \ // a0 + MOVQ a0, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a0, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a0, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a0, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + MOVQ a0, AX \ + MULQ 32+rb \ + ADDQ AX, R12 \ + ADCQ $0, DX \ + MOVQ DX, R13 \ + MOVQ a0, AX \ + MULQ 40+rb \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + \ + storeBlock(R8,R9,R10,R11,R12,R13, 0+stack) \ + MOVQ R14, 48+stack \ + \ + \ // a1 + MOVQ a1, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a1, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a1, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a1, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + MOVQ a1, AX \ + MULQ 32+rb \ + ADDQ AX, R12 \ + ADCQ $0, DX \ + MOVQ DX, R13 \ + MOVQ a1, AX \ + MULQ 40+rb \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + \ + ADDQ 8+stack, R8 \ + ADCQ 16+stack, R9 \ + ADCQ 24+stack, R10 \ + ADCQ 32+stack, R11 \ + ADCQ 40+stack, R12 \ + ADCQ 48+stack, R13 \ + ADCQ $0, R14 \ + storeBlock(R8,R9,R10,R11,R12,R13, 8+stack) \ + MOVQ R14, 56+stack \ + \ + \ // a2 + MOVQ a2, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a2, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a2, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a2, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + MOVQ a2, AX \ + MULQ 32+rb \ + ADDQ AX, R12 \ + ADCQ $0, DX \ + MOVQ DX, R13 \ + MOVQ a2, AX \ + MULQ 40+rb \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + \ + ADDQ 16+stack, R8 \ + ADCQ 24+stack, R9 \ + ADCQ 32+stack, R10 \ + ADCQ 40+stack, R11 \ + ADCQ 48+stack, R12 \ + ADCQ 56+stack, R13 \ + ADCQ $0, R14 \ + storeBlock(R8,R9,R10,R11,R12,R13, 16+stack) \ + MOVQ R14, 64+stack \ + \ + \ // a3 + MOVQ a3, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a3, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a3, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a3, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + MOVQ a3, AX \ + MULQ 32+rb \ + ADDQ AX, R12 \ + ADCQ $0, DX \ + MOVQ DX, R13 \ + MOVQ a3, AX \ + MULQ 40+rb \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + \ + ADDQ 24+stack, R8 \ + ADCQ 32+stack, R9 \ + ADCQ 40+stack, R10 \ + ADCQ 48+stack, R11 \ + ADCQ 56+stack, R12 \ + ADCQ 64+stack, R13 \ + ADCQ $0, R14 \ + storeBlock(R8,R9,R10,R11,R12,R13, 24+stack) \ + MOVQ R14, 72+stack \ + \ + \ // a4 + MOVQ a4, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a4, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a4, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a4, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + MOVQ a4, AX \ + MULQ 32+rb \ + ADDQ AX, R12 \ + ADCQ $0, DX \ + MOVQ DX, R13 \ + MOVQ a4, AX \ + MULQ 40+rb \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + \ + ADDQ 32+stack, R8 \ + ADCQ 40+stack, R9 \ + ADCQ 48+stack, R10 \ + ADCQ 56+stack, R11 \ + ADCQ 64+stack, R12 \ + ADCQ 72+stack, R13 \ + ADCQ $0, R14 \ + storeBlock(R8,R9,R10,R11,R12,R13, 32+stack) \ + MOVQ R14, 80+stack \ + \ + \ // a5 + MOVQ a5, AX \ + MULQ 0+rb \ + MOVQ AX, R8 \ + MOVQ DX, R9 \ + MOVQ a5, AX \ + MULQ 8+rb \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ a5, AX \ + MULQ 16+rb \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ a5, AX \ + MULQ 24+rb \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + MOVQ a5, AX \ + MULQ 32+rb \ + ADDQ AX, R12 \ + ADCQ $0, DX \ + MOVQ DX, R13 \ + MOVQ a5, AX \ + MULQ 40+rb \ + ADDQ AX, R13 \ + ADCQ $0, DX \ + MOVQ DX, R14 \ + \ + ADDQ 40+stack, R8 \ + ADCQ 48+stack, R9 \ + ADCQ 56+stack, R10 \ + ADCQ 64+stack, R11 \ + ADCQ 72+stack, R12 \ + ADCQ 80+stack, R13 \ + ADCQ $0, R14 \ + storeBlock(R8,R9,R10,R11,R12,R13, 40+stack) \ + MOVQ R14, 88+stack + +#define fp384Reduce(stack) \ + \ // m = (T * P') mod R, store m in R8:R9:R10:R11:R12:R13 + MOVQ ·pp+0(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R8 ; MOVQ R8, 96+stack\ + MOVQ DX, R9 \ + MOVQ ·pp+0(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R9 \ + ADCQ $0, DX \ + MOVQ DX, R10 \ + MOVQ ·pp+0(SB), AX \ + MULQ 16+stack \ + ADDQ AX, R10 \ + ADCQ $0, DX \ + MOVQ DX, R11 \ + MOVQ ·pp+0(SB), AX \ + MULQ 24+stack \ + ADDQ AX, R11 \ + ADCQ $0, DX \ + MOVQ DX, R12 \ + MOVQ ·pp+0(SB), AX \ + MULQ 32+stack \ + ADDQ AX, R12 \ + ADCQ $0, DX \ + MOVQ DX, R13 \ + MOVQ ·pp+0(SB), AX \ + MULQ 40+stack \ + ADDQ AX, R13 \ + \ + ADDQ 0+stack, R9 \ + ADCQ 8+stack, R10 \ + ADCQ 16+stack, R11 \ + ADCQ 24+stack, R12 \ + ADCQ 32+stack, R13 \ + \ + MOVQ ·pp+16(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R14 \ + MOVQ DX, R8 \ + MOVQ ·pp+16(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R8 \ + ADCQ $0, DX \ + MOVQ DX, BX \ + MOVQ ·pp+16(SB), AX \ + MULQ 16+stack \ + ADDQ AX, BX \ + ADCQ $0, DX \ + MOVQ DX, CX \ + MOVQ ·pp+16(SB), AX \ + MULQ 24+stack \ + ADDQ AX, CX \ + \ + ADDQ R14, R10 \ + ADCQ R8, R11 \ + ADCQ BX, R12 \ + ADCQ CX, R13 \ + \ + MOVQ ·pp+24(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R14 \ + MOVQ DX, R8 \ + MOVQ ·pp+24(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R8 \ + ADCQ $0, DX \ + MOVQ DX, BX \ + MOVQ ·pp+24(SB), AX \ + MULQ 16+stack \ + ADDQ AX, BX \ + \ + ADDQ R14, R11 \ + ADCQ R8, R12 \ + ADCQ BX, R13 \ + \ + MOVQ ·pp+32(SB), AX \ + MULQ 0+stack \ + MOVQ AX, R14 \ + MOVQ DX, R8 \ + MOVQ ·pp+32(SB), AX \ + MULQ 8+stack \ + ADDQ AX, R8 \ + \ + ADDQ R14, R12 \ + ADCQ R8, R13 \ + \ + MOVQ ·pp+40(SB), AX \ + MULQ 0+stack \ + ADDQ AX, R13 \ + \ + MOVQ 96+stack, R8 \ + \ + storeBlock(R8,R9,R10,R11,R12,R13, 96+stack) \ + \ + \ // m * P + mul(·p+0(SB),·p+8(SB),·p+16(SB),·p+24(SB),·p+32(SB),·p+40(SB), 96+stack, 144+stack) \ + \ + \ // Add the 768-bit intermediate to m*N + MOVQ $0, R15 \ + loadBlock(144+stack, R8,R9,R10,R11,R12,R13) \ + loadBlock(192+stack, R14,SI,AX,BX,CX,DX) \ + \ + ADDQ 0+stack, R8 \ + ADCQ 8+stack, R9 \ + ADCQ 16+stack, R10 \ + ADCQ 24+stack, R11 \ + ADCQ 32+stack, R12 \ + ADCQ 40+stack, R13 \ + ADCQ 48+stack, R14 \ + ADCQ 56+stack, SI \ + ADCQ 64+stack, AX \ + ADCQ 72+stack, BX \ + ADCQ 80+stack, CX \ + ADCQ 88+stack, DX \ + ADCQ $0, R15 \ + \ + fp384Carry(R14,SI,AX,BX,CX,DX,R15, R8,R9,R10,R11,R12,R13,DI) + +#define mulBMI2(a0,a1,a2,a3,a4,a5, rb, stack) \ + MOVQ a0, DX \ + MULXQ 0+rb, R8, R9; MOVQ R8, 0+stack; MOVQ $0, R8 \ + MULXQ 8+rb, AX, R10 \ + ADDQ AX, R9 \ + MULXQ 16+rb, AX, R11 \ + ADCQ AX, R10 \ + MULXQ 24+rb, AX, R12 \ + ADCQ AX, R11 \ + MULXQ 32+rb, AX, R13 \ + ADCQ AX, R12 \ + MULXQ 40+rb, AX, R14 \ + ADCQ AX, R13 \ + ADCQ $0, R14 \ + \ + MOVQ a1, DX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R9; MOVQ R9, 8+stack; MOVL $0, R9 \ + ADCQ BX, R10 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 32+rb, AX, BX \ + ADCQ AX, R13 \ + ADCQ BX, R14 \ + ADCQ $0, R8 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R12 \ + ADCQ BX, R13 \ + MULXQ 40+rb, AX, BX \ + ADCQ AX, R14 \ + ADCQ BX, R8 \ + ADCQ $0, R9 \ + \ + MOVQ a2, DX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R10; MOVQ R10, 16+stack; MOVL $0, R10 \ + ADCQ BX, R11 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R12 \ + ADCQ BX, R13 \ + MULXQ 32+rb, AX, BX \ + ADCQ AX, R14 \ + ADCQ BX, R8 \ + ADCQ $0, R9 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R13 \ + ADCQ BX, R14 \ + MULXQ 40+rb, AX, BX \ + ADCQ AX, R8 \ + ADCQ BX, R9 \ + ADCQ $0, R10 \ + \ + MOVQ a3, DX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R11; MOVQ R11, 24+stack; MOVL $0, R11 \ + ADCQ BX, R12 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R13 \ + ADCQ BX, R14 \ + MULXQ 32+rb, AX, BX \ + ADCQ AX, R8 \ + ADCQ BX, R9 \ + ADCQ $0, R10 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R12 \ + ADCQ BX, R13 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R14 \ + ADCQ BX, R8 \ + MULXQ 40+rb, AX, BX \ + ADCQ AX, R9 \ + ADCQ BX, R10 \ + ADCQ $0, R11 \ + \ + MOVQ a4, DX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R12; MOVQ R12, 32+stack; MOVL $0, R12 \ + ADCQ BX, R13 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R14 \ + ADCQ BX, R8 \ + MULXQ 32+rb, AX, BX \ + ADCQ AX, R9 \ + ADCQ BX, R10 \ + ADCQ $0, R11 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R13 \ + ADCQ BX, R14 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R8 \ + ADCQ BX, R9 \ + MULXQ 40+rb, AX, BX \ + ADCQ AX, R10 \ + ADCQ BX, R11 \ + ADCQ $0, R12 \ + \ + MOVQ a5, DX \ + MULXQ 0+rb, AX, BX \ + ADDQ AX, R13; MOVQ R13, 40+stack \ + ADCQ BX, R14 \ + MULXQ 16+rb, AX, BX \ + ADCQ AX, R8 \ + ADCQ BX, R9 \ + MULXQ 32+rb, AX, BX \ + ADCQ AX, R10 \ + ADCQ BX, R11 \ + ADCQ $0, R12 \ + MULXQ 8+rb, AX, BX \ + ADDQ AX, R14 \ + ADCQ BX, R8 \ + MULXQ 24+rb, AX, BX \ + ADCQ AX, R9 \ + ADCQ BX, R10 \ + MULXQ 40+rb, AX, BX \ + ADCQ AX, R11 \ + ADCQ BX, R12 + +#define fp384ReduceBMI2(stack) \ + \ // m = (T * P') mod R, store m in R8:R9:R10:R11:R12:R13 + MOVQ ·pp+0(SB), DX \ + MULXQ 0+stack, R8, R9 \ + MULXQ 8+stack, AX, R10 \ + ADDQ AX, R9 \ + MULXQ 16+stack, AX, R11 \ + ADCQ AX, R10 \ + MULXQ 24+stack, AX, R12 \ + ADCQ AX, R11 \ + MULXQ 32+stack, AX, R13 \ + ADCQ AX, R12 \ + MULXQ 40+stack, AX, BX \ + ADCQ AX, R13 \ + \ + ADDQ 0+stack, R9 \ + ADCQ 8+stack, R10 \ + ADCQ 16+stack, R11 \ + ADCQ 24+stack, R12 \ + ADCQ 32+stack, R13 \ + \ + MOVQ ·pp+16(SB), DX \ + MULXQ 0+stack, AX, BX \ + ADDQ AX, R10 \ + ADCQ BX, R11 \ + MULXQ 16+stack, AX, BX \ + ADCQ AX, R12 \ + ADCQ BX, R13 \ + MULXQ 8+stack, AX, BX \ + ADDQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 24+stack, AX, BX \ + ADCQ AX, R13 \ + \ + MOVQ ·pp+24(SB), DX \ + MULXQ 0+stack, AX, BX \ + ADDQ AX, R11 \ + ADCQ BX, R12 \ + MULXQ 16+stack, AX, BX \ + ADCQ AX, R13 \ + MULXQ 8+stack, AX, BX \ + ADDQ AX, R12 \ + ADCQ BX, R13 \ + \ + MOVQ ·pp+32(SB), DX \ + MULXQ 0+stack, AX, BX \ + ADDQ AX, R12 \ + ADCQ BX, R13 \ + MULXQ 8+stack, AX, BX \ + ADDQ AX, R13 \ + \ + MOVQ ·pp+40(SB), DX \ + MULXQ 0+stack, AX, BX \ + ADDQ AX, R13 \ + \ + storeBlock(R8,R9,R10,R11,R12,R13, 96+stack) \ + \ + \ // m * P + mulBMI2(·p+0(SB),·p+8(SB),·p+16(SB),·p+24(SB),·p+32(SB),·p+40(SB), 96+stack, 144+stack) \ + \ + \ // Add the 768-bit intermediate to m*N + loadBlock(144+stack, AX,R13,BX,CX,DX,DI) \ + \ + ADDQ 0+stack, AX \ + ADCQ 8+stack, R13 \ + ADCQ 16+stack, BX \ + ADCQ 24+stack, CX \ + ADCQ 32+stack, DX \ + ADCQ 40+stack, DI \ + ADCQ 48+stack, R14 \ + ADCQ 56+stack, R8 \ + ADCQ 64+stack, R9 \ + ADCQ 72+stack, R10 \ + ADCQ 80+stack, R11 \ + ADCQ 88+stack, R12 \ + MOVQ $0, 0+stack \ + ADCQ $0, 0+stack \ + \ + fp384Carry(R14,R8,R9,R10,R11,R12, 0+stack, AX,R13,BX,CX,DX,DI,SI) + +TEXT ·fp384Neg(SB), NOSPLIT, $0-16 + MOVQ ·p+0(SB), R8 + MOVQ ·p+8(SB), R9 + MOVQ ·p+16(SB), R10 + MOVQ ·p+24(SB), R11 + MOVQ ·p+32(SB), R12 + MOVQ ·p+40(SB), R13 + + MOVQ a+8(FP), DI + SUBQ 0(DI), R8 + SBBQ 8(DI), R9 + SBBQ 16(DI), R10 + SBBQ 24(DI), R11 + SBBQ 32(DI), R12 + SBBQ 40(DI), R13 + + MOVQ $0, R15 + fp384Carry(R8,R9,R10,R11,R12,R13,R15, R14,AX,BX,CX,DX,DI,SI) + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11,R12,R13, 0(DI)) + RET + +TEXT ·fp384Add(SB), NOSPLIT, $0-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + loadBlock(0(DI), R8,R9,R10,R11,R12,R13) + MOVQ $0, R15 + + ADDQ 0(SI), R8 + ADCQ 8(SI), R9 + ADCQ 16(SI), R10 + ADCQ 24(SI), R11 + ADCQ 32(SI), R12 + ADCQ 40(SI), R13 + ADCQ $0, R15 + + fp384Carry(R8,R9,R10,R11,R12,R13,R15, R14,AX,BX,CX,DX,DI,SI) + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11,R12,R13, 0(DI)) + RET + +TEXT ·fp384Sub(SB), NOSPLIT, $0-24 + MOVQ ·p+0(SB), R8 + MOVQ ·p+8(SB), R9 + MOVQ ·p+16(SB), R10 + MOVQ ·p+24(SB), R11 + MOVQ ·p+32(SB), R12 + MOVQ ·p+40(SB), R13 + + MOVQ b+16(FP), DI + SUBQ 0(DI), R8 + SBBQ 8(DI), R9 + SBBQ 16(DI), R10 + SBBQ 24(DI), R11 + SBBQ 32(DI), R12 + SBBQ 40(DI), R13 + + MOVQ $0, R15 + MOVQ a+8(FP), DI + ADDQ 0(DI), R8 + ADCQ 8(DI), R9 + ADCQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ 32(DI), R12 + ADCQ 40(DI), R13 + ADCQ $0, R15 + + fp384Carry(R8,R9,R10,R11,R12,R13,R15, R14,AX,BX,CX,DX,DI,SI) + + MOVQ c+0(FP), DI + storeBlock(R8,R9,R10,R11,R12,R13, 0(DI)) + RET + +TEXT ·fp384Mul(SB), NOSPLIT, $240-24 + MOVQ a+8(FP), DI + MOVQ b+16(FP), SI + + // Jump to a slightly different implementation if MULX isn't supported. + CMPB ·hasBMI2(SB), $0 + JE nobmi2Mul + + // T = a * b + mulBMI2(0(DI),8(DI),16(DI),24(DI),32(DI),40(DI), 0(SI), 0(SP)) + storeBlock(R14,R8,R9,R10,R11,R12, 48(SP)) + + // Reduce T. + fp384ReduceBMI2(0(SP)) + + MOVQ c+0(FP), DI + storeBlock(R14,R8,R9,R10,R11,R12, 0(DI)) + JMP end + +nobmi2Mul: + // T = a * b + mul(0(DI),8(DI),16(DI),24(DI),32(DI),40(DI), 0(SI), 0(SP)) + + // Reduce T. + fp384Reduce(0(SP)) + + MOVQ c+0(FP), DI + storeBlock(R14,SI,AX,BX,CX,DX, 0(DI)) + +end: + RET + +TEXT ·fp384Cmov(SB), NOSPLIT, $0 + MOVQ x+0(FP), DI + MOVQ y+8(FP), SI + MOVQ b+16(FP), BX + TESTQ BX, BX + MOVQ 0(DI), AX; MOVQ 0(SI), DX; CMOVQNE DX, AX; MOVQ AX, 0(DI); + MOVQ 8(DI), AX; MOVQ 8(SI), DX; CMOVQNE DX, AX; MOVQ AX, 8(DI); + MOVQ 16(DI), AX; MOVQ 16(SI), DX; CMOVQNE DX, AX; MOVQ AX, 16(DI); + MOVQ 24(DI), AX; MOVQ 24(SI), DX; CMOVQNE DX, AX; MOVQ AX, 24(DI); + MOVQ 32(DI), AX; MOVQ 32(SI), DX; CMOVQNE DX, AX; MOVQ AX, 32(DI); + MOVQ 40(DI), AX; MOVQ 40(SI), DX; CMOVQNE DX, AX; MOVQ AX, 40(DI); + RET diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_arm64.s b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_arm64.s new file mode 100644 index 00000000000..a02e76d576e --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_arm64.s @@ -0,0 +1,511 @@ +// +build arm64,!purego + +#include "textflag.h" + +TEXT ·fp384Cmov(SB), NOSPLIT, $0 + MOVD x+0(FP), R0 + MOVD y+8(FP), R1 + MOVW b+16(FP), R2 + CMP $0, R2 + LDP 0(R0), (R3, R5) + LDP 0(R1), (R4, R6) + CSEL NE,R4,R3,R7 + CSEL NE,R6,R5,R8 + STP (R7, R8), 0(R0) + LDP 16(R0), (R3, R5) + LDP 16(R1), (R4, R6) + CSEL NE,R4,R3,R7 + CSEL NE,R6,R5,R8 + STP (R7, R8), 16(R0) + LDP 32(R0), (R3, R5) + LDP 32(R1), (R4, R6) + CSEL NE,R4,R3,R7 + CSEL NE,R6,R5,R8 + STP (R7, R8), 32(R0) + RET + +// Compute c = -a mod p +TEXT ·fp384Neg(SB), NOSPLIT, $0-16 + MOVD c+0(FP), R0 + MOVD a+8(FP), R1 + + // Load p in R2-R7, a in R8-R13 + // Compute p-a in R8-R13 + LDP ·p+0(SB), (R2, R3) + LDP 0(R1), (R8, R9) + SUBS R8, R2, R8 + SBCS R9, R3, R9 + LDP ·p+16(SB), (R4, R5) + LDP 16(R1), (R10, R11) + SBCS R10, R4, R10 + SBCS R11, R5, R11 + LDP ·p+32(SB), (R6, R7) + LDP 32(R1), (R12, R13) + SBCS R12, R6, R12 + SBC R13, R7, R13 + + // Compute (p-a)-p in R2-R7 + SUBS R2, R8, R2 + SBCS R3, R9, R3 + SBCS R4, R10, R4 + SBCS R5, R11, R5 + SBCS R6, R12, R6 + SBCS R7, R13, R7 + + // If (p-a)-p < 0 (nearly always), return p-a + // Only return (p-a)-p for a = 0 + // Store result in c + CSEL CC, R8, R2, R2 + CSEL CC, R9, R3, R3 + STP (R2, R3), 0(R0) + CSEL CC, R10, R4, R4 + CSEL CC, R11, R5, R5 + STP (R4, R5), 16(R0) + CSEL CC, R12, R6, R6 + CSEL CC, R13, R7, R7 + STP (R6, R7), 32(R0) + + RET + +// Compute c = a+b mod p +TEXT ·fp384Add(SB), NOSPLIT, $0-24 + MOVD c+0(FP), R0 + MOVD a+8(FP), R1 + MOVD b+16(FP), R2 + + // Load a in R3-R8, b in R9-R14 + // Compute a+b in R3-R9 + LDP 0(R1), (R3, R4) + LDP 0(R2), (R9, R10) + ADDS R9, R3 + ADCS R10, R4 + LDP 16(R1), (R5, R6) + LDP 16(R2), (R11, R12) + ADCS R11, R5 + ADCS R12, R6 + LDP 32(R1), (R7, R8) + LDP 32(R2), (R13, R14) + ADCS R13, R7 + ADCS R14, R8 + ADC ZR, ZR, R9 + + // Load p in R10-R15 + LDP ·p+ 0(SB), (R10, R11) + LDP ·p+16(SB), (R12, R13) + LDP ·p+32(SB), (R14, R15) + + // Compute a+b-p in R10-R16 + SUBS R10, R3, R10 + SBCS R11, R4, R11 + SBCS R12, R5, R12 + SBCS R13, R6, R13 + SBCS R14, R7, R14 + SBCS R15, R8, R15 + SBCS ZR, R9, R16 + + // If a+b-p is negative, return a+b + // Store result in c + CSEL CC, R3, R10, R3 + CSEL CC, R4, R11, R4 + STP (R3, R4), 0(R0) + CSEL CC, R5, R12, R5 + CSEL CC, R6, R13, R6 + STP (R5, R6), 16(R0) + CSEL CC, R7, R14, R7 + CSEL CC, R8, R15, R8 + STP (R7, R8), 32(R0) + + RET + +// Compute c = a-b mod p +TEXT ·fp384Sub(SB), NOSPLIT, $0-24 + MOVD c+0(FP), R0 + MOVD a+8(FP), R1 + MOVD b+16(FP), R2 + + // Load a in R3-R8, b in R9-R14 + // Compute a-b in R3-R9 + LDP 0(R1), (R3, R4) + LDP 0(R2), (R9, R10) + SUBS R9, R3 + SBCS R10, R4 + LDP 16(R1), (R5, R6) + LDP 16(R2), (R11, R12) + SBCS R11, R5 + SBCS R12, R6 + LDP 32(R1), (R7, R8) + LDP 32(R2), (R13, R14) + SBCS R13, R7 + SBCS R14, R8 + SBC ZR, ZR, R9 + + // Load p in R10-R15 + // If a-b < 0, (a-b)+p to R3-R8 + // Store result in c + LDP ·p+ 0(SB), (R10, R11) + AND R9, R10 + LDP ·p+16(SB), (R12, R13) + AND R9, R11 + AND R9, R12 + LDP ·p+32(SB), (R14, R15) + AND R9, R13 + AND R9, R14 + AND R9, R15 + + ADDS R10, R3 + ADCS R11, R4 + STP (R3, R4), 0(R0) + ADCS R12, R5 + ADCS R13, R6 + STP (R5, R6), 16(R0) + ADCS R14, R7 + ADC R15, R8 + STP (R7, R8), 32(R0) + + RET + +// Expects that A0*B0 is already in C0(low),C3(high) and A0*B1 in C1(low),C2(high) +// C0 is not actually touched +// Result of (A0-A2) * (B0-B2) will be in C0-C5 +// Inputs remain intact +#define mul192x192comba(A0,A1,A2, B0,B1,B2, C0,C1,C2,C3,C4,C5, S0,S1,S2,S3) \ + MUL A1, B0, S2 \ + UMULH A1, B0, S3 \ + \ + ADDS C3, C1 \ + ADCS ZR, C2 \ + ADC ZR, ZR, C3 \ + \ + MUL A0, B2, S0 \ + UMULH A0, B2, S1 \ + \ + ADDS S2, C1 \ + ADCS S3, C2 \ + ADC ZR, C3 \ + \ + MUL A1, B1, S2 \ + UMULH A1, B1, S3 \ + \ + ADDS S0, C2 \ + ADCS S1, C3 \ + ADC ZR, ZR, C4 \ + \ + MUL A2, B0, S0 \ + UMULH A2, B0, S1 \ + \ + ADDS S2, C2 \ + ADCS S3, C3 \ + ADC ZR, C4 \ + \ + MUL A1, B2, S2 \ + UMULH A1, B2, S3 \ + \ + ADDS S0, C2 \ + ADCS S1, C3 \ + ADC ZR, C4 \ + \ + MUL A2, B1, S0 \ + UMULH A2, B1, S1 \ + \ + ADDS S2, C3 \ + ADCS S3, C4 \ + ADC ZR, ZR, C5 \ + \ + MUL A2, B2, S2 \ + UMULH A2, B2, S3 \ + \ + ADDS S0, C3 \ + ADCS S1, C4 \ + ADC ZR, C5 \ + \ + ADDS S2, C4 \ + ADC S3, C5 + + +// Assumes that there are at least 96 bytes left on the stack +// Expects that X and Y point to input +// X and Y get overwritten, Z0 will be in Y +#define mul384x384karatsuba(X,Y, Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9,Z10,Z11, T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12) \ + /* Load a in Z1-Z6, b in T12,Z7-Z11 */ \ + LDP 0(X), ( Z1, Z2) \ + LDP 0(Y), (T12, Z7) \ + MUL Z1, Z7, T1 \ + UMULH Z1, T12, T3 \ + LDP 16(X), ( Z3, Z4) \ + LDP 16(Y), ( Z8, Z9) \ + MUL Z1, T12, T0 \ + UMULH Z1, Z7, T2 \ + LDP 32(X), ( Z5, Z6) \ + LDP 32(Y), (Z10, Z11) \ + \ + /* Compute aL*bL in T0-T5 */ \ + mul192x192comba(Z1,Z2,Z3, T12,Z7,Z8, T0,T1,T2,T3,T4,T5, T6,T7,T8,T9) \ + \ + /* Compute aH*bH in T6-T11, destroys aL and bL */ \ + MUL Z4, Z10, T7 \ + MUL Z4, Z9, T6 \ + UMULH Z4, Z9, T9 \ + UMULH Z4, Z10, T8 \ + mul192x192comba(Z4,Z5,Z6, Z9,Z10,Z11, T6,T7,T8,T9,T10,T11, Z1,Z2,T12,Z7) \ + \ + /* Compute aL*bL + aH*bH in Z1-Z6,T12, destroys aH */ \ + ADDS T0, T6, Z1 \ + ADCS T1, T7, Z2 \ + ADCS T2, T8, Z3 \ + ADCS T3, T9, Z4 \ + ADCS T4, T10, Z5 \ + ADCS T5, T11, Z6 \ + ADC ZR, ZR, T12 \ + \ + /* Add to T0-T11 and store on stack */ \ + STP ( T0, T1), -16(RSP) \ + ADDS Z1, T3 \ + STP ( T2, T3), -32(RSP) \ + ADCS Z2, T4 \ + ADCS Z3, T5 \ + STP ( T4, T5), -48(RSP) \ + ADCS Z4, T6 \ + ADCS Z5, T7 \ + STP ( T6, T7), -64(RSP) \ + ADCS Z6, T8 \ + ADC ZR, T12 \ + STP ( T8, T9), -80(RSP) \ + STP (T10, T11), -96(RSP) \ + \ + /* Load a to Z1-Z6 */ \ + LDP 0(X), (Z1, Z2) \ + LDP 16(X), (Z3, Z4) \ + LDP 32(X), (Z5, Z6) \ + \ + /* Compute |aL-aH| to Z1-Z3, keep borrow in X */ \ + SUBS Z4, Z1 \ + SBCS Z5, Z2 \ + SBCS Z6, Z3 \ + SBC ZR, ZR, X \ + NEGS Z1, Z4 \ + NGCS Z2, Z5 \ + NGC Z3, Z6 \ + ADDS $1, X \ + \ + /* Load b to Z7-Z11,T0 */ \ + LDP 0(Y), ( Z7, Z8) \ + LDP 16(Y), ( Z9, Z10) \ + LDP 32(Y), (Z11, T0) \ + \ + CSEL EQ, Z4, Z1, Z1 \ + CSEL EQ, Z5, Z2 ,Z2 \ + CSEL EQ, Z6, Z3, Z3 \ + \ + /* Compute |bH-bL| to Z7-Z9, keep borrow in Y */ \ + SUBS Z7, Z10 \ + SBCS Z8, Z11 \ + SBCS Z9, T0 \ + SBC ZR, ZR, Y \ + NEGS Z10, Z7 \ + NGCS Z11, Z8 \ + NGC T0, Z9 \ + ADDS $1, Y \ + CSEL EQ, Z7, Z10, Z7 \ + CSEL EQ, Z8, Z11, Z8 \ + CSEL EQ, Z9, T0, Z9 \ + \ + /* Combine borrows */ \ + EOR Y, X \ + \ + /* Compute |aL-aH|*|bH-bL| to Z10,Z11,T0-T3 */ \ + MUL Z1, Z8, Z11 \ + MUL Z1, Z7, Z10 \ + UMULH Z1, Z8, T0 \ + UMULH Z1, Z7, T1 \ + mul192x192comba(Z1,Z2,Z3, Z7,Z8,Z9, Z10,Z11,T0,T1,T2,T3, T4,T5,T6,T7) \ + \ + /* The result has to be negated if exactly one of the operands was negative */ \ + NEGS Z10, Y \ + NGCS Z11, Z1 \ + NGCS T0, Z2 \ + NGCS T1, Z3 \ + NGCS T2, Z4 \ + NGCS T3, Z5 \ + NGC ZR, T4 \ + \ + AND T4, X \ + CMP $1, X \ + CSEL EQ, Y, Z10, Z10 \ + CSEL EQ, Z1, Z11, Z11 \ + CSEL EQ, Z2, T0, T0 \ + CSEL EQ, Z3, T1, T1 \ + CSEL EQ, Z4, T2, T2 \ + CSEL EQ, Z5, T3, T3 \ + \ + /* Add that to the middle part */ \ + LDP -16(RSP), ( Y, Z1) \ + LDP -32(RSP), ( Z2, Z3) \ + LDP -48(RSP), ( Z4, Z5) \ + ADDS Z10, Z3 \ + ADCS Z11, Z4 \ + LDP -64(RSP), ( Z6, Z7) \ + ADCS T0, Z5 \ + ADCS T1, Z6 \ + LDP -80(RSP), ( Z8, Z9) \ + ADCS T2, Z7 \ + ADCS T3, Z8 \ + LDP -96(RSP), (Z10, Z11) \ + ADCS T12, Z9 \ + ADCS ZR, Z10 \ + ADC ZR, Z11 \ + SUBS X, Z9 \ + SBCS ZR, Z10 \ + SBC ZR, Z11 + +// Compute c = a*b*R^-1 mod p +TEXT ·fp384Mul(SB), NOSPLIT, $200-24 + MOVD c+0(FP), R0 + MOVD a+8(FP), R1 + MOVD b+16(FP), R2 + + // Compute a*b in R2-R13 + mul384x384karatsuba(R1, R2, R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13, R14,R15,R16,R17,R19,R20,R21,R22,R23,R24,R25,R26,R27) + + // Store a*b on the stack + STP ( R2, R3), -112(RSP) + STP ( R4, R5), -128(RSP) + STP ( R6, R7), -144(RSP) + STP ( R8, R9), -160(RSP) + STP (R10, R11), -176(RSP) + STP (R12, R13), -192(RSP) + + // Compute m = a*b*pp mod 2^384 in R19-R24 + // Store it temporarily in c + MOVD ·pp+0(SB), R14 + MUL R14, R2, R19 + UMULH R14, R2, R20 + + MUL R14, R3, R16 + UMULH R14, R3, R21 + ADDS R16, R20 + ADC ZR, R21 + + MUL R14, R4, R16 + UMULH R14, R4, R22 + ADDS R16, R21 + ADC ZR, R22 + + MUL R14, R5, R16 + UMULH R14, R5, R23 + ADDS R16, R22 + ADC ZR, R23 + + MUL R14, R6, R16 + UMULH R14, R6, R24 + ADDS R16, R23 + ADC ZR, R24 + + MADD R14, R24, R7, R24 + + // ·pp+8(SB) = 1, so we can just add + ADDS R2, R20 + STP (R19, R20), 0(R0) + ADCS R3, R21 + ADCS R4, R22 + ADCS R5, R23 + ADC R6, R24 + + LDP ·pp+16(SB), (R14, R15) + MUL R14, R2, R8 + UMULH R14, R2, R9 + + MUL R14, R3, R16 + UMULH R14, R3, R10 + ADDS R16, R9 + ADC ZR, R10 + + MUL R14, R4, R16 + UMULH R14, R4, R11 + ADDS R16, R10 + ADC ZR, R11 + + MUL R14, R5, R16 + ADD R16, R11 + + ADDS R8, R21 + ADCS R9, R22 + ADCS R10, R23 + ADC R11, R24 + + MUL R15, R2, R8 + UMULH R15, R2, R9 + + MUL R15, R3, R16 + UMULH R15, R3, R10 + ADDS R16, R9 + ADC ZR, R10 + + MADD R15, R10, R4, R10 + + ADDS R8, R22 + STP (R21, R22), 16(R0) + ADCS R9, R23 + ADC R10, R24 + + LDP ·pp+32(SB), (R14, R15) + MUL R14, R2, R8 + UMULH R14, R2, R9 + + MADD R14, R9, R3, R9 + + ADDS R8, R23 + ADC R9, R24 + + MADD R15, R24, R2, R24 + STP (R23, R24), 32(R0) + + // Compute m*p in R1-R12 + MOVD $·p(SB), R1 + mul384x384karatsuba(R0, R1, R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12, R13,R14,R15,R16,R17,R19,R20,R21,R22,R23,R24,R25,R26) + + // Add a*b to m*p in R1-R12,R26 + LDP -112(RSP), (R13, R14) + ADDS R13, R1 + LDP -128(RSP), (R15, R16) + ADCS R14, R2 + ADCS R15, R3 + LDP -144(RSP), (R17, R19) + ADCS R16, R4 + ADCS R17, R5 + LDP -160(RSP), (R20, R21) + ADCS R19, R6 + ADCS R20, R7 + LDP -176(RSP), (R22, R23) + ADCS R21, R8 + ADCS R22, R9 + LDP -192(RSP), (R24, R25) + ADCS R23, R10 + ADCS R24, R11 + ADCS R25, R12 + ADC ZR, ZR, R26 + + // Reduce the top half mod p + LDP ·p+ 0(SB), (R13, R14) + SUBS R13, R7, R13 + LDP ·p+16(SB), (R15, R16) + SBCS R14, R8, R14 + SBCS R15, R9, R15 + LDP ·p+32(SB), (R17, R19) + SBCS R16, R10, R16 + SBCS R17, R11, R17 + SBCS R19, R12, R19 + SBCS ZR, R26 + + // Store result in c + MOVD c+0(FP), R0 + CSEL CC, R7, R13, R7 + CSEL CC, R8, R14, R8 + STP ( R7, R8), 0(R0) + CSEL CC, R9, R15, R9 + CSEL CC, R10, R16, R10 + STP ( R9, R10), 16(R0) + CSEL CC, R11, R17, R11 + CSEL CC, R12, R19, R12 + STP (R11, R12), 32(R0) + + RET diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/doc.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/doc.go new file mode 100644 index 00000000000..807676fb7fd --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/doc.go @@ -0,0 +1,10 @@ +// Package p384 provides optimized elliptic curve operations on the P-384 curve. +// +// These are some improvements over crypto/elliptic package: +// - Around 10x faster in amd64 architecture. +// - Reduced number of memory allocations. +// - Native support for arm64 architecture. +// - ScalarMult is performed using a constant-time algorithm. +// - ScalarBaseMult fallbacks into ScalarMult. +// - A new method included for double-point multiplication. +package p384 diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/p384.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384.go new file mode 100644 index 00000000000..75005d08df9 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384.go @@ -0,0 +1,28 @@ +package p384 + +import ( + "crypto/elliptic" + "math/big" +) + +// Curve is used to provide the extended functionality and performance of +// elliptic.Curve interface. +type Curve interface { + elliptic.Curve + // IsAtInfinity returns True is the point is the identity point. + IsAtInfinity(X, Y *big.Int) bool + // CombinedMult calculates P=mG+nQ, where G is the generator and + // Q=(Qx,Qy). The scalars m and n are positive integers in big-endian form. + // Runs in non-constant time to be used in signature verification. + CombinedMult(Qx, Qy *big.Int, m, n []byte) (Px, Py *big.Int) +} + +// Params returns the parameters for the curve. Note: The value returned by +// this function fallbacks to the stdlib implementation of elliptic curve +// operations. Use this method to only recover elliptic curve parameters. +func (c curve) Params() *elliptic.CurveParams { return elliptic.P384().Params() } + +// IsAtInfinity returns True is the point is the identity point. +func (c curve) IsAtInfinity(x, y *big.Int) bool { + return x.Sign() == 0 && y.Sign() == 0 +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/p384_generic.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384_generic.go new file mode 100644 index 00000000000..9b14feaec08 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384_generic.go @@ -0,0 +1,21 @@ +//go:build purego || (!amd64 && !arm64) +// +build purego !amd64,!arm64 + +package p384 + +import ( + "crypto/elliptic" + "math/big" +) + +type curve struct{ elliptic.Curve } + +func P384() Curve { return curve{elliptic.P384()} } + +// CombinedMult calculates P=mG+nQ, where G is the generator and Q=(x,y,z). +// The scalars m and n are integers in big-endian form. Non-constant time. +func (c curve) CombinedMult(xQ, yQ *big.Int, m, n []byte) (xP, yP *big.Int) { + x1, y1 := c.ScalarBaseMult(m) + x2, y2 := c.ScalarMult(xQ, yQ, n) + return c.Add(x1, y1, x2, y2) +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go new file mode 100644 index 00000000000..5f744eac89b --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go @@ -0,0 +1,181 @@ +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 + +package p384 + +import ( + "crypto/subtle" + "math/big" + + "github.com/cloudflare/circl/math" +) + +type curve struct{} + +// P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4). +func P384() Curve { return curve{} } + +// IsOnCurve reports whether the given (x,y) lies on the curve. +func (c curve) IsOnCurve(x, y *big.Int) bool { + x1, y1 := &fp384{}, &fp384{} + x1.SetBigInt(x) + y1.SetBigInt(y) + montEncode(x1, x1) + montEncode(y1, y1) + + y2, x3 := &fp384{}, &fp384{} + fp384Sqr(y2, y1) + fp384Sqr(x3, x1) + fp384Mul(x3, x3, x1) + + threeX := &fp384{} + fp384Add(threeX, x1, x1) + fp384Add(threeX, threeX, x1) + + fp384Sub(x3, x3, threeX) + fp384Add(x3, x3, &bb) + + return *y2 == *x3 +} + +// Add returns the sum of (x1,y1) and (x2,y2). +func (c curve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) { + P := newAffinePoint(x1, y1).toJacobian() + P.mixadd(P, newAffinePoint(x2, y2)) + return P.toAffine().toInt() +} + +// Double returns 2*(x,y). +func (c curve) Double(x1, y1 *big.Int) (x, y *big.Int) { + P := newAffinePoint(x1, y1).toJacobian() + P.double() + return P.toAffine().toInt() +} + +// reduceScalar shorten a scalar modulo the order of the curve. +func (c curve) reduceScalar(k []byte) []byte { + bigK := new(big.Int).SetBytes(k) + bigK.Mod(bigK, c.Params().N) + return bigK.FillBytes(make([]byte, sizeFp)) +} + +// toOdd performs k = (-k mod N) if k is even. +func (c curve) toOdd(k []byte) ([]byte, int) { + var X, Y big.Int + X.SetBytes(k) + Y.Neg(&X).Mod(&Y, c.Params().N) + isEven := 1 - int(X.Bit(0)) + x := X.Bytes() + y := Y.Bytes() + + if len(x) < len(y) { + x = append(make([]byte, len(y)-len(x)), x...) + } else if len(x) > len(y) { + y = append(make([]byte, len(x)-len(y)), y...) + } + subtle.ConstantTimeCopy(isEven, x, y) + return x, isEven +} + +// ScalarMult returns (Qx,Qy)=k*(Px,Py) where k is a number in big-endian form. +func (c curve) ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int) { + return c.scalarMultOmega(x1, y1, k, 5) +} + +func (c curve) scalarMultOmega(x1, y1 *big.Int, k []byte, omega uint) (x, y *big.Int) { + k = c.reduceScalar(k) + oddK, isEvenK := c.toOdd(k) + + var scalar big.Int + scalar.SetBytes(oddK) + if scalar.Sign() == 0 { + return new(big.Int), new(big.Int) + } + const bitsN = uint(384) + L := math.SignedDigit(&scalar, omega, bitsN) + + var R jacobianPoint + Q := zeroPoint().toJacobian() + TabP := newAffinePoint(x1, y1).oddMultiples(omega) + for i := len(L) - 1; i > 0; i-- { + for j := uint(0); j < omega-1; j++ { + Q.double() + } + idx := absolute(L[i]) >> 1 + for j := range TabP { + R.cmov(&TabP[j], subtle.ConstantTimeEq(int32(j), idx)) + } + R.cneg(int(L[i]>>31) & 1) + Q.add(Q, &R) + } + // Calculate the last iteration using complete addition formula. + for j := uint(0); j < omega-1; j++ { + Q.double() + } + idx := absolute(L[0]) >> 1 + for j := range TabP { + R.cmov(&TabP[j], subtle.ConstantTimeEq(int32(j), idx)) + } + R.cneg(int(L[0]>>31) & 1) + QQ := Q.toProjective() + QQ.completeAdd(QQ, R.toProjective()) + QQ.cneg(isEvenK) + return QQ.toAffine().toInt() +} + +// ScalarBaseMult returns k*G, where G is the base point of the group +// and k is an integer in big-endian form. +func (c curve) ScalarBaseMult(k []byte) (x, y *big.Int) { + params := c.Params() + return c.ScalarMult(params.Gx, params.Gy, k) +} + +// CombinedMult calculates P=mG+nQ, where G is the generator and Q=(x,y,z). +// The scalars m and n are integers in big-endian form. Non-constant time. +func (c curve) CombinedMult(xQ, yQ *big.Int, m, n []byte) (xP, yP *big.Int) { + const nOmega = uint(5) + var k big.Int + k.SetBytes(m) + nafM := math.OmegaNAF(&k, baseOmega) + k.SetBytes(n) + nafN := math.OmegaNAF(&k, nOmega) + + if len(nafM) > len(nafN) { + nafN = append(nafN, make([]int32, len(nafM)-len(nafN))...) + } else if len(nafM) < len(nafN) { + nafM = append(nafM, make([]int32, len(nafN)-len(nafM))...) + } + + TabQ := newAffinePoint(xQ, yQ).oddMultiples(nOmega) + var jR jacobianPoint + var aR affinePoint + P := zeroPoint().toJacobian() + for i := len(nafN) - 1; i >= 0; i-- { + P.double() + // Generator point + if nafM[i] != 0 { + idxM := absolute(nafM[i]) >> 1 + aR = baseOddMultiples[idxM] + if nafM[i] < 0 { + aR.neg() + } + P.mixadd(P, &aR) + } + // Input point + if nafN[i] != 0 { + idxN := absolute(nafN[i]) >> 1 + jR = TabQ[idxN] + if nafN[i] < 0 { + jR.neg() + } + P.add(P, &jR) + } + } + return P.toAffine().toInt() +} + +// absolute returns always a positive value. +func absolute(x int32) int32 { + mask := x >> 31 + return (x + mask) ^ mask +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go new file mode 100644 index 00000000000..e20b57b0176 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go @@ -0,0 +1,358 @@ +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 + +package p384 + +import ( + "fmt" + "math/big" +) + +// affinePoint represents an affine point of the curve. The point at +// infinity is (0,0) leveraging that it is not an affine point. +type affinePoint struct{ x, y fp384 } + +func newAffinePoint(x, y *big.Int) *affinePoint { + var P affinePoint + P.x.SetBigInt(x) + P.y.SetBigInt(y) + montEncode(&P.x, &P.x) + montEncode(&P.y, &P.y) + return &P +} + +func zeroPoint() *affinePoint { return &affinePoint{} } + +func (ap affinePoint) String() string { + if ap.isZero() { + return "inf" + } + return fmt.Sprintf("x: %v\ny: %v", ap.x, ap.y) +} + +func (ap *affinePoint) isZero() bool { + zero := fp384{} + return ap.x == zero && ap.y == zero +} + +func (ap *affinePoint) neg() { fp384Neg(&ap.y, &ap.y) } + +func (ap *affinePoint) toInt() (x, y *big.Int) { + var x1, y1 fp384 + montDecode(&x1, &ap.x) + montDecode(&y1, &ap.y) + return x1.BigInt(), y1.BigInt() +} + +func (ap *affinePoint) toJacobian() *jacobianPoint { + var P jacobianPoint + if ap.isZero() { + montEncode(&P.x, &fp384{1}) + montEncode(&P.y, &fp384{1}) + } else { + P.x = ap.x + P.y = ap.y + montEncode(&P.z, &fp384{1}) + } + return &P +} + +func (ap *affinePoint) toProjective() *projectivePoint { + var P projectivePoint + if ap.isZero() { + montEncode(&P.y, &fp384{1}) + } else { + P.x = ap.x + P.y = ap.y + montEncode(&P.z, &fp384{1}) + } + return &P +} + +// OddMultiples calculates the points iP for i={1,3,5,7,..., 2^(n-1)-1} +// Ensure that 1 < n < 31, otherwise it returns an empty slice. +func (ap affinePoint) oddMultiples(n uint) []jacobianPoint { + var t []jacobianPoint + if n > 1 && n < 31 { + P := ap.toJacobian() + s := int32(1) << (n - 1) + t = make([]jacobianPoint, s) + t[0] = *P + _2P := *P + _2P.double() + for i := int32(1); i < s; i++ { + t[i].add(&t[i-1], &_2P) + } + } + return t +} + +// p2Point is a point in P^2 +type p2Point struct{ x, y, z fp384 } + +func (P *p2Point) String() string { + return fmt.Sprintf("x: %v\ny: %v\nz: %v", P.x, P.y, P.z) +} + +func (P *p2Point) neg() { fp384Neg(&P.y, &P.y) } + +// condNeg if P is negated if b=1. +func (P *p2Point) cneg(b int) { + var mY fp384 + fp384Neg(&mY, &P.y) + fp384Cmov(&P.y, &mY, b) +} + +// cmov sets P to Q if b=1. +func (P *p2Point) cmov(Q *p2Point, b int) { + fp384Cmov(&P.x, &Q.x, b) + fp384Cmov(&P.y, &Q.y, b) + fp384Cmov(&P.z, &Q.z, b) +} + +func (P *p2Point) toInt() (x, y, z *big.Int) { + var x1, y1, z1 fp384 + montDecode(&x1, &P.x) + montDecode(&y1, &P.y) + montDecode(&z1, &P.z) + return x1.BigInt(), y1.BigInt(), z1.BigInt() +} + +// jacobianPoint represents a point in Jacobian coordinates. The point at +// infinity is any point (x,y,0) such that x and y are different from 0. +type jacobianPoint struct{ p2Point } + +func (P *jacobianPoint) isZero() bool { + zero := fp384{} + return P.x != zero && P.y != zero && P.z == zero +} + +func (P *jacobianPoint) toAffine() *affinePoint { + var aP affinePoint + z, z2 := &fp384{}, &fp384{} + fp384Inv(z, &P.z) + fp384Sqr(z2, z) + fp384Mul(&aP.x, &P.x, z2) + fp384Mul(&aP.y, &P.y, z) + fp384Mul(&aP.y, &aP.y, z2) + return &aP +} + +func (P *jacobianPoint) cmov(Q *jacobianPoint, b int) { P.p2Point.cmov(&Q.p2Point, b) } + +// add calculates P=Q+R such that Q and R are different than the identity point, +// and Q!==R. This function cannot be used for doublings. +func (P *jacobianPoint) add(Q, R *jacobianPoint) { + if Q.isZero() { + *P = *R + return + } else if R.isZero() { + *P = *Q + return + } + + // Cohen-Miyagi-Ono (1998) + // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2 + X1, Y1, Z1 := &Q.x, &Q.y, &Q.z + X2, Y2, Z2 := &R.x, &R.y, &R.z + Z1Z1, Z2Z2, U1, U2 := &fp384{}, &fp384{}, &fp384{}, &fp384{} + H, HH, HHH, RR := &fp384{}, &fp384{}, &fp384{}, &fp384{} + V, t4, t5, t6, t7, t8 := &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{} + t0, t1, t2, t3, S1, S2 := &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{} + fp384Sqr(Z1Z1, Z1) // Z1Z1 = Z1 ^ 2 + fp384Sqr(Z2Z2, Z2) // Z2Z2 = Z2 ^ 2 + fp384Mul(U1, X1, Z2Z2) // U1 = X1 * Z2Z2 + fp384Mul(U2, X2, Z1Z1) // U2 = X2 * Z1Z1 + fp384Mul(t0, Z2, Z2Z2) // t0 = Z2 * Z2Z2 + fp384Mul(S1, Y1, t0) // S1 = Y1 * t0 + fp384Mul(t1, Z1, Z1Z1) // t1 = Z1 * Z1Z1 + fp384Mul(S2, Y2, t1) // S2 = Y2 * t1 + fp384Sub(H, U2, U1) // H = U2 - U1 + fp384Sqr(HH, H) // HH = H ^ 2 + fp384Mul(HHH, H, HH) // HHH = H * HH + fp384Sub(RR, S2, S1) // r = S2 - S1 + fp384Mul(V, U1, HH) // V = U1 * HH + fp384Sqr(t2, RR) // t2 = r ^ 2 + fp384Add(t3, V, V) // t3 = V + V + fp384Sub(t4, t2, HHH) // t4 = t2 - HHH + fp384Sub(&P.x, t4, t3) // X3 = t4 - t3 + fp384Sub(t5, V, &P.x) // t5 = V - X3 + fp384Mul(t6, S1, HHH) // t6 = S1 * HHH + fp384Mul(t7, RR, t5) // t7 = r * t5 + fp384Sub(&P.y, t7, t6) // Y3 = t7 - t6 + fp384Mul(t8, Z2, H) // t8 = Z2 * H + fp384Mul(&P.z, Z1, t8) // Z3 = Z1 * t8 +} + +// mixadd calculates P=Q+R such that P and Q different than the identity point, +// and Q not in {P,-P, O}. +func (P *jacobianPoint) mixadd(Q *jacobianPoint, R *affinePoint) { + if Q.isZero() { + *P = *R.toJacobian() + return + } else if R.isZero() { + *P = *Q + return + } + + z1z1, u2 := &fp384{}, &fp384{} + fp384Sqr(z1z1, &Q.z) + fp384Mul(u2, &R.x, z1z1) + + s2 := &fp384{} + fp384Mul(s2, &R.y, &Q.z) + fp384Mul(s2, s2, z1z1) + if Q.x == *u2 { + if Q.y != *s2 { + *P = *(zeroPoint().toJacobian()) + return + } + *P = *Q + P.double() + return + } + + h, r := &fp384{}, &fp384{} + fp384Sub(h, u2, &Q.x) + fp384Mul(&P.z, h, &Q.z) + fp384Sub(r, s2, &Q.y) + + h2, h3 := &fp384{}, &fp384{} + fp384Sqr(h2, h) + fp384Mul(h3, h2, h) + h3y1 := &fp384{} + fp384Mul(h3y1, h3, &Q.y) + + h2x1 := &fp384{} + fp384Mul(h2x1, h2, &Q.x) + + fp384Sqr(&P.x, r) + fp384Sub(&P.x, &P.x, h3) + fp384Sub(&P.x, &P.x, h2x1) + fp384Sub(&P.x, &P.x, h2x1) + + fp384Sub(&P.y, h2x1, &P.x) + fp384Mul(&P.y, &P.y, r) + fp384Sub(&P.y, &P.y, h3y1) +} + +func (P *jacobianPoint) double() { + delta, gamma, alpha, alpha2 := &fp384{}, &fp384{}, &fp384{}, &fp384{} + fp384Sqr(delta, &P.z) + fp384Sqr(gamma, &P.y) + fp384Sub(alpha, &P.x, delta) + fp384Add(alpha2, &P.x, delta) + fp384Mul(alpha, alpha, alpha2) + *alpha2 = *alpha + fp384Add(alpha, alpha, alpha) + fp384Add(alpha, alpha, alpha2) + + beta := &fp384{} + fp384Mul(beta, &P.x, gamma) + + beta8 := &fp384{} + fp384Sqr(&P.x, alpha) + fp384Add(beta8, beta, beta) + fp384Add(beta8, beta8, beta8) + fp384Add(beta8, beta8, beta8) + fp384Sub(&P.x, &P.x, beta8) + + fp384Add(&P.z, &P.y, &P.z) + fp384Sqr(&P.z, &P.z) + fp384Sub(&P.z, &P.z, gamma) + fp384Sub(&P.z, &P.z, delta) + + fp384Add(beta, beta, beta) + fp384Add(beta, beta, beta) + fp384Sub(beta, beta, &P.x) + + fp384Mul(&P.y, alpha, beta) + + fp384Sqr(gamma, gamma) + fp384Add(gamma, gamma, gamma) + fp384Add(gamma, gamma, gamma) + fp384Add(gamma, gamma, gamma) + fp384Sub(&P.y, &P.y, gamma) +} + +func (P *jacobianPoint) toProjective() *projectivePoint { + var hP projectivePoint + hP.y = P.y + fp384Mul(&hP.x, &P.x, &P.z) + fp384Sqr(&hP.z, &P.z) + fp384Mul(&hP.z, &hP.z, &P.z) + return &hP +} + +// projectivePoint represents a point in projective homogeneous coordinates. +// The point at infinity is (0,y,0) such that y is different from 0. +type projectivePoint struct{ p2Point } + +func (P *projectivePoint) isZero() bool { + zero := fp384{} + return P.x == zero && P.y != zero && P.z == zero +} + +func (P *projectivePoint) toAffine() *affinePoint { + var aP affinePoint + z := &fp384{} + fp384Inv(z, &P.z) + fp384Mul(&aP.x, &P.x, z) + fp384Mul(&aP.y, &P.y, z) + return &aP +} + +// add calculates P=Q+R using complete addition formula for prime groups. +func (P *projectivePoint) completeAdd(Q, R *projectivePoint) { + // Reference: + // "Complete addition formulas for prime order elliptic curves" by + // Costello-Renes-Batina. [Alg.4] (eprint.iacr.org/2015/1060). + X1, Y1, Z1 := &Q.x, &Q.y, &Q.z + X2, Y2, Z2 := &R.x, &R.y, &R.z + X3, Y3, Z3 := &fp384{}, &fp384{}, &fp384{} + t0, t1, t2, t3, t4 := &fp384{}, &fp384{}, &fp384{}, &fp384{}, &fp384{} + fp384Mul(t0, X1, X2) // 1. t0 ← X1 · X2 + fp384Mul(t1, Y1, Y2) // 2. t1 ← Y1 · Y2 + fp384Mul(t2, Z1, Z2) // 3. t2 ← Z1 · Z2 + fp384Add(t3, X1, Y1) // 4. t3 ← X1 + Y1 + fp384Add(t4, X2, Y2) // 5. t4 ← X2 + Y2 + fp384Mul(t3, t3, t4) // 6. t3 ← t3 · t4 + fp384Add(t4, t0, t1) // 7. t4 ← t0 + t1 + fp384Sub(t3, t3, t4) // 8. t3 ← t3 − t4 + fp384Add(t4, Y1, Z1) // 9. t4 ← Y1 + Z1 + fp384Add(X3, Y2, Z2) // 10. X3 ← Y2 + Z2 + fp384Mul(t4, t4, X3) // 11. t4 ← t4 · X3 + fp384Add(X3, t1, t2) // 12. X3 ← t1 + t2 + fp384Sub(t4, t4, X3) // 13. t4 ← t4 − X3 + fp384Add(X3, X1, Z1) // 14. X3 ← X1 + Z1 + fp384Add(Y3, X2, Z2) // 15. Y3 ← X2 + Z2 + fp384Mul(X3, X3, Y3) // 16. X3 ← X3 · Y3 + fp384Add(Y3, t0, t2) // 17. Y3 ← t0 + t2 + fp384Sub(Y3, X3, Y3) // 18. Y3 ← X3 − Y3 + fp384Mul(Z3, &bb, t2) // 19. Z3 ← b · t2 + fp384Sub(X3, Y3, Z3) // 20. X3 ← Y3 − Z3 + fp384Add(Z3, X3, X3) // 21. Z3 ← X3 + X3 + fp384Add(X3, X3, Z3) // 22. X3 ← X3 + Z3 + fp384Sub(Z3, t1, X3) // 23. Z3 ← t1 − X3 + fp384Add(X3, t1, X3) // 24. X3 ← t1 + X3 + fp384Mul(Y3, &bb, Y3) // 25. Y3 ← b · Y3 + fp384Add(t1, t2, t2) // 26. t1 ← t2 + t2 + fp384Add(t2, t1, t2) // 27. t2 ← t1 + t2 + fp384Sub(Y3, Y3, t2) // 28. Y3 ← Y3 − t2 + fp384Sub(Y3, Y3, t0) // 29. Y3 ← Y3 − t0 + fp384Add(t1, Y3, Y3) // 30. t1 ← Y3 + Y3 + fp384Add(Y3, t1, Y3) // 31. Y3 ← t1 + Y3 + fp384Add(t1, t0, t0) // 32. t1 ← t0 + t0 + fp384Add(t0, t1, t0) // 33. t0 ← t1 + t0 + fp384Sub(t0, t0, t2) // 34. t0 ← t0 − t2 + fp384Mul(t1, t4, Y3) // 35. t1 ← t4 · Y3 + fp384Mul(t2, t0, Y3) // 36. t2 ← t0 · Y3 + fp384Mul(Y3, X3, Z3) // 37. Y3 ← X3 · Z3 + fp384Add(Y3, Y3, t2) // 38. Y3 ← Y3 + t2 + fp384Mul(X3, t3, X3) // 39. X3 ← t3 · X3 + fp384Sub(X3, X3, t1) // 40. X3 ← X3 − t1 + fp384Mul(Z3, t4, Z3) // 41. Z3 ← t4 · Z3 + fp384Mul(t1, t3, t0) // 42. t1 ← t3 · t0 + fp384Add(Z3, Z3, t1) // 43. Z3 ← Z3 + t1 + P.x, P.y, P.z = *X3, *Y3, *Z3 +} diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go new file mode 100644 index 00000000000..5132565ef34 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go @@ -0,0 +1,331 @@ +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 + +package p384 + +const baseOmega = uint(7) + +// baseOddMultiples has [2*i+1] * G at position i. +// Each coordinate has been multiplied by R=2^384 +var baseOddMultiples = [1 << (baseOmega - 1)]affinePoint{ + // 1P + { + x: fp384{0x28, 0xb5, 0xc0, 0x49, 0x66, 0x75, 0xd0, 0x3d, 0x38, 0xce, 0xd6, 0xa0, 0xe2, 0x78, 0xe3, 0x20, 0x6e, 0x4d, 0x1b, 0x54, 0xfc, 0x3a, 0x9c, 0x87, 0xff, 0xe, 0xa3, 0x59, 0x84, 0x86, 0x54, 0x64, 0x2b, 0xde, 0x4e, 0x61, 0x23, 0xf7, 0x2f, 0x81, 0x13, 0x15, 0x9e, 0x29, 0xc2, 0xad, 0x3a, 0x4d}, + y: fp384{0xfe, 0xa4, 0x3, 0x4b, 0xad, 0x3d, 0x4, 0x23, 0xac, 0xa9, 0xb4, 0x7b, 0xbf, 0xa8, 0xbf, 0xa1, 0x50, 0xb0, 0x83, 0x2e, 0x56, 0xe7, 0xad, 0x8b, 0xd9, 0xff, 0xf4, 0x68, 0x19, 0x52, 0xc3, 0xc6, 0x40, 0xa8, 0x69, 0x39, 0x26, 0x2, 0x80, 0xdd, 0xe9, 0xc5, 0x15, 0x5a, 0xc2, 0xab, 0x78, 0x2b}, + }, + // 3P + { + x: fp384{0x73, 0x40, 0xdc, 0xc1, 0xe6, 0xdb, 0xe4, 0x5, 0x9c, 0x77, 0x4f, 0xf0, 0xff, 0xa9, 0x4e, 0xc5, 0xf0, 0xcc, 0x70, 0xa1, 0xe9, 0x34, 0x20, 0x6b, 0x3e, 0x6c, 0x1c, 0xd5, 0x32, 0xd7, 0x48, 0x3a, 0x70, 0xa4, 0x3a, 0x26, 0x2d, 0x7e, 0x6f, 0xe3, 0xac, 0xc3, 0xc1, 0xe7, 0x68, 0xfe, 0x83, 0xd2}, + y: fp384{0x57, 0xe1, 0x4e, 0xc0, 0x21, 0x48, 0x28, 0x7e, 0x6d, 0xe3, 0xe0, 0x7a, 0xa7, 0x89, 0xd7, 0x92, 0x46, 0x74, 0xf6, 0x4e, 0xc0, 0x63, 0x26, 0x13, 0xb4, 0xd0, 0xe1, 0xd2, 0x5a, 0x2d, 0x1, 0x68, 0x39, 0xb3, 0x2, 0x51, 0xb1, 0x68, 0xdb, 0xf6, 0xaf, 0x92, 0x32, 0x98, 0xfc, 0x65, 0x54, 0x46}, + }, + // 5P + { + x: fp384{0xdf, 0xf0, 0xf1, 0x68, 0xba, 0x5e, 0x59, 0xbb, 0x66, 0x34, 0x87, 0xcc, 0xcb, 0xc0, 0x85, 0xc1, 0x3b, 0x70, 0x3c, 0x29, 0xb5, 0xb1, 0x1e, 0x7f, 0xe6, 0x5, 0xcc, 0xaa, 0xf5, 0x2c, 0xdb, 0x60, 0xc6, 0xe4, 0xe8, 0xe2, 0x87, 0xb9, 0x76, 0xc6, 0xfb, 0x8f, 0x17, 0x1d, 0xb1, 0x26, 0xbb, 0xe1}, + y: fp384{0x21, 0xfa, 0x73, 0x70, 0xa0, 0x4b, 0x69, 0x2b, 0x66, 0x45, 0xf3, 0x72, 0x2e, 0x6e, 0xc1, 0x22, 0x99, 0x5b, 0xc3, 0x1, 0x31, 0x1b, 0xb6, 0x80, 0x11, 0x4, 0x2c, 0x98, 0xaf, 0x7f, 0x23, 0x4b, 0x6d, 0x23, 0xde, 0x24, 0x40, 0x94, 0xc5, 0xe6, 0xa3, 0xe4, 0x9, 0xe2, 0xd6, 0xc9, 0xb1, 0x4d}, + }, + // 7P + { + x: fp384{0x2b, 0x22, 0x69, 0x7d, 0xd1, 0xb9, 0x13, 0xdf, 0xb1, 0x74, 0x47, 0x87, 0x5f, 0x41, 0xe6, 0x4c, 0x95, 0xaa, 0x1f, 0x21, 0xf8, 0xdc, 0x1e, 0x73, 0xed, 0x53, 0x97, 0x65, 0xd1, 0x15, 0x42, 0x5f, 0x55, 0xdf, 0xb2, 0x9d, 0x58, 0xdb, 0x93, 0xf8, 0x5b, 0x2, 0x89, 0x1c, 0x81, 0x9f, 0x2c, 0x93}, + y: fp384{0x1e, 0xa6, 0x6, 0x77, 0x20, 0xb2, 0x96, 0x9, 0x79, 0x1c, 0x64, 0xa8, 0xd5, 0x49, 0x53, 0x13, 0x44, 0x8, 0x13, 0x50, 0x6f, 0xd7, 0xaa, 0x65, 0x80, 0xf7, 0xff, 0x1, 0x4, 0x7c, 0xf3, 0xf, 0x6, 0x7, 0x3b, 0x69, 0x8e, 0x23, 0x7f, 0xf5, 0x3e, 0x9b, 0x6c, 0xaf, 0xb6, 0x16, 0xa, 0xd9}, + }, + // 9P + { + x: fp384{0x2f, 0xb9, 0x53, 0x23, 0xe, 0x20, 0x5d, 0x2f, 0xf9, 0xe4, 0xd7, 0x3f, 0x29, 0x87, 0x5d, 0xe3, 0x5d, 0x74, 0x6d, 0xa9, 0x33, 0x48, 0x9, 0x26, 0x3f, 0xff, 0xbf, 0x3c, 0xc1, 0x1d, 0x35, 0xdc, 0x6a, 0x4d, 0xd5, 0xda, 0xc6, 0x64, 0xd4, 0x26, 0x6a, 0x6c, 0x63, 0x53, 0x1d, 0x1d, 0xab, 0x5c}, + y: fp384{0xb0, 0xc0, 0x8e, 0xb1, 0x72, 0x30, 0x81, 0xf2, 0x2f, 0xaa, 0x42, 0xd7, 0x70, 0xe2, 0x77, 0x37, 0xc2, 0xa7, 0x3c, 0x3, 0xc7, 0x61, 0xf0, 0x27, 0xd8, 0xd0, 0xea, 0x68, 0xcc, 0xac, 0xec, 0xa6, 0x54, 0xa7, 0x69, 0xee, 0xf4, 0x29, 0x94, 0x7d, 0xc6, 0xf5, 0xe8, 0x31, 0x34, 0x63, 0x70, 0xe7}, + }, + // 11P + { + x: fp384{0x7d, 0x8c, 0x8b, 0xb6, 0x19, 0x8b, 0x70, 0xc7, 0xba, 0x7a, 0x37, 0x44, 0x7c, 0x7, 0x32, 0x45, 0x4f, 0xd6, 0xda, 0x6c, 0x70, 0x67, 0xcc, 0xd, 0x2, 0x66, 0x7b, 0x14, 0x56, 0xbf, 0xb8, 0x1, 0x79, 0x1d, 0x56, 0xf0, 0x85, 0x98, 0xd8, 0xf8, 0x37, 0xc4, 0xa9, 0x7b, 0xfc, 0xe9, 0x19, 0x9c}, + y: fp384{0x25, 0xba, 0xc4, 0xbd, 0x46, 0xb1, 0x4e, 0x76, 0x83, 0x4b, 0x14, 0xac, 0x6b, 0xe4, 0x4f, 0x60, 0x80, 0xe7, 0x77, 0x8a, 0x29, 0x13, 0xe8, 0x3c, 0x2e, 0x68, 0x9e, 0xfe, 0x36, 0xf, 0x7, 0x2e, 0x7a, 0x28, 0x53, 0x3a, 0xc, 0x1d, 0x82, 0x41, 0x18, 0xf9, 0x33, 0x35, 0x9f, 0x2f, 0xa6, 0x9a}, + }, + // 13P + { + x: fp384{0xfb, 0xbd, 0xcc, 0x75, 0x7e, 0xeb, 0x7a, 0x9b, 0x95, 0x9a, 0x74, 0xf6, 0xc5, 0x28, 0x5e, 0xb2, 0xae, 0xd4, 0xb7, 0x33, 0x46, 0x8e, 0x7a, 0x8a, 0x56, 0xbd, 0xc1, 0xd9, 0xa8, 0x3, 0x52, 0xdb, 0x97, 0xdf, 0x22, 0xed, 0x65, 0x72, 0x65, 0xd2, 0x94, 0x3c, 0xf2, 0x8c, 0xe1, 0x56, 0x1c, 0xb5}, + y: fp384{0x2d, 0x81, 0x3d, 0x6c, 0x59, 0x94, 0xd3, 0xf4, 0xc2, 0xe0, 0xca, 0x87, 0x1a, 0x8f, 0xe8, 0xd8, 0xe3, 0xf, 0x4d, 0xcf, 0x48, 0x2a, 0x9a, 0x78, 0x60, 0x8d, 0xc3, 0xfe, 0x2d, 0xac, 0xfe, 0xb7, 0xc3, 0xe, 0x49, 0x3b, 0x1c, 0xbd, 0xfd, 0x81, 0xe1, 0x79, 0x69, 0xcc, 0xb7, 0xad, 0x17, 0x46}, + }, + // 15P + { + x: fp384{0xa9, 0xf4, 0x9, 0x47, 0x88, 0xd8, 0x6a, 0x44, 0xd8, 0xab, 0x3d, 0xec, 0xe2, 0x10, 0x72, 0x2b, 0x34, 0x7b, 0xe0, 0x50, 0x95, 0xf1, 0xcc, 0x83, 0x75, 0x30, 0x9b, 0x78, 0x17, 0x9, 0x50, 0x59, 0x93, 0x59, 0x8, 0xeb, 0xd4, 0x1f, 0xc0, 0xf, 0x6b, 0x2, 0x3, 0x49, 0x6f, 0xd2, 0x62, 0xfb}, + y: fp384{0xbb, 0x89, 0xe9, 0x6f, 0x9d, 0xcc, 0x9, 0x23, 0x86, 0xd5, 0x4b, 0x14, 0xbd, 0x9c, 0x60, 0x61, 0xc, 0x61, 0x6, 0xde, 0xa0, 0xd3, 0x23, 0x4b, 0x70, 0xf4, 0x98, 0xd8, 0x66, 0x28, 0xdc, 0xdd, 0x97, 0x57, 0xc, 0x40, 0x41, 0xfc, 0x33, 0x87, 0x16, 0x27, 0xbc, 0xd0, 0xfe, 0xc6, 0x68, 0x5a}, + }, + // 17P + { + x: fp384{0xd0, 0x3c, 0x4a, 0x4b, 0x30, 0xe1, 0x3, 0x89, 0x3e, 0xf4, 0xf1, 0x8f, 0x4c, 0xea, 0xa4, 0x3e, 0xd, 0xa1, 0x55, 0xf6, 0x2a, 0x3f, 0xfc, 0xe6, 0xfc, 0xfe, 0x4f, 0x52, 0x7d, 0x73, 0xe3, 0x7b, 0x5e, 0x45, 0x30, 0x53, 0x55, 0x28, 0x69, 0x9f, 0x70, 0xce, 0x75, 0xe4, 0x6e, 0x16, 0x4f, 0x52}, + y: fp384{0x55, 0xf0, 0x12, 0x6c, 0xcd, 0x69, 0xcc, 0x3f, 0xda, 0xc0, 0xb9, 0xd5, 0xff, 0xb6, 0x23, 0x4e, 0x83, 0xf1, 0x6b, 0x33, 0x93, 0x69, 0xce, 0x49, 0x4a, 0x50, 0x54, 0x4a, 0x85, 0x6d, 0x7d, 0xf8, 0x7a, 0x67, 0xc2, 0xb3, 0xf1, 0x5d, 0xeb, 0x25, 0xc9, 0x64, 0xb1, 0x55, 0x6f, 0x98, 0x37, 0xac}, + }, + // 19P + { + x: fp384{0x8, 0x4c, 0xa8, 0xba, 0x4a, 0xed, 0xa2, 0x82, 0x12, 0xc9, 0xa8, 0x41, 0x5f, 0xcc, 0xc4, 0x22, 0x5e, 0xad, 0x4a, 0x15, 0x3b, 0x9c, 0x10, 0xca, 0x8e, 0x53, 0x38, 0xfc, 0x98, 0x12, 0x89, 0x23, 0xae, 0x2, 0x98, 0x53, 0x9c, 0x63, 0xb6, 0xb3, 0x6, 0xd7, 0x90, 0x3, 0x45, 0x1f, 0xf, 0xfa}, + y: fp384{0xd0, 0x21, 0xdc, 0xb0, 0x5d, 0x8e, 0xb7, 0x46, 0xac, 0x2e, 0xda, 0xc3, 0x3c, 0x2d, 0xc7, 0xa8, 0x43, 0xf6, 0xf2, 0x6f, 0x78, 0xb3, 0x70, 0x91, 0xc3, 0x30, 0x7f, 0xb6, 0x9b, 0x79, 0x5a, 0x3f, 0x72, 0xb6, 0x64, 0x82, 0x77, 0xdc, 0xd1, 0x15, 0x64, 0x77, 0x57, 0xe9, 0x23, 0x7b, 0xd4, 0xa1}, + }, + // 21P + { + x: fp384{0x2f, 0xce, 0x22, 0x4, 0x51, 0x5e, 0x26, 0x8, 0x21, 0x9e, 0x2f, 0xdd, 0x96, 0xd4, 0xe0, 0x88, 0x5d, 0xf7, 0x77, 0x61, 0xa0, 0x8a, 0x12, 0x30, 0x69, 0xbe, 0x9e, 0xbd, 0x62, 0xab, 0x59, 0x2e, 0x37, 0xe5, 0xf0, 0x5d, 0x6c, 0xf, 0x1a, 0x1b, 0xb5, 0x12, 0xc0, 0xda, 0x26, 0xc6, 0x16, 0xab}, + y: fp384{0xe7, 0x5d, 0x8c, 0x0, 0x4b, 0x21, 0x14, 0x80, 0xea, 0x7b, 0xf1, 0x38, 0x9e, 0xa, 0x74, 0xaa, 0x98, 0x90, 0x14, 0x8a, 0x49, 0xbb, 0x2e, 0x26, 0x59, 0xcd, 0x27, 0x85, 0x1e, 0x11, 0x54, 0xb4, 0x17, 0x58, 0xea, 0xac, 0x5a, 0xd1, 0x6a, 0x26, 0xba, 0xcc, 0x53, 0x13, 0x41, 0x4f, 0x82, 0x21}, + }, + // 23P + { + x: fp384{0x3b, 0x68, 0xe3, 0x12, 0x4d, 0xe7, 0xb4, 0xd1, 0xf6, 0x8e, 0x9b, 0x56, 0xb, 0xd2, 0xe, 0x99, 0x18, 0xa, 0x9c, 0x42, 0x25, 0xdd, 0xd3, 0xb9, 0x83, 0x17, 0x35, 0x2a, 0xab, 0xb8, 0x75, 0x1c, 0xf0, 0x32, 0x54, 0x90, 0x2b, 0xca, 0xe4, 0x61, 0x24, 0xf2, 0xa8, 0xee, 0x69, 0x6a, 0x82, 0x80}, + y: fp384{0xad, 0xab, 0x52, 0xec, 0x6b, 0x3a, 0xc3, 0x7f, 0x13, 0x48, 0x5e, 0xa6, 0xf0, 0xa3, 0xcc, 0xb, 0xbe, 0xce, 0x27, 0xa5, 0x32, 0xa1, 0xd8, 0x7a, 0x7e, 0x2c, 0xf2, 0xea, 0x50, 0x89, 0x13, 0xf0, 0xc1, 0x18, 0x67, 0x56, 0x37, 0x24, 0x2d, 0x28, 0x59, 0x25, 0x21, 0xe2, 0xd, 0xcb, 0xfc, 0x9d}, + }, + // 25P + { + x: fp384{0x83, 0x3b, 0xce, 0x58, 0x27, 0x72, 0x93, 0x1e, 0x36, 0xfb, 0xb3, 0x3c, 0xfa, 0xd, 0x28, 0xbb, 0x4a, 0x17, 0xbe, 0xe2, 0xd2, 0xf3, 0xd0, 0x57, 0x1e, 0xbe, 0x8a, 0x20, 0x99, 0x1b, 0xd5, 0x9b, 0x24, 0x80, 0x24, 0xde, 0x50, 0xab, 0x9, 0x38, 0x31, 0x73, 0xbb, 0xa5, 0x2c, 0x6e, 0x9c, 0xc2}, + y: fp384{0x5, 0x4f, 0x12, 0x61, 0x2e, 0xfd, 0x44, 0x99, 0x91, 0xe3, 0x9, 0x90, 0x4e, 0xbc, 0xcc, 0x83, 0xcc, 0xa3, 0x24, 0x94, 0x5, 0x8f, 0x62, 0x1, 0x44, 0x43, 0x8e, 0xea, 0x1d, 0xf5, 0xa2, 0xd6, 0x6e, 0xc9, 0xeb, 0x4c, 0x3d, 0x1a, 0x3e, 0xda, 0xdc, 0x9, 0x78, 0xe9, 0x42, 0xfb, 0xe6, 0x1f}, + }, + // 27P + { + x: fp384{0xe4, 0x66, 0x7d, 0x46, 0xd2, 0x82, 0x44, 0xa0, 0x1d, 0x29, 0x78, 0x4d, 0x93, 0x12, 0x19, 0xcf, 0xf9, 0x96, 0x23, 0x48, 0x68, 0x41, 0xd, 0x8e, 0xd0, 0x14, 0x8f, 0xd1, 0xd5, 0xe2, 0x28, 0x72, 0xfe, 0x58, 0x6a, 0x9c, 0x50, 0x8d, 0x7e, 0x2f, 0xec, 0x5a, 0x3e, 0x37, 0xe, 0x78, 0xca, 0xe8}, + y: fp384{0xf8, 0xe9, 0x68, 0x1b, 0xd6, 0xd1, 0xaa, 0x42, 0xf4, 0xf8, 0xe2, 0x69, 0xf5, 0xd7, 0xa6, 0x58, 0xea, 0x1b, 0xda, 0x31, 0xfe, 0xad, 0x79, 0xd7, 0x85, 0x5a, 0xc8, 0x38, 0x6, 0x54, 0x26, 0x7d, 0xdf, 0x3c, 0x4d, 0xd4, 0x95, 0x71, 0xe6, 0x67, 0xd7, 0x4e, 0x13, 0xc5, 0xb, 0xa, 0x82, 0x17}, + }, + // 29P + { + x: fp384{0x70, 0x14, 0x2, 0xd3, 0xc5, 0x6a, 0x9d, 0x1, 0xd6, 0x43, 0x4, 0x78, 0x66, 0x6b, 0x84, 0x25, 0x47, 0x76, 0xc9, 0x55, 0xed, 0x15, 0x3c, 0xce, 0xf, 0xeb, 0x3f, 0xe, 0x49, 0x2d, 0xc2, 0x3d, 0xe4, 0x26, 0xdf, 0xa7, 0xcb, 0xb7, 0x65, 0x20, 0x1f, 0xea, 0x7c, 0x18, 0xe8, 0xa, 0xb0, 0xc8}, + y: fp384{0xd3, 0xde, 0x5d, 0x86, 0xa0, 0x84, 0x52, 0x1a, 0xe2, 0x3d, 0xc8, 0x20, 0x49, 0x16, 0x3c, 0x29, 0xb3, 0x51, 0xe8, 0xcc, 0x26, 0x8d, 0x17, 0xab, 0xfb, 0x5, 0x45, 0x40, 0xb, 0xb1, 0x6d, 0x8e, 0x33, 0x20, 0xc8, 0x90, 0x71, 0x7e, 0xf5, 0xf6, 0x6c, 0xf1, 0x77, 0x59, 0x1, 0x1c, 0x2a, 0x1d}, + }, + // 31P + { + x: fp384{0xa4, 0x6, 0x89, 0x7c, 0x31, 0x89, 0x9c, 0xa3, 0xe6, 0x1e, 0x82, 0x9e, 0xdd, 0xec, 0xe7, 0xb6, 0xe6, 0x4f, 0xdf, 0xf0, 0x40, 0x83, 0xcf, 0x2e, 0x65, 0x49, 0xc1, 0x53, 0xc9, 0x7d, 0x2f, 0xd4, 0x85, 0x82, 0xba, 0xe3, 0xa3, 0x51, 0xfb, 0x1a, 0xd1, 0x5, 0x33, 0xa, 0x4, 0xc4, 0x7, 0x6c}, + y: fp384{0xda, 0xc1, 0x7f, 0x12, 0x88, 0x32, 0xb8, 0xda, 0x8, 0x4b, 0x4c, 0x37, 0x9b, 0x69, 0xa, 0xbc, 0xdd, 0x20, 0xeb, 0x42, 0xab, 0x9b, 0x2a, 0x40, 0x1c, 0x7a, 0x5a, 0x4, 0x4f, 0x46, 0xdd, 0xd7, 0xc4, 0xec, 0xbe, 0x36, 0x6d, 0xd, 0x3d, 0x5b, 0x9d, 0xa1, 0x98, 0x63, 0x75, 0x3e, 0x5a, 0x47}, + }, + // 33P + { + x: fp384{0x63, 0xba, 0xb3, 0x2f, 0x38, 0x3a, 0x33, 0x61, 0x86, 0x3c, 0x94, 0x5b, 0x9d, 0xd, 0x33, 0xdf, 0xaf, 0xf3, 0x5e, 0x95, 0xee, 0xc7, 0xc7, 0xbb, 0xfb, 0x9e, 0xf0, 0x60, 0xc1, 0x1f, 0x63, 0xda, 0x0, 0xc4, 0xd5, 0x41, 0x26, 0x62, 0xaf, 0x68, 0x9d, 0x3e, 0x83, 0x6c, 0xa4, 0x97, 0x9e, 0xcc}, + y: fp384{0x76, 0x5e, 0x62, 0x3a, 0x8e, 0x3e, 0xd7, 0x7f, 0x5e, 0xe5, 0x9, 0xc2, 0x24, 0x61, 0xbf, 0x13, 0x91, 0xb, 0xb9, 0x48, 0xea, 0x7c, 0x46, 0x8, 0xba, 0xa, 0x6f, 0xbb, 0xb9, 0x6e, 0x41, 0x8a, 0x72, 0x10, 0xc3, 0xb8, 0xa1, 0x93, 0xcc, 0x6f, 0xd7, 0xda, 0x57, 0x90, 0x61, 0x2b, 0xfd, 0xa7}, + }, + // 35P + { + x: fp384{0x9b, 0xec, 0x20, 0x37, 0x43, 0xb5, 0xa5, 0x58, 0xb4, 0x2f, 0x7c, 0x2d, 0xd5, 0x0, 0x38, 0xbb, 0xa, 0xbd, 0xe6, 0xdd, 0x20, 0x86, 0x50, 0x4a, 0xfd, 0x83, 0x25, 0xa0, 0x73, 0x62, 0xf1, 0x65, 0x23, 0x85, 0xc7, 0x4f, 0xe3, 0xd8, 0x2b, 0x83, 0xc6, 0x7b, 0x41, 0xe9, 0x75, 0x9f, 0x14, 0xd6}, + y: fp384{0x2a, 0xb5, 0xee, 0x3d, 0xe9, 0x26, 0xb0, 0xfe, 0x56, 0x9, 0x5e, 0xa5, 0x88, 0x80, 0xe1, 0xc, 0xa2, 0x92, 0x80, 0x98, 0x98, 0x89, 0x1, 0x50, 0xee, 0x5e, 0xf3, 0x28, 0xab, 0x9f, 0xf1, 0x22, 0x5c, 0xd3, 0xcc, 0x52, 0x7f, 0x87, 0x8a, 0xac, 0x26, 0x3f, 0xe2, 0x30, 0xd8, 0x8a, 0x3a, 0xb1}, + }, + // 37P + { + x: fp384{0xa3, 0x61, 0x4f, 0xe4, 0x7d, 0xd5, 0x2, 0x2, 0xf2, 0xe, 0x63, 0xb5, 0x4b, 0x70, 0x27, 0x40, 0x5d, 0x4a, 0xb5, 0xf5, 0xdf, 0xe2, 0x29, 0xa1, 0x86, 0x2b, 0x48, 0x97, 0x75, 0xa, 0xb6, 0xac, 0x14, 0x71, 0xf2, 0x7e, 0xe8, 0xed, 0x61, 0x92, 0xb5, 0x58, 0xfc, 0xde, 0xf3, 0x28, 0xba, 0x1e}, + y: fp384{0x9e, 0x58, 0xe5, 0x8b, 0xc9, 0xc0, 0x91, 0x6c, 0xee, 0x4b, 0x59, 0x14, 0xd5, 0x43, 0x16, 0x2f, 0x34, 0xa0, 0x2c, 0x5d, 0x43, 0x12, 0xa9, 0x2e, 0x1f, 0x7d, 0x4, 0x94, 0xa8, 0x49, 0x6, 0xb5, 0x37, 0xa3, 0x8c, 0x63, 0xb5, 0xcb, 0x4f, 0x28, 0x85, 0xbf, 0x85, 0xfe, 0xb7, 0x7, 0xe, 0xfa}, + }, + // 39P + { + x: fp384{0x42, 0xe, 0x6e, 0x50, 0x80, 0x4f, 0x89, 0x7d, 0x46, 0x2c, 0x3d, 0x8e, 0x4a, 0x24, 0x84, 0xd9, 0x6f, 0x0, 0x7f, 0x2b, 0x64, 0xdf, 0x7e, 0x6d, 0x30, 0x62, 0x9b, 0xde, 0x6d, 0xcd, 0xa1, 0x36, 0x65, 0x6, 0x6c, 0xb7, 0x40, 0x50, 0x98, 0xc9, 0xc2, 0x1f, 0x9b, 0xb8, 0xd6, 0xf4, 0x7d, 0x58}, + y: fp384{0x7a, 0xae, 0x71, 0x6a, 0x47, 0x38, 0x6, 0x4c, 0x47, 0x47, 0x29, 0xe8, 0xb3, 0xa, 0x2b, 0x7b, 0xb8, 0x53, 0x31, 0xb5, 0x3a, 0x55, 0x5c, 0x34, 0xe2, 0x9f, 0x6d, 0x43, 0x53, 0xe4, 0x46, 0xb6, 0x40, 0x3, 0xd6, 0x1c, 0x5f, 0x35, 0x95, 0x1a, 0xfb, 0x68, 0x49, 0x7, 0x28, 0xc1, 0x7b, 0x2d}, + }, + // 41P + { + x: fp384{0x4c, 0xd1, 0xa6, 0xbc, 0x87, 0x8e, 0x14, 0xad, 0x1e, 0x20, 0x6a, 0x45, 0x4d, 0xd2, 0xdf, 0x41, 0xf3, 0x68, 0xd, 0xa8, 0x33, 0x29, 0xa8, 0x73, 0x35, 0xa0, 0x2c, 0x85, 0x8d, 0x6c, 0x74, 0x89, 0xae, 0x71, 0xfd, 0x95, 0x88, 0x77, 0xbc, 0xe3, 0x5d, 0x24, 0x92, 0xda, 0x2c, 0xcd, 0x64, 0x87}, + y: fp384{0xe2, 0x23, 0xeb, 0x82, 0x47, 0x2c, 0xfe, 0xa2, 0x6e, 0x9d, 0x3c, 0xf, 0xe0, 0x62, 0xc7, 0x5a, 0x31, 0x6f, 0x64, 0x21, 0xe1, 0xc, 0x86, 0x57, 0x9a, 0x58, 0x9f, 0x4f, 0xc3, 0xd6, 0xc9, 0xbd, 0x2e, 0x27, 0x93, 0xd1, 0xc7, 0x52, 0x99, 0x67, 0xc5, 0xf1, 0x18, 0xeb, 0x2e, 0x70, 0xea, 0x82}, + }, + // 43P + { + x: fp384{0x44, 0x6d, 0x84, 0x0, 0x55, 0x93, 0xfa, 0x37, 0x8c, 0xbc, 0x78, 0x5, 0xc5, 0x2f, 0x11, 0x9, 0x3d, 0x94, 0xc4, 0x39, 0xb2, 0xf5, 0xd9, 0xda, 0x86, 0xbd, 0x6d, 0x41, 0xf0, 0xf5, 0x14, 0x73, 0x56, 0xfb, 0xfe, 0x1, 0xa9, 0x95, 0xf0, 0x5c, 0x93, 0xb3, 0xda, 0x22, 0xad, 0x8b, 0x17, 0x35}, + y: fp384{0xa7, 0xf1, 0xba, 0x36, 0x1b, 0xfc, 0x79, 0xcf, 0x98, 0x54, 0x9e, 0x74, 0x2d, 0xe4, 0x7e, 0x1b, 0xbb, 0x14, 0xe3, 0xed, 0xa9, 0x8a, 0xe7, 0xbc, 0xdf, 0x28, 0x6, 0xbd, 0xf6, 0xe0, 0xf8, 0xaa, 0x48, 0xf9, 0xcb, 0x15, 0x94, 0xb0, 0x74, 0xa9, 0x78, 0x2b, 0x63, 0xc9, 0x63, 0x1f, 0x3f, 0x8f}, + }, + // 45P + { + x: fp384{0x5b, 0xda, 0xdd, 0x4f, 0x56, 0x11, 0xc4, 0xd4, 0x12, 0x91, 0xad, 0x73, 0xc6, 0x65, 0xaf, 0xd4, 0x59, 0x8f, 0xeb, 0x39, 0xbb, 0xe0, 0xe8, 0xff, 0x13, 0xcf, 0x6f, 0x8d, 0xe, 0xc, 0x4, 0xb0, 0x99, 0xb5, 0x2b, 0x1f, 0xc6, 0xc0, 0xe1, 0x99, 0x5, 0x34, 0xac, 0xb2, 0x58, 0xc8, 0x94, 0x9c}, + y: fp384{0x5d, 0xd8, 0xee, 0x6e, 0xd7, 0x78, 0x88, 0x8f, 0x3f, 0xca, 0xfc, 0x51, 0x43, 0xf5, 0xb2, 0x62, 0x18, 0x69, 0xb5, 0xe5, 0xa9, 0x44, 0x3b, 0xeb, 0x93, 0x4e, 0x23, 0xb7, 0x76, 0x66, 0xf9, 0x16, 0x9e, 0xf1, 0x2a, 0xbd, 0x22, 0x77, 0x47, 0x17, 0x85, 0xa4, 0x83, 0xdb, 0x79, 0x29, 0xeb, 0x42}, + }, + // 47P + { + x: fp384{0xca, 0x68, 0xc6, 0xf0, 0x7d, 0x8f, 0x88, 0x6f, 0x6c, 0xc6, 0xd, 0x5f, 0x78, 0x88, 0xc7, 0x65, 0xa0, 0x7, 0x5b, 0x5f, 0x12, 0x85, 0xb1, 0xbf, 0xd0, 0xac, 0x78, 0xd8, 0xf7, 0xbf, 0xa, 0x78, 0x50, 0xf9, 0xc, 0x57, 0xb1, 0x21, 0x4f, 0x50, 0x71, 0x33, 0x23, 0xda, 0xc5, 0x37, 0x5b, 0xea}, + y: fp384{0xd1, 0x7e, 0x43, 0x22, 0xbd, 0xe8, 0x7a, 0x48, 0xb7, 0xf9, 0x9c, 0x24, 0x58, 0x17, 0x70, 0x9c, 0xff, 0x34, 0xfb, 0x98, 0xa8, 0x62, 0x65, 0xf8, 0x91, 0xfc, 0xe0, 0x65, 0xa2, 0xa1, 0xee, 0xdf, 0x23, 0xfc, 0x20, 0x2e, 0x91, 0x6, 0xf0, 0xee, 0x8b, 0x2a, 0xa7, 0xdf, 0xc7, 0xfe, 0x9d, 0xac}, + }, + // 49P + { + x: fp384{0xc6, 0x36, 0x71, 0x69, 0xef, 0x3a, 0x5c, 0xfa, 0xb8, 0x6f, 0xea, 0xa5, 0x63, 0xaf, 0xa5, 0x8e, 0xa4, 0x65, 0xe3, 0x42, 0x65, 0x15, 0x69, 0xa6, 0x86, 0x33, 0x6e, 0x5b, 0x11, 0x6c, 0xc5, 0x47, 0x56, 0x3f, 0xa0, 0xce, 0x2b, 0x83, 0x97, 0x11, 0x9e, 0xea, 0xe4, 0x50, 0xb2, 0xb, 0x47, 0xb}, + y: fp384{0x12, 0x57, 0xb2, 0x13, 0x43, 0xc7, 0x13, 0x31, 0x48, 0x7d, 0x49, 0xd2, 0x4e, 0x17, 0x6c, 0x8d, 0xe8, 0xeb, 0xc9, 0x49, 0xee, 0x86, 0x44, 0xfc, 0xd3, 0xbd, 0x82, 0x7f, 0xd5, 0xed, 0x87, 0x24, 0x2f, 0xbe, 0x57, 0x5b, 0x41, 0x64, 0x1e, 0x77, 0xdb, 0x2b, 0x8b, 0xe2, 0x18, 0xc5, 0x1c, 0x2d}, + }, + // 51P + { + x: fp384{0x8d, 0xac, 0x70, 0x20, 0xc7, 0xca, 0x4c, 0x2c, 0xb8, 0x22, 0x4a, 0xec, 0xca, 0xc0, 0x47, 0x19, 0xd9, 0x78, 0x5a, 0x8c, 0x59, 0xfb, 0xe0, 0xa5, 0xe7, 0x4d, 0xa8, 0x41, 0xd2, 0xe8, 0x4a, 0x46, 0x27, 0xbc, 0xaa, 0xda, 0xe9, 0x16, 0xba, 0x3d, 0x3c, 0xcb, 0x35, 0x4f, 0x50, 0x4a, 0x63, 0x16}, + y: fp384{0x4f, 0xc8, 0x6e, 0xb1, 0xf9, 0x8b, 0xc1, 0xad, 0x35, 0xdd, 0x59, 0x73, 0x7e, 0x6, 0x4d, 0x32, 0xf0, 0x43, 0x5, 0x57, 0xc3, 0xc0, 0xea, 0xda, 0x36, 0x7d, 0x88, 0x3c, 0x0, 0x40, 0x22, 0xb, 0xd, 0x1a, 0x3f, 0x37, 0xe2, 0x89, 0x94, 0xc6, 0x97, 0xd, 0xaa, 0xcb, 0x7d, 0x4, 0x8b, 0x51}, + }, + // 53P + { + x: fp384{0xef, 0x49, 0xde, 0xfb, 0xc6, 0xdd, 0x1b, 0x3b, 0xcc, 0x15, 0x9, 0x8a, 0x26, 0x7c, 0xed, 0xda, 0xa2, 0x22, 0x4, 0xf, 0x61, 0x10, 0x1, 0xb, 0x16, 0x4b, 0xc5, 0xa7, 0x74, 0x5c, 0x48, 0xcf, 0xe2, 0xaa, 0xc3, 0x15, 0xe6, 0xc4, 0x2e, 0x64, 0xea, 0x83, 0xf3, 0xe0, 0x10, 0x8f, 0xba, 0xa8}, + y: fp384{0x1, 0x85, 0x61, 0x95, 0xb4, 0x54, 0x20, 0x2a, 0x8b, 0xfa, 0x9e, 0x8, 0x42, 0x64, 0xec, 0xeb, 0x3e, 0xa8, 0x2f, 0x4e, 0x9a, 0xa1, 0x86, 0x57, 0x63, 0x99, 0x6, 0x39, 0xd1, 0x1a, 0xc7, 0xd2, 0xe2, 0x65, 0x17, 0x48, 0x9a, 0x3d, 0xc9, 0xad, 0x85, 0x94, 0xcc, 0x7e, 0xeb, 0xe3, 0xf2, 0xed}, + }, + // 55P + { + x: fp384{0x67, 0x33, 0x9f, 0x6, 0x60, 0x5f, 0xab, 0xbc, 0x3c, 0xec, 0x18, 0x17, 0xbc, 0x22, 0x66, 0xfd, 0xd6, 0x42, 0xa1, 0xe3, 0x67, 0x78, 0xfb, 0xa4, 0xb3, 0xae, 0x5f, 0x8, 0xbf, 0xd8, 0x78, 0x60, 0x4f, 0x55, 0xf4, 0x60, 0xda, 0xbf, 0x5c, 0xfa, 0x8, 0xd4, 0xc, 0x69, 0xd1, 0xd5, 0xfc, 0xb3}, + y: fp384{0x84, 0x78, 0x1f, 0x28, 0x7d, 0xee, 0xbd, 0x4e, 0xa7, 0x63, 0xa, 0x18, 0xaa, 0x23, 0xaf, 0x82, 0x61, 0x9f, 0x7, 0x3d, 0x7c, 0x10, 0xe3, 0x8d, 0xf8, 0x34, 0x23, 0xbe, 0xcb, 0xb5, 0xc6, 0x17, 0x6, 0xfa, 0xd0, 0x97, 0x39, 0xe7, 0x91, 0x6a, 0xd4, 0xee, 0xce, 0x14, 0x73, 0x25, 0x60, 0x74}, + }, + // 57P + { + x: fp384{0x5c, 0x86, 0x7f, 0xf9, 0x1c, 0xa6, 0x4b, 0xb1, 0xd, 0x8b, 0x4b, 0x69, 0xc1, 0xe4, 0xba, 0x73, 0x62, 0xbf, 0x4b, 0xac, 0xdf, 0x67, 0x49, 0xa1, 0xe0, 0x46, 0xf4, 0x9b, 0x50, 0xd1, 0x9d, 0x1e, 0xef, 0xce, 0x99, 0x1c, 0xeb, 0xf3, 0x52, 0xc0, 0x89, 0xc1, 0x78, 0x7a, 0xa0, 0x7f, 0x4d, 0x81}, + y: fp384{0x5d, 0xb0, 0x74, 0xab, 0x83, 0xa4, 0x1, 0xa1, 0x65, 0x7b, 0x73, 0xa1, 0x58, 0xc2, 0x88, 0x77, 0x3c, 0xa1, 0x9, 0xe8, 0xb7, 0xba, 0x60, 0xd, 0x5b, 0x1d, 0xc8, 0x73, 0xc4, 0x7b, 0x42, 0x8f, 0xfc, 0xc1, 0x52, 0x29, 0x55, 0x30, 0xe1, 0xd2, 0x63, 0xdf, 0x26, 0x4b, 0x9a, 0x3b, 0x82, 0xa}, + }, + // 59P + { + x: fp384{0xc9, 0x64, 0xbf, 0x27, 0xe2, 0x7c, 0x46, 0xaf, 0x4c, 0x97, 0x29, 0xf9, 0x97, 0x68, 0xca, 0xdf, 0x38, 0x27, 0x32, 0x5c, 0x59, 0x3b, 0x47, 0x64, 0x15, 0xe3, 0xd0, 0x1e, 0xcf, 0x17, 0xa9, 0x96, 0xb9, 0x4d, 0xe6, 0xd, 0x5b, 0x43, 0x3, 0x37, 0x46, 0xb6, 0x67, 0x92, 0x67, 0x39, 0xa0, 0x9b}, + y: fp384{0xbe, 0x2f, 0x52, 0x3a, 0xae, 0x2a, 0xc, 0xdf, 0xf0, 0xef, 0x35, 0xb3, 0x41, 0xb7, 0xbd, 0x41, 0x3, 0x97, 0x5, 0x7b, 0xdd, 0x2e, 0xcf, 0xac, 0xce, 0x3c, 0x46, 0x28, 0x30, 0x4b, 0xb3, 0x6f, 0x19, 0xca, 0xe3, 0xd9, 0xb, 0xba, 0xd9, 0x96, 0xc1, 0x55, 0x46, 0x50, 0x12, 0x6f, 0x33, 0xff}, + }, + // 61P + { + x: fp384{0xe0, 0xa6, 0x60, 0xfc, 0xd3, 0x1f, 0xda, 0x48, 0xe8, 0x41, 0x22, 0x22, 0x34, 0x5a, 0xfb, 0x54, 0x80, 0xe0, 0x2a, 0x77, 0x4f, 0xe3, 0x35, 0x60, 0xd0, 0x82, 0x29, 0x33, 0xf2, 0x7f, 0xf7, 0x5f, 0xfd, 0x51, 0xfe, 0x0, 0x73, 0x46, 0x66, 0x23, 0x6, 0xa0, 0x6b, 0xef, 0x49, 0xa0, 0x3e, 0xc9}, + y: fp384{0x66, 0x12, 0x38, 0x7d, 0x17, 0xf1, 0x40, 0x66, 0xac, 0xf4, 0xe9, 0x6a, 0xcd, 0x32, 0x4d, 0x39, 0xeb, 0x3, 0xd3, 0x70, 0x53, 0x88, 0xa7, 0xe6, 0x67, 0x57, 0x27, 0xe5, 0xff, 0x19, 0xda, 0xd, 0x23, 0x6d, 0x46, 0x1, 0x72, 0xc7, 0xa6, 0xb0, 0x29, 0x98, 0xc6, 0x1f, 0x45, 0x11, 0xcc, 0xc4}, + }, + // 63P + { + x: fp384{0xc0, 0x89, 0xed, 0xaa, 0xd7, 0xe6, 0xc0, 0xc5, 0x96, 0x18, 0x9a, 0x14, 0xd6, 0xea, 0xe8, 0x6c, 0x8f, 0x9f, 0x94, 0x8c, 0x45, 0xf7, 0x50, 0x7a, 0xaa, 0x71, 0x2b, 0x6e, 0xf7, 0x35, 0x7e, 0xcd, 0x7a, 0x9f, 0x4, 0x9a, 0x51, 0x9e, 0x15, 0xf6, 0x1e, 0x2d, 0xe5, 0xf1, 0xb0, 0xf0, 0x9b, 0x1c}, + y: fp384{0x80, 0x2c, 0x20, 0x18, 0xf5, 0xc1, 0xb6, 0x3b, 0x1a, 0x7b, 0xcd, 0x1e, 0x62, 0x5f, 0x3a, 0x8d, 0x19, 0x7f, 0xd1, 0x88, 0xe8, 0x34, 0xb0, 0x3b, 0x8d, 0x4, 0xd4, 0x97, 0x49, 0xbd, 0x89, 0xdc, 0x22, 0xdf, 0x35, 0x37, 0x8e, 0x7b, 0xaf, 0xf5, 0xe8, 0x89, 0xa6, 0xa0, 0x12, 0x37, 0xbb, 0x52}, + }, + // 65P + { + x: fp384{0x79, 0x96, 0x9b, 0x83, 0x54, 0x94, 0x46, 0x8e, 0x9f, 0x27, 0x1d, 0xd, 0x3b, 0xa4, 0xcd, 0xbe, 0x80, 0x3c, 0xb6, 0xed, 0x15, 0xdc, 0x9e, 0xcf, 0x2, 0xf0, 0xd5, 0xbd, 0x8a, 0xec, 0x97, 0x45, 0x53, 0x22, 0xb, 0x65, 0xb2, 0x50, 0x3, 0x8b, 0x6f, 0x26, 0xd4, 0x5f, 0x6a, 0x3a, 0x4c, 0xb8}, + y: fp384{0xf9, 0x79, 0xfc, 0x30, 0x3d, 0xd8, 0x16, 0xe, 0xd3, 0x95, 0xd9, 0x3a, 0x83, 0x87, 0xa4, 0xb6, 0x66, 0xc2, 0x2b, 0xde, 0x2c, 0x4b, 0x78, 0xab, 0xdd, 0x66, 0x9d, 0x88, 0x6d, 0x3d, 0x76, 0x19, 0x87, 0xf0, 0xf9, 0xc8, 0x24, 0x6c, 0x86, 0xa2, 0xc9, 0xb1, 0x5b, 0xa5, 0x28, 0x25, 0x6f, 0xea}, + }, + // 67P + { + x: fp384{0xca, 0x72, 0x17, 0x8b, 0xbc, 0x5c, 0xfc, 0x6e, 0x68, 0x4f, 0x63, 0xb, 0x3b, 0xdd, 0xc7, 0xea, 0x85, 0x61, 0x5d, 0xa5, 0xda, 0x5e, 0xd7, 0x65, 0xf7, 0xd8, 0xf3, 0x6e, 0x7e, 0x63, 0x6e, 0x55, 0x25, 0x9d, 0x90, 0x90, 0x4d, 0x3e, 0xaf, 0xf9, 0x5a, 0x3, 0x53, 0xe1, 0x48, 0xca, 0x62, 0xe4}, + y: fp384{0xd1, 0x9e, 0x10, 0xa, 0x7b, 0x3b, 0x76, 0x52, 0x6, 0x5d, 0x78, 0x42, 0xa6, 0xb1, 0x4a, 0x10, 0xbc, 0xe4, 0x59, 0x3f, 0xed, 0x35, 0x7e, 0x1a, 0x3, 0xc0, 0xeb, 0xc6, 0x46, 0xb7, 0x90, 0x59, 0xf9, 0xc5, 0x62, 0x13, 0xf0, 0x6b, 0x6a, 0x9, 0x94, 0x49, 0x79, 0xac, 0x8a, 0xcb, 0x22, 0x83}, + }, + // 69P + { + x: fp384{0x52, 0x27, 0xc, 0x67, 0x74, 0xdf, 0xd3, 0xf8, 0x28, 0x5e, 0x11, 0xa1, 0x59, 0x28, 0xcb, 0x5c, 0x1b, 0x98, 0x19, 0xf, 0xaa, 0xc8, 0x66, 0xcc, 0x65, 0xfd, 0xab, 0x25, 0xb1, 0xc8, 0xbc, 0xd4, 0xca, 0x3c, 0xdd, 0x4f, 0x16, 0xee, 0x86, 0x2c, 0xf4, 0x35, 0xf7, 0xa3, 0x78, 0x5d, 0xd6, 0x59}, + y: fp384{0xce, 0x55, 0xc, 0x7c, 0x28, 0xde, 0x5a, 0x3, 0x4d, 0x99, 0xd3, 0x45, 0x62, 0x9d, 0x76, 0x57, 0xa4, 0x23, 0xd4, 0x2b, 0x89, 0xe4, 0x3a, 0xd1, 0xbc, 0x66, 0xed, 0x82, 0x48, 0xee, 0xce, 0xa, 0x32, 0x7a, 0x16, 0x73, 0x8b, 0x9e, 0x2c, 0x6f, 0x7a, 0xbd, 0x1d, 0x27, 0x0, 0x1, 0xcd, 0xfb}, + }, + // 71P + { + x: fp384{0xb1, 0xfc, 0xfe, 0xef, 0x45, 0xce, 0x2e, 0xc4, 0x41, 0x14, 0xb1, 0xab, 0xb3, 0x31, 0x57, 0xbf, 0x92, 0xa, 0x8d, 0xe5, 0xcf, 0x15, 0xba, 0x93, 0x54, 0xac, 0x8, 0x35, 0x14, 0xde, 0xbb, 0x27, 0xda, 0x5d, 0x25, 0xfe, 0x38, 0x37, 0x12, 0x2b, 0x70, 0xcd, 0x7e, 0x53, 0x5a, 0xaa, 0x4f, 0xb}, + y: fp384{0xc6, 0x83, 0xec, 0xdd, 0x84, 0xd0, 0x44, 0x6a, 0x3d, 0x52, 0x1, 0x8, 0x4d, 0x3c, 0x79, 0x86, 0x19, 0xe3, 0xb3, 0x25, 0x50, 0x28, 0x4f, 0x15, 0x3a, 0x37, 0x64, 0xce, 0xf1, 0xda, 0x44, 0x21, 0x66, 0x95, 0x13, 0x7, 0xee, 0x24, 0xb9, 0xbd, 0x1c, 0xd0, 0x2a, 0x73, 0x28, 0xea, 0xa7, 0xf9}, + }, + // 73P + { + x: fp384{0x2, 0xa7, 0x51, 0xd8, 0x32, 0x5c, 0x38, 0x43, 0x3b, 0x96, 0xe8, 0x1d, 0xb1, 0xa9, 0xc2, 0xa9, 0x24, 0x9b, 0x8b, 0xdf, 0xb, 0x23, 0x8d, 0x5b, 0xc2, 0x31, 0x37, 0x2d, 0x25, 0xa9, 0x29, 0x90, 0xd2, 0xa7, 0xca, 0xe8, 0x4d, 0xb0, 0x8d, 0xb0, 0x3c, 0x67, 0xf4, 0x2b, 0xe7, 0x83, 0x9d, 0xb8}, + y: fp384{0x24, 0x44, 0xf2, 0xe1, 0xbf, 0x39, 0xfd, 0xa8, 0x16, 0xd6, 0xe8, 0xe1, 0xd6, 0xb6, 0x89, 0x9f, 0x6e, 0x21, 0x1d, 0x4f, 0x7b, 0xc8, 0x9f, 0xaf, 0x59, 0x5a, 0x26, 0x92, 0x3, 0x1e, 0xe2, 0x4, 0x73, 0x63, 0xb8, 0x87, 0x3, 0x74, 0x15, 0xb, 0x62, 0xa1, 0x98, 0x7c, 0x3b, 0xaf, 0x65, 0x6f}, + }, + // 75P + { + x: fp384{0xde, 0x3, 0x73, 0x86, 0x14, 0x40, 0x5d, 0x6b, 0xef, 0xb7, 0xa, 0x42, 0xa, 0xc4, 0xcb, 0xc8, 0x96, 0x9a, 0x54, 0x91, 0x89, 0xcf, 0x28, 0x5b, 0x66, 0x8f, 0x2f, 0x39, 0xb4, 0x31, 0x46, 0x5d, 0xc8, 0xb5, 0x67, 0xf3, 0x3d, 0xe2, 0x7e, 0x4a, 0x15, 0x7a, 0xca, 0xe6, 0xf, 0xae, 0xe0, 0xa1}, + y: fp384{0x7c, 0xa2, 0x9f, 0x13, 0xe1, 0x5e, 0x65, 0x2a, 0x1, 0xb9, 0xfa, 0x50, 0xc4, 0xc2, 0x31, 0xa5, 0x71, 0xed, 0xa, 0x43, 0x69, 0xab, 0x62, 0x67, 0x1d, 0x2e, 0x40, 0xf0, 0xe3, 0x39, 0xe2, 0x64, 0x45, 0xe4, 0x7f, 0x95, 0x42, 0x0, 0x87, 0xd7, 0x62, 0x65, 0x7d, 0x41, 0x62, 0xd8, 0x42, 0xfd}, + }, + // 77P + { + x: fp384{0x3f, 0x1a, 0x50, 0x2a, 0xc1, 0x34, 0x21, 0x9f, 0xa7, 0x93, 0x47, 0x33, 0x40, 0x9b, 0x4a, 0x11, 0x25, 0x61, 0x2a, 0x21, 0xc0, 0xb6, 0xcc, 0x27, 0xa3, 0x78, 0xce, 0x98, 0xb9, 0x30, 0xa9, 0xc, 0x27, 0x26, 0xa1, 0x28, 0xb, 0x6, 0x2e, 0x74, 0x16, 0x98, 0x5c, 0xfa, 0x7, 0x36, 0xd2, 0x63}, + y: fp384{0xdc, 0x91, 0x1f, 0xec, 0xa4, 0xcb, 0x4d, 0x77, 0x23, 0x1d, 0x4d, 0xf3, 0x2e, 0x7e, 0xcd, 0x34, 0x3d, 0x3c, 0xfd, 0x49, 0xe, 0x85, 0x0, 0x15, 0xb2, 0xcf, 0xc9, 0x30, 0x0, 0x95, 0x3, 0xdd, 0xa6, 0x41, 0x29, 0x57, 0xe5, 0xc3, 0x61, 0xce, 0x2e, 0xfd, 0x2c, 0x30, 0x75, 0x10, 0x4b, 0xd4}, + }, + // 79P + { + x: fp384{0x24, 0xc2, 0xa6, 0xe9, 0xd4, 0xd9, 0x11, 0xca, 0x85, 0x45, 0xb7, 0xc3, 0x48, 0xc2, 0xda, 0x2c, 0x71, 0x55, 0xca, 0x4, 0xa2, 0x1, 0x89, 0xe5, 0xf0, 0x1, 0x5d, 0xd1, 0x2d, 0x31, 0x1c, 0x49, 0x7c, 0xcb, 0x69, 0x70, 0x8a, 0x81, 0xcc, 0xb3, 0xda, 0x12, 0x39, 0xd5, 0xa5, 0x45, 0xb2, 0x23}, + y: fp384{0x63, 0xb1, 0xb0, 0xa6, 0x8b, 0x83, 0xf7, 0x30, 0x52, 0x55, 0x77, 0x32, 0x3e, 0xeb, 0x52, 0xa0, 0xc1, 0x5e, 0xb9, 0xee, 0xe9, 0x43, 0x32, 0x40, 0xb3, 0x2e, 0x63, 0x8, 0x1b, 0x30, 0x7b, 0x61, 0xf9, 0x81, 0x2, 0xf3, 0xc9, 0x66, 0x1c, 0x94, 0x55, 0xb2, 0x7a, 0x1d, 0xf8, 0x28, 0x97, 0x4b}, + }, + // 81P + { + x: fp384{0x82, 0xf6, 0x6, 0xdb, 0xcb, 0xd3, 0xbd, 0x3c, 0x85, 0x87, 0xc0, 0x86, 0x3e, 0x47, 0x45, 0xde, 0xfb, 0x1b, 0x7b, 0xe0, 0x60, 0x35, 0xcb, 0xd8, 0xaf, 0x38, 0xf1, 0xea, 0x8f, 0x11, 0xc3, 0xf2, 0xaf, 0x6f, 0x43, 0x9f, 0x85, 0x8a, 0x23, 0x11, 0x4f, 0x34, 0xdf, 0x7c, 0xe3, 0xc2, 0x84, 0x9}, + y: fp384{0x4f, 0x58, 0x82, 0xc3, 0x17, 0x3c, 0x8, 0xe1, 0x40, 0xa2, 0x6f, 0x73, 0xd4, 0x14, 0x9a, 0x95, 0x7d, 0x63, 0xf2, 0x18, 0xf0, 0xd2, 0xad, 0x56, 0x8d, 0x27, 0xdd, 0xe5, 0x5e, 0x7a, 0x4, 0x1, 0xa7, 0x6, 0x27, 0xae, 0x63, 0x8d, 0xe3, 0x5d, 0x7e, 0xb8, 0x45, 0x97, 0x60, 0xb7, 0xd7, 0x9d}, + }, + // 83P + { + x: fp384{0x71, 0x40, 0xe9, 0x44, 0xbf, 0xf0, 0x61, 0x8e, 0xb4, 0x5e, 0xf0, 0xd2, 0x7e, 0x84, 0xcf, 0x44, 0xeb, 0x94, 0x66, 0x4a, 0xd, 0xaa, 0x87, 0x84, 0xb5, 0xaa, 0xa4, 0xc7, 0xa1, 0x8c, 0xb8, 0xee, 0x26, 0x89, 0xa, 0x52, 0x3, 0xaa, 0x5b, 0xc2, 0x5, 0x78, 0x3d, 0xc0, 0x6a, 0xb1, 0x75, 0xa0}, + y: fp384{0xc3, 0x70, 0xd9, 0x13, 0x8a, 0xa4, 0x57, 0xc3, 0x3e, 0x64, 0x9, 0x60, 0x70, 0x13, 0x3c, 0x4e, 0x29, 0x4, 0xe6, 0x49, 0x57, 0xa9, 0x21, 0xcf, 0xda, 0xbc, 0x51, 0x22, 0xba, 0x62, 0xa2, 0xa, 0xe4, 0x78, 0x3c, 0x56, 0xd0, 0x7c, 0x2a, 0xb7, 0xf9, 0x1c, 0xce, 0x69, 0xda, 0xfe, 0x3d, 0x77}, + }, + // 85P + { + x: fp384{0x2d, 0x76, 0x6, 0x9b, 0xdf, 0x2c, 0x5d, 0x93, 0x5a, 0x25, 0x7, 0x82, 0xb8, 0xbb, 0x48, 0x21, 0xd8, 0x53, 0x31, 0x5, 0xdd, 0xca, 0xbd, 0x7b, 0x57, 0x6a, 0x25, 0x73, 0xff, 0xaa, 0x53, 0xd9, 0x1, 0x6f, 0x4e, 0x11, 0xe1, 0x8f, 0xa0, 0xb0, 0x4d, 0x4d, 0xe6, 0x46, 0x54, 0x2, 0x35, 0xc8}, + y: fp384{0x57, 0xc1, 0xdb, 0x0, 0xd8, 0xba, 0xcf, 0xe7, 0x69, 0xe9, 0xfb, 0x71, 0x2, 0xae, 0x2a, 0x39, 0x14, 0xe3, 0xeb, 0xb, 0x2a, 0xa7, 0x22, 0x74, 0xf2, 0x52, 0xaf, 0x2c, 0xd2, 0x55, 0xd4, 0xc3, 0x95, 0x51, 0x89, 0xe2, 0x9f, 0x83, 0x31, 0xa2, 0x13, 0xf2, 0x93, 0xc9, 0x92, 0x8d, 0x21, 0x6c}, + }, + // 87P + { + x: fp384{0x2e, 0x37, 0xa0, 0x4a, 0x2e, 0xa0, 0x11, 0x4f, 0x75, 0x77, 0x96, 0x10, 0x30, 0x47, 0x42, 0x59, 0x95, 0x91, 0x80, 0x8b, 0xba, 0xc1, 0xe, 0xdf, 0xf1, 0x3a, 0x3c, 0x9a, 0x8d, 0x92, 0xa, 0xf3, 0x2e, 0x6b, 0x7b, 0x38, 0x20, 0x3, 0x84, 0xc4, 0x22, 0xbb, 0x0, 0xa5, 0x17, 0x34, 0x1b, 0x1c}, + y: fp384{0xf2, 0x66, 0x32, 0xbf, 0xc7, 0xe6, 0xe, 0x69, 0x81, 0x96, 0x90, 0xa7, 0x74, 0x6d, 0x24, 0x18, 0x8f, 0xa8, 0x84, 0xf9, 0x54, 0x24, 0xdf, 0xde, 0x9, 0x9f, 0x55, 0xe7, 0x75, 0x41, 0x94, 0x31, 0xb7, 0x4d, 0x7b, 0xe, 0x88, 0x81, 0xac, 0xbd, 0x68, 0xfe, 0x96, 0xe9, 0xae, 0x6f, 0x4, 0x9f}, + }, + // 89P + { + x: fp384{0xac, 0xd4, 0x71, 0x2d, 0x4b, 0x9, 0x62, 0xc, 0xe0, 0x63, 0xf1, 0x4b, 0xdc, 0x9f, 0xa4, 0x18, 0x1f, 0x72, 0x96, 0x0, 0xb, 0xf3, 0x3d, 0x46, 0x7b, 0x5b, 0xe5, 0xc8, 0x4a, 0x64, 0xd3, 0x67, 0xb6, 0xe2, 0xe0, 0x19, 0x9d, 0xd2, 0x3d, 0xd6, 0x61, 0x73, 0x4b, 0x16, 0xde, 0x5, 0xd1, 0xd0}, + y: fp384{0x8e, 0x18, 0x17, 0x2, 0x4e, 0x5c, 0x86, 0xe5, 0x7e, 0xcf, 0x93, 0x20, 0x1b, 0xb7, 0x61, 0x78, 0x3c, 0x25, 0xaa, 0x2d, 0x51, 0xf0, 0xcc, 0x65, 0xc0, 0xe4, 0x4d, 0xb, 0x9, 0x1, 0x77, 0x14, 0xd9, 0x62, 0xb9, 0x40, 0x35, 0x24, 0x28, 0x1d, 0xf3, 0x37, 0xdf, 0xb8, 0x39, 0xe9, 0xc7, 0x1}, + }, + // 91P + { + x: fp384{0x58, 0x8, 0xba, 0x9c, 0x9c, 0x40, 0xea, 0x5d, 0x63, 0x3f, 0xae, 0x14, 0x1b, 0x42, 0xc2, 0x35, 0x8a, 0x61, 0xc2, 0xbb, 0x34, 0xe5, 0xf6, 0xa4, 0x5f, 0x4f, 0xd7, 0x42, 0x7d, 0x97, 0x4b, 0xb0, 0xb7, 0x3e, 0xdc, 0x59, 0x27, 0x38, 0xe7, 0xe7, 0xb0, 0x23, 0xf2, 0x8b, 0x34, 0x52, 0xf, 0xeb}, + y: fp384{0x58, 0x51, 0xc7, 0xf, 0x67, 0x51, 0x1c, 0x99, 0x6d, 0x2c, 0xde, 0x3f, 0x1a, 0x81, 0x12, 0xd0, 0x3d, 0x34, 0x36, 0x92, 0x31, 0xb3, 0xd0, 0x9, 0xa0, 0xcb, 0xa2, 0x63, 0xc8, 0xe0, 0x78, 0xcb, 0x78, 0x84, 0xb8, 0x9a, 0xbd, 0xb3, 0x9, 0xb, 0xe2, 0xc6, 0x16, 0xf1, 0x3, 0xc7, 0xca, 0x47}, + }, + // 93P + { + x: fp384{0xaf, 0x80, 0x2d, 0xe3, 0x71, 0x4d, 0xd1, 0xeb, 0x5e, 0x67, 0x80, 0x53, 0x4f, 0xc2, 0x1c, 0x1b, 0xcd, 0x42, 0x61, 0xb1, 0x64, 0x47, 0x63, 0x1c, 0xe, 0xb0, 0xfd, 0x7c, 0xde, 0x45, 0x35, 0x7a, 0x54, 0x51, 0xd1, 0xcf, 0x89, 0x16, 0xf9, 0x2d, 0xd7, 0xa2, 0xa, 0x43, 0xb3, 0x55, 0x33, 0x81}, + y: fp384{0x7e, 0xca, 0xf2, 0x85, 0xc9, 0xe2, 0xdc, 0x16, 0x79, 0xbb, 0x3a, 0xe0, 0xf7, 0x3, 0xe3, 0xd9, 0x98, 0x66, 0xb0, 0x3c, 0x10, 0xa8, 0x7c, 0xfe, 0xcb, 0xd, 0x67, 0x71, 0x5b, 0x42, 0x2a, 0x57, 0xe5, 0x68, 0xa2, 0x90, 0x54, 0x39, 0x1b, 0xc7, 0x9, 0x9d, 0xbf, 0x66, 0x8f, 0xf3, 0x71, 0xc0}, + }, + // 95P + { + x: fp384{0x91, 0x3c, 0xbc, 0xd, 0x63, 0xf2, 0xc0, 0xf, 0xb1, 0xcb, 0xc0, 0x9b, 0x16, 0xca, 0x74, 0x9f, 0x77, 0x89, 0xf9, 0xe, 0x9d, 0x7b, 0x60, 0x4a, 0x79, 0x2b, 0x7d, 0xa2, 0xef, 0xb, 0xe9, 0xb, 0xe1, 0x23, 0x7f, 0xad, 0xb5, 0xb, 0x7b, 0x25, 0xe4, 0xd1, 0xea, 0x2f, 0xe5, 0x2f, 0xf4, 0xb8}, + y: fp384{0x92, 0xb5, 0x93, 0x5f, 0x31, 0xe4, 0x78, 0xde, 0x7d, 0x61, 0x79, 0xfd, 0xeb, 0xe7, 0x5f, 0x50, 0xfb, 0xf9, 0x99, 0xdd, 0x14, 0x3f, 0xcc, 0x45, 0x91, 0xb5, 0xc7, 0x3b, 0xe8, 0x64, 0xf, 0x8c, 0xf9, 0x93, 0xab, 0x55, 0xed, 0x4d, 0x36, 0x65, 0x6e, 0x28, 0xdf, 0x42, 0xa5, 0x4b, 0x6d, 0xbb}, + }, + // 97P + { + x: fp384{0xe2, 0x54, 0x5c, 0x7f, 0x5d, 0x3, 0xd2, 0x7c, 0x2c, 0x49, 0x49, 0x4a, 0x0, 0xdb, 0xf0, 0xc1, 0x98, 0x8f, 0x27, 0x65, 0x30, 0x3e, 0x27, 0x8f, 0x9d, 0x9d, 0xef, 0x6f, 0xd1, 0x1e, 0x24, 0x10, 0x16, 0x96, 0x6, 0xac, 0x1b, 0xe5, 0xb1, 0x87, 0x7f, 0x80, 0xd, 0x17, 0xcd, 0x1a, 0x8, 0x8c}, + y: fp384{0x98, 0xb5, 0x73, 0x1c, 0xea, 0x51, 0x50, 0x0, 0xf4, 0x5b, 0x86, 0xd6, 0x12, 0x55, 0xeb, 0xe4, 0xd3, 0x5d, 0xe0, 0x30, 0xf4, 0x4e, 0xd2, 0xd7, 0x9e, 0xa3, 0x89, 0x78, 0xed, 0xe4, 0x47, 0xcb, 0x64, 0x69, 0xf5, 0xc4, 0x91, 0x24, 0x3e, 0x4c, 0x6, 0x30, 0xf0, 0xc4, 0x8e, 0xb7, 0xc6, 0x83}, + }, + // 99P + { + x: fp384{0xa1, 0x84, 0x5f, 0xb0, 0xa9, 0x35, 0x38, 0x6e, 0x4e, 0x17, 0xaa, 0x41, 0xf, 0x9e, 0x4f, 0xbb, 0x69, 0xa4, 0x8b, 0x70, 0x7c, 0x17, 0x41, 0x1b, 0xbd, 0xf8, 0xc8, 0x79, 0xb4, 0xe6, 0xb2, 0xb9, 0xbd, 0xd6, 0xd9, 0x82, 0x9, 0xae, 0x9c, 0xd4, 0x3a, 0x22, 0x28, 0xbb, 0x0, 0x5f, 0x8c, 0x64}, + y: fp384{0xa5, 0xc4, 0x8c, 0x5d, 0x76, 0x85, 0xf4, 0x4, 0x8d, 0xa3, 0xa0, 0x81, 0xdd, 0x96, 0x30, 0xfe, 0xe1, 0x47, 0x82, 0x70, 0x8f, 0x13, 0x75, 0x66, 0x8, 0xea, 0xa0, 0xd1, 0xd8, 0x59, 0xf7, 0xd6, 0x98, 0xd, 0x19, 0x76, 0xb1, 0x93, 0x74, 0x1f, 0xbd, 0x63, 0x2d, 0x32, 0x8b, 0x69, 0xe1, 0x3}, + }, + // 101P + { + x: fp384{0xac, 0xde, 0x8a, 0x9b, 0xf6, 0xc6, 0x66, 0x8e, 0x70, 0x6d, 0xc6, 0x50, 0xfe, 0xf5, 0x39, 0xb5, 0x1a, 0xfb, 0xcc, 0x2e, 0x2c, 0xcd, 0xdd, 0x73, 0xfc, 0x5c, 0x8b, 0x8b, 0xad, 0x1f, 0x3b, 0xd7, 0x10, 0x87, 0xa1, 0x47, 0x35, 0x94, 0xdd, 0x9c, 0xdb, 0x14, 0xc8, 0x7b, 0xbf, 0x92, 0x23, 0x7e}, + y: fp384{0xe8, 0x74, 0x8f, 0x6c, 0xc0, 0x93, 0x41, 0x91, 0x4d, 0xc0, 0x67, 0x1d, 0x21, 0xdc, 0xed, 0xff, 0x93, 0x86, 0xd6, 0xa, 0x85, 0x41, 0xef, 0x1f, 0x54, 0x80, 0x3e, 0xf5, 0x9a, 0x1d, 0x3e, 0xa7, 0x4, 0xc1, 0xe, 0x42, 0x6f, 0x65, 0x9b, 0x90, 0xde, 0xe1, 0x2, 0x17, 0x36, 0x2d, 0x87, 0x73}, + }, + // 103P + { + x: fp384{0x5f, 0x5d, 0x35, 0x21, 0xaa, 0xab, 0x4c, 0xd2, 0xbd, 0x2, 0xd4, 0xaf, 0xe, 0xb1, 0xcb, 0xdd, 0xe1, 0x1d, 0xc2, 0x29, 0x43, 0xd1, 0xf0, 0xd3, 0xfc, 0x84, 0x3d, 0xf2, 0x94, 0x5a, 0xd9, 0x1a, 0xd, 0x53, 0xda, 0xe3, 0x2, 0x79, 0x3a, 0x11, 0x48, 0x10, 0x67, 0x64, 0x8e, 0xa8, 0xd, 0x59}, + y: fp384{0xda, 0xf0, 0x5b, 0x92, 0x82, 0x82, 0xa5, 0xf4, 0xb, 0x6e, 0x2e, 0xe6, 0xe7, 0xe4, 0x52, 0x1a, 0xfd, 0x4d, 0x6f, 0xd8, 0x4e, 0xbb, 0xeb, 0x97, 0xc3, 0xd1, 0xfa, 0x58, 0xc3, 0xd1, 0x1b, 0x60, 0x52, 0x5, 0xe4, 0x2d, 0xa6, 0xd5, 0xe2, 0xd6, 0xed, 0xdb, 0x73, 0x72, 0x37, 0x71, 0x9e, 0xc}, + }, + // 105P + { + x: fp384{0x45, 0x28, 0x80, 0xe5, 0x85, 0x19, 0xe9, 0xe6, 0xbc, 0x1, 0xe2, 0xa6, 0xae, 0xd6, 0x67, 0xc3, 0xbe, 0x23, 0x2c, 0xdd, 0xe5, 0x30, 0x7f, 0x7, 0xe3, 0x75, 0x50, 0x27, 0x9c, 0xf3, 0x2e, 0x86, 0x42, 0x65, 0x80, 0x1a, 0x44, 0x75, 0x2c, 0x2, 0x9c, 0xd0, 0xeb, 0x99, 0x3a, 0x3e, 0xab, 0xd0}, + y: fp384{0xb8, 0x28, 0x90, 0xd9, 0x60, 0xef, 0x67, 0x7d, 0x6b, 0x13, 0xad, 0xa9, 0x4f, 0x36, 0xcf, 0xa5, 0x8c, 0xff, 0x1f, 0xa9, 0xa9, 0x23, 0x2c, 0x37, 0x60, 0x25, 0x20, 0x47, 0x95, 0x7a, 0xd5, 0xd3, 0x23, 0x19, 0x2f, 0x15, 0x45, 0xf1, 0xba, 0xce, 0xa5, 0x73, 0x89, 0x6d, 0x2c, 0xe7, 0x3a, 0xcc}, + }, + // 107P + { + x: fp384{0x23, 0x3f, 0x36, 0xf4, 0xe1, 0xe8, 0x18, 0xd7, 0x90, 0x14, 0x76, 0x4f, 0x20, 0x1e, 0xc2, 0x73, 0x46, 0x5d, 0x7, 0xa0, 0x25, 0xec, 0xc6, 0x27, 0xd0, 0x40, 0x3f, 0x75, 0x56, 0xf4, 0xd4, 0xcc, 0x22, 0x16, 0xa9, 0x60, 0x49, 0x4c, 0x99, 0x50, 0x48, 0xb, 0x74, 0x3f, 0x79, 0x4d, 0x96, 0x77}, + y: fp384{0x2, 0xed, 0x47, 0xf6, 0xe2, 0x55, 0xc9, 0xf4, 0x79, 0x3d, 0x19, 0xe4, 0x9a, 0xc7, 0x4f, 0x84, 0x9f, 0x3f, 0x7f, 0xa2, 0xd1, 0x74, 0x83, 0x48, 0x63, 0x94, 0x65, 0xb8, 0x45, 0xad, 0xd6, 0x95, 0x39, 0x8e, 0x43, 0xc7, 0x78, 0x9f, 0xd9, 0xe1, 0xf2, 0xed, 0xfc, 0x2a, 0x17, 0xa7, 0x82, 0x51}, + }, + // 109P + { + x: fp384{0xfa, 0xb1, 0xde, 0xb2, 0x27, 0x2e, 0xfc, 0xe, 0x4b, 0x18, 0xc1, 0x3c, 0x83, 0x35, 0x7d, 0x9c, 0xc8, 0xbd, 0xdc, 0xa8, 0xf8, 0xc5, 0x41, 0x58, 0xbb, 0x3a, 0xd9, 0xf0, 0x8a, 0xa5, 0x11, 0xa9, 0x87, 0xf8, 0xcf, 0xb9, 0x33, 0x8c, 0xd1, 0x3c, 0x3, 0x24, 0x3f, 0xf1, 0xbb, 0x27, 0x3c, 0x6e}, + y: fp384{0xe6, 0x3a, 0x53, 0xea, 0x12, 0x17, 0x39, 0x5b, 0x5, 0x4c, 0x29, 0x54, 0xb, 0xd9, 0xcd, 0x35, 0xf4, 0xda, 0x60, 0xf5, 0xb4, 0x7f, 0xb5, 0x2d, 0x1d, 0x41, 0xa1, 0xf5, 0xca, 0x33, 0xad, 0x75, 0x68, 0x75, 0x7c, 0x7f, 0x4e, 0x9a, 0xe1, 0x87, 0x5, 0x77, 0x8c, 0x19, 0x56, 0x6c, 0xc4, 0xf4}, + }, + // 111P + { + x: fp384{0xb8, 0x74, 0xbe, 0x5, 0x48, 0xb7, 0xb3, 0x8d, 0xab, 0x5f, 0x76, 0x0, 0x50, 0x80, 0xe0, 0x8, 0xd9, 0x7f, 0x44, 0x50, 0xb, 0x72, 0x44, 0x67, 0x3, 0xbe, 0x27, 0xc7, 0x12, 0x20, 0x55, 0x27, 0x7f, 0x66, 0x2, 0x8b, 0x51, 0x7b, 0x90, 0xc3, 0x14, 0xef, 0xbd, 0xb9, 0xbc, 0xaa, 0x58, 0xa1}, + y: fp384{0x6f, 0xc5, 0x9c, 0xf4, 0x3, 0xfa, 0xdd, 0xaa, 0x96, 0xfb, 0x5, 0xe3, 0xe4, 0xbe, 0x95, 0x10, 0x19, 0x26, 0xc3, 0x93, 0xbc, 0x54, 0xff, 0xa2, 0x85, 0x26, 0xeb, 0x4a, 0xf9, 0xe1, 0xf8, 0xcc, 0xfe, 0xd9, 0x0, 0x23, 0xb8, 0x47, 0x4b, 0xc6, 0xa9, 0x9d, 0x27, 0x8, 0x68, 0x77, 0xca, 0x9}, + }, + // 113P + { + x: fp384{0x12, 0xda, 0xb, 0x9b, 0xb7, 0x86, 0x5b, 0xf8, 0x72, 0x35, 0xe3, 0xbb, 0xd1, 0x16, 0xc6, 0xd2, 0x7f, 0xd2, 0x2b, 0x85, 0xef, 0x15, 0x22, 0xe7, 0xc5, 0x7f, 0x9b, 0x13, 0x9, 0x5b, 0x81, 0xe9, 0xc2, 0xa0, 0x7f, 0x8d, 0x4, 0xdb, 0x5b, 0x4a, 0x86, 0xa9, 0x86, 0xff, 0x17, 0xcd, 0x9f, 0x86}, + y: fp384{0xbe, 0xf6, 0xda, 0x91, 0x17, 0x52, 0x78, 0x32, 0x4, 0x4d, 0x66, 0xd6, 0xf1, 0x7, 0xc0, 0xb9, 0x29, 0x20, 0xb1, 0xe7, 0x2a, 0x72, 0x98, 0x69, 0x67, 0xbb, 0x31, 0xfc, 0xd9, 0xde, 0x7f, 0xbf, 0x57, 0x77, 0xb8, 0x31, 0x7c, 0xd1, 0xe, 0x3d, 0x4b, 0x94, 0xf7, 0x55, 0xf2, 0x3d, 0xb, 0xa1}, + }, + // 115P + { + x: fp384{0x56, 0x8f, 0x49, 0x34, 0x3b, 0x67, 0x4e, 0xaa, 0x6d, 0x45, 0x43, 0xa0, 0xb3, 0xf7, 0x20, 0x91, 0x26, 0x88, 0xa4, 0x26, 0xf3, 0x68, 0xe8, 0x33, 0xfd, 0x6b, 0x40, 0x32, 0xf4, 0xcc, 0x7a, 0xa9, 0x46, 0x7, 0xc5, 0x23, 0x41, 0x2a, 0x44, 0x84, 0x2d, 0x98, 0x50, 0x73, 0x65, 0x69, 0x4c, 0x27}, + y: fp384{0xaa, 0x9e, 0xdc, 0x95, 0xfb, 0xb7, 0x6, 0x31, 0x41, 0xe2, 0x7a, 0xec, 0xb1, 0x1d, 0xbf, 0x3e, 0x86, 0x5b, 0x8a, 0x84, 0xb8, 0x39, 0xdc, 0x0, 0xc6, 0x2e, 0x31, 0xf6, 0x3a, 0x34, 0x9a, 0xdf, 0x3, 0x1f, 0x12, 0xcf, 0x32, 0x9e, 0x2, 0x75, 0xdb, 0x11, 0x5a, 0xcf, 0xf6, 0xbd, 0xc5, 0xc0}, + }, + // 117P + { + x: fp384{0x9a, 0x55, 0x23, 0x7, 0xa8, 0xe7, 0xcc, 0xfd, 0x70, 0xd0, 0x29, 0xa2, 0xe, 0xb3, 0x32, 0x95, 0x61, 0x79, 0x85, 0xfe, 0x94, 0x52, 0x3e, 0x61, 0x8d, 0x73, 0xea, 0x9a, 0x9a, 0x74, 0x9e, 0xad, 0x53, 0xba, 0xac, 0x23, 0xae, 0x6b, 0x7a, 0x51, 0x8b, 0x56, 0x23, 0x78, 0xcd, 0x74, 0x67, 0xf2}, + y: fp384{0x4d, 0x11, 0x53, 0xae, 0xa1, 0x67, 0x7, 0x94, 0x7b, 0x5, 0x8c, 0xeb, 0x4b, 0x3a, 0xcb, 0xc6, 0x0, 0xf6, 0xae, 0x6, 0x5f, 0xc0, 0x99, 0x6d, 0x81, 0x84, 0x79, 0xb2, 0x8d, 0x9b, 0x72, 0xa6, 0x5b, 0x58, 0xf1, 0xbf, 0x82, 0x65, 0x54, 0x7a, 0x73, 0x97, 0xb0, 0x82, 0xb0, 0x9a, 0x50, 0x70}, + }, + // 119P + { + x: fp384{0xd1, 0xd8, 0x29, 0x73, 0xac, 0x95, 0x25, 0x73, 0xc4, 0xbc, 0x73, 0xab, 0x8d, 0x7, 0xf9, 0x59, 0xde, 0x9d, 0xcf, 0x21, 0xb4, 0xe7, 0x55, 0xcd, 0x27, 0xab, 0x5f, 0x87, 0xa1, 0xb, 0x63, 0xa4, 0xcd, 0xf4, 0x9c, 0xec, 0xb8, 0x7f, 0x16, 0x13, 0x77, 0x5, 0x8b, 0x99, 0x57, 0x5c, 0xfc, 0xd2}, + y: fp384{0x6f, 0x1b, 0xf5, 0x5f, 0xc1, 0x60, 0x13, 0x76, 0xeb, 0x9c, 0xcf, 0x6, 0xf2, 0x96, 0xdb, 0xb2, 0x46, 0x8f, 0xdc, 0x99, 0x48, 0xa6, 0x77, 0xd6, 0xe5, 0xb7, 0x9, 0x91, 0xbc, 0xca, 0x9e, 0xeb, 0xa3, 0xb7, 0x21, 0x92, 0xac, 0xb1, 0x1b, 0x9a, 0xcd, 0xa5, 0x40, 0x8a, 0x28, 0x36, 0x65, 0xb1}, + }, + // 121P + { + x: fp384{0x8d, 0xfa, 0x9d, 0x18, 0x40, 0xba, 0x98, 0x51, 0x1e, 0xab, 0x96, 0xa8, 0xe3, 0x16, 0x9a, 0x8c, 0xe4, 0x44, 0x67, 0xba, 0xd6, 0xd5, 0x33, 0x6c, 0x8a, 0x77, 0x72, 0x77, 0xd4, 0xfb, 0x9a, 0xc2, 0xe0, 0xf7, 0x29, 0x93, 0x95, 0x3c, 0xdf, 0x65, 0x81, 0xdb, 0x91, 0x38, 0x1e, 0x3f, 0xcd, 0x79}, + y: fp384{0x9b, 0x1, 0x84, 0xd7, 0xb, 0x8f, 0xaa, 0xca, 0x62, 0x8e, 0x2, 0xe9, 0x6b, 0x4f, 0x40, 0xf5, 0x85, 0x89, 0x4d, 0xae, 0x54, 0x7a, 0x50, 0x95, 0x1b, 0xf2, 0x16, 0xb7, 0xa8, 0x39, 0x1d, 0x9c, 0x7e, 0x5b, 0x26, 0xf8, 0xf9, 0xd, 0x3d, 0x47, 0x16, 0x9, 0x4d, 0xc6, 0xa1, 0xed, 0xae, 0x11}, + }, + // 123P + { + x: fp384{0x80, 0xb, 0x4c, 0xc, 0x48, 0x98, 0x11, 0x15, 0xfe, 0x18, 0x10, 0x2a, 0x4a, 0x7d, 0xb0, 0x46, 0x7b, 0x90, 0x80, 0xea, 0xeb, 0xc3, 0xa9, 0x14, 0x5, 0x44, 0x95, 0x42, 0xee, 0x5, 0x3d, 0x4b, 0xd2, 0x18, 0x4, 0x55, 0x78, 0xfd, 0xd6, 0xd4, 0xa6, 0x82, 0xdc, 0x21, 0x63, 0x4f, 0x4a, 0x8e}, + y: fp384{0xd9, 0xb9, 0x78, 0xa1, 0xf7, 0xd7, 0xe4, 0x1b, 0x9f, 0x8c, 0x78, 0x70, 0x4, 0xba, 0xc6, 0x83, 0xe8, 0xf7, 0x30, 0x9f, 0x3e, 0xaf, 0x82, 0x5a, 0x7b, 0x44, 0x8f, 0x49, 0xf, 0xab, 0x86, 0x8a, 0x33, 0xcf, 0x5c, 0xc2, 0xec, 0xbc, 0xba, 0x3, 0xdd, 0x8a, 0x79, 0x1a, 0xed, 0x62, 0xc4, 0x74}, + }, + // 125P + { + x: fp384{0xbb, 0x44, 0xfb, 0x3c, 0xbc, 0xb8, 0x12, 0x96, 0xda, 0x6a, 0x9d, 0x71, 0x77, 0x56, 0xf2, 0x70, 0xe2, 0x14, 0xf6, 0x46, 0xaa, 0x65, 0xea, 0x50, 0x6d, 0x35, 0x50, 0x34, 0xcf, 0xa8, 0x36, 0x94, 0xac, 0x3, 0x67, 0x3, 0xad, 0xeb, 0xd6, 0x7a, 0xae, 0x48, 0xcf, 0x45, 0xb2, 0xda, 0xb2, 0x3}, + y: fp384{0x1e, 0x6, 0x17, 0x41, 0x2a, 0x3d, 0x95, 0x21, 0xa4, 0x55, 0x4f, 0xed, 0x30, 0xb7, 0x3f, 0xdf, 0x8e, 0xab, 0x19, 0xe1, 0x41, 0x36, 0xf5, 0xec, 0xaa, 0x87, 0x91, 0x21, 0xbc, 0x41, 0x1f, 0x55, 0x2, 0x58, 0x9, 0xb0, 0x4b, 0xa7, 0xd5, 0x7c, 0xcb, 0x5c, 0xf3, 0x72, 0xf5, 0xbf, 0x33, 0x89}, + }, + // 127P + { + x: fp384{0xec, 0x1, 0xa1, 0xec, 0x46, 0x32, 0x75, 0xf7, 0xaf, 0x4, 0x96, 0x56, 0x4c, 0xfa, 0xac, 0x2a, 0x79, 0x62, 0x2c, 0x52, 0x34, 0x8f, 0xf2, 0xee, 0xf, 0x1e, 0x23, 0x74, 0x38, 0xe6, 0xfd, 0x96, 0x9d, 0xf0, 0xe0, 0xd6, 0x1b, 0xb1, 0x2b, 0xa9, 0xb4, 0x5d, 0x39, 0xf, 0x74, 0x4e, 0xe3, 0xbb}, + y: fp384{0xf9, 0x3c, 0x94, 0xbf, 0xdd, 0x59, 0x6e, 0xaa, 0xaa, 0xd5, 0x8a, 0x1, 0xbe, 0xbd, 0x98, 0x56, 0x19, 0xc5, 0x67, 0xa4, 0x44, 0x2a, 0xd2, 0x88, 0xe, 0xb, 0x18, 0xad, 0x39, 0xe3, 0x29, 0x9e, 0x94, 0x2f, 0x7b, 0x36, 0x2e, 0x83, 0xd6, 0xf3, 0x69, 0x80, 0x94, 0xe3, 0x61, 0x2a, 0xe9, 0xc7}, + }, +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/aead.go b/src/vendor/github.com/cloudflare/circl/hpke/aead.go new file mode 100644 index 00000000000..baf147bb4fa --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/aead.go @@ -0,0 +1,103 @@ +package hpke + +import ( + "crypto/cipher" + "fmt" +) + +type encdecContext struct { + // Serialized parameters + suite Suite + sharedSecret []byte + secret []byte + keyScheduleContext []byte + exporterSecret []byte + key []byte + baseNonce []byte + sequenceNumber []byte + + // Operational parameters + cipher.AEAD + nonce []byte +} + +type ( + sealContext struct{ *encdecContext } + openContext struct{ *encdecContext } +) + +// Export takes a context string exporterContext and a desired length (in +// bytes), and produces a secret derived from the internal exporter secret +// using the corresponding KDF Expand function. It panics if length is +// greater than 255*N bytes, where N is the size (in bytes) of the KDF's +// output. +func (c *encdecContext) Export(exporterContext []byte, length uint) []byte { + maxLength := uint(255 * c.suite.kdfID.ExtractSize()) + if length > maxLength { + panic(fmt.Errorf("output length must be lesser than %v bytes", maxLength)) + } + return c.suite.labeledExpand(c.exporterSecret, []byte("sec"), + exporterContext, uint16(length)) +} + +func (c *encdecContext) Suite() Suite { + return c.suite +} + +func (c *encdecContext) calcNonce() []byte { + for i := range c.baseNonce { + c.nonce[i] = c.baseNonce[i] ^ c.sequenceNumber[i] + } + return c.nonce +} + +func (c *encdecContext) increment() error { + // tests whether the sequence number is all-ones, which prevents an + // overflow after the increment. + allOnes := byte(0xFF) + for i := range c.sequenceNumber { + allOnes &= c.sequenceNumber[i] + } + if allOnes == byte(0xFF) { + return ErrAEADSeqOverflows + } + + // performs an increment by 1 and verifies whether the sequence overflows. + carry := uint(1) + for i := len(c.sequenceNumber) - 1; i >= 0; i-- { + sum := uint(c.sequenceNumber[i]) + carry + carry = sum >> 8 + c.sequenceNumber[i] = byte(sum & 0xFF) + } + if carry != 0 { + return ErrAEADSeqOverflows + } + return nil +} + +func (c *sealContext) Seal(pt, aad []byte) ([]byte, error) { + ct := c.AEAD.Seal(nil, c.calcNonce(), pt, aad) + err := c.increment() + if err != nil { + for i := range ct { + ct[i] = 0 + } + return nil, err + } + return ct, nil +} + +func (c *openContext) Open(ct, aad []byte) ([]byte, error) { + pt, err := c.AEAD.Open(nil, c.calcNonce(), ct, aad) + if err != nil { + return nil, err + } + err = c.increment() + if err != nil { + for i := range pt { + pt[i] = 0 + } + return nil, err + } + return pt, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/algs.go b/src/vendor/github.com/cloudflare/circl/hpke/algs.go new file mode 100644 index 00000000000..a9fbc661232 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/algs.go @@ -0,0 +1,278 @@ +package hpke + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/elliptic" + _ "crypto/sha256" // Linking sha256. + _ "crypto/sha512" // Linking sha512. + "fmt" + "hash" + "io" + + "github.com/cloudflare/circl/dh/x25519" + "github.com/cloudflare/circl/dh/x448" + "github.com/cloudflare/circl/ecc/p384" + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/kem/kyber/kyber768" + "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/hkdf" +) + +type KEM uint16 + +//nolint:golint,stylecheck +const ( + // KEM_P256_HKDF_SHA256 is a KEM using P256 curve and HKDF with SHA-256. + KEM_P256_HKDF_SHA256 KEM = 0x10 + // KEM_P384_HKDF_SHA384 is a KEM using P384 curve and HKDF with SHA-384. + KEM_P384_HKDF_SHA384 KEM = 0x11 + // KEM_P521_HKDF_SHA512 is a KEM using P521 curve and HKDF with SHA-512. + KEM_P521_HKDF_SHA512 KEM = 0x12 + // KEM_X25519_HKDF_SHA256 is a KEM using X25519 Diffie-Hellman function + // and HKDF with SHA-256. + KEM_X25519_HKDF_SHA256 KEM = 0x20 + // KEM_X448_HKDF_SHA512 is a KEM using X448 Diffie-Hellman function and + // HKDF with SHA-512. + KEM_X448_HKDF_SHA512 KEM = 0x21 + // KEM_X25519_KYBER768_DRAFT00 is a hybrid KEM built on DHKEM(X25519, HKDF-SHA256) + // and Kyber768Draft00 + KEM_X25519_KYBER768_DRAFT00 KEM = 0x30 +) + +// IsValid returns true if the KEM identifier is supported by the HPKE package. +func (k KEM) IsValid() bool { + switch k { + case KEM_P256_HKDF_SHA256, + KEM_P384_HKDF_SHA384, + KEM_P521_HKDF_SHA512, + KEM_X25519_HKDF_SHA256, + KEM_X448_HKDF_SHA512, + KEM_X25519_KYBER768_DRAFT00: + return true + default: + return false + } +} + +// Scheme returns an instance of a KEM that supports authentication. Panics if +// the KEM identifier is invalid. +func (k KEM) Scheme() kem.AuthScheme { + switch k { + case KEM_P256_HKDF_SHA256: + return dhkemp256hkdfsha256 + case KEM_P384_HKDF_SHA384: + return dhkemp384hkdfsha384 + case KEM_P521_HKDF_SHA512: + return dhkemp521hkdfsha512 + case KEM_X25519_HKDF_SHA256: + return dhkemx25519hkdfsha256 + case KEM_X448_HKDF_SHA512: + return dhkemx448hkdfsha512 + case KEM_X25519_KYBER768_DRAFT00: + return hybridkemX25519Kyber768 + default: + panic(ErrInvalidKEM) + } +} + +type KDF uint16 + +//nolint:golint,stylecheck +const ( + // KDF_HKDF_SHA256 is a KDF using HKDF with SHA-256. + KDF_HKDF_SHA256 KDF = 0x01 + // KDF_HKDF_SHA384 is a KDF using HKDF with SHA-384. + KDF_HKDF_SHA384 KDF = 0x02 + // KDF_HKDF_SHA512 is a KDF using HKDF with SHA-512. + KDF_HKDF_SHA512 KDF = 0x03 +) + +func (k KDF) IsValid() bool { + switch k { + case KDF_HKDF_SHA256, + KDF_HKDF_SHA384, + KDF_HKDF_SHA512: + return true + default: + return false + } +} + +// ExtractSize returns the size (in bytes) of the pseudorandom key produced +// by KDF.Extract. +func (k KDF) ExtractSize() int { + switch k { + case KDF_HKDF_SHA256: + return crypto.SHA256.Size() + case KDF_HKDF_SHA384: + return crypto.SHA384.Size() + case KDF_HKDF_SHA512: + return crypto.SHA512.Size() + default: + panic(ErrInvalidKDF) + } +} + +// Extract derives a pseudorandom key from a high-entropy, secret input and a +// salt. The size of the output is determined by KDF.ExtractSize. +func (k KDF) Extract(secret, salt []byte) (pseudorandomKey []byte) { + return hkdf.Extract(k.hash(), secret, salt) +} + +// Expand derives a variable length pseudorandom string from a pseudorandom key +// and an information string. Panics if the pseudorandom key is less +// than N bytes, or if the output length is greater than 255*N bytes, +// where N is the size returned by KDF.Extract function. +func (k KDF) Expand(pseudorandomKey, info []byte, outputLen uint) []byte { + extractSize := k.ExtractSize() + if len(pseudorandomKey) < extractSize { + panic(fmt.Errorf("pseudorandom key must be %v bytes", extractSize)) + } + maxLength := uint(255 * extractSize) + if outputLen > maxLength { + panic(fmt.Errorf("output length must be less than %v bytes", maxLength)) + } + output := make([]byte, outputLen) + rd := hkdf.Expand(k.hash(), pseudorandomKey[:extractSize], info) + _, err := io.ReadFull(rd, output) + if err != nil { + panic(err) + } + return output +} + +func (k KDF) hash() func() hash.Hash { + switch k { + case KDF_HKDF_SHA256: + return crypto.SHA256.New + case KDF_HKDF_SHA384: + return crypto.SHA384.New + case KDF_HKDF_SHA512: + return crypto.SHA512.New + default: + panic(ErrInvalidKDF) + } +} + +type AEAD uint16 + +//nolint:golint,stylecheck +const ( + // AEAD_AES128GCM is AES-128 block cipher in Galois Counter Mode (GCM). + AEAD_AES128GCM AEAD = 0x01 + // AEAD_AES256GCM is AES-256 block cipher in Galois Counter Mode (GCM). + AEAD_AES256GCM AEAD = 0x02 + // AEAD_ChaCha20Poly1305 is ChaCha20 stream cipher and Poly1305 MAC. + AEAD_ChaCha20Poly1305 AEAD = 0x03 +) + +// New instantiates an AEAD cipher from the identifier, returns an error if the +// identifier is not known. +func (a AEAD) New(key []byte) (cipher.AEAD, error) { + switch a { + case AEAD_AES128GCM, AEAD_AES256GCM: + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + return cipher.NewGCM(block) + case AEAD_ChaCha20Poly1305: + return chacha20poly1305.New(key) + default: + panic(ErrInvalidAEAD) + } +} + +func (a AEAD) IsValid() bool { + switch a { + case AEAD_AES128GCM, + AEAD_AES256GCM, + AEAD_ChaCha20Poly1305: + return true + default: + return false + } +} + +// KeySize returns the size in bytes of the keys used by the AEAD cipher. +func (a AEAD) KeySize() uint { + switch a { + case AEAD_AES128GCM: + return 16 + case AEAD_AES256GCM: + return 32 + case AEAD_ChaCha20Poly1305: + return chacha20poly1305.KeySize + default: + panic(ErrInvalidAEAD) + } +} + +// NonceSize returns the size in bytes of the nonce used by the AEAD cipher. +func (a AEAD) NonceSize() uint { + switch a { + case AEAD_AES128GCM, + AEAD_AES256GCM, + AEAD_ChaCha20Poly1305: + return 12 + default: + panic(ErrInvalidAEAD) + } +} + +// CipherLen returns the length of a ciphertext corresponding to a message of +// length mLen. +func (a AEAD) CipherLen(mLen uint) uint { + switch a { + case AEAD_AES128GCM, AEAD_AES256GCM, AEAD_ChaCha20Poly1305: + return mLen + 16 + default: + panic(ErrInvalidAEAD) + } +} + +var ( + dhkemp256hkdfsha256, dhkemp384hkdfsha384, dhkemp521hkdfsha512 shortKEM + dhkemx25519hkdfsha256, dhkemx448hkdfsha512 xKEM + hybridkemX25519Kyber768 hybridKEM +) + +func init() { + dhkemp256hkdfsha256.Curve = elliptic.P256() + dhkemp256hkdfsha256.dhKemBase.id = KEM_P256_HKDF_SHA256 + dhkemp256hkdfsha256.dhKemBase.name = "HPKE_KEM_P256_HKDF_SHA256" + dhkemp256hkdfsha256.dhKemBase.Hash = crypto.SHA256 + dhkemp256hkdfsha256.dhKemBase.dhKEM = dhkemp256hkdfsha256 + + dhkemp384hkdfsha384.Curve = p384.P384() + dhkemp384hkdfsha384.dhKemBase.id = KEM_P384_HKDF_SHA384 + dhkemp384hkdfsha384.dhKemBase.name = "HPKE_KEM_P384_HKDF_SHA384" + dhkemp384hkdfsha384.dhKemBase.Hash = crypto.SHA384 + dhkemp384hkdfsha384.dhKemBase.dhKEM = dhkemp384hkdfsha384 + + dhkemp521hkdfsha512.Curve = elliptic.P521() + dhkemp521hkdfsha512.dhKemBase.id = KEM_P521_HKDF_SHA512 + dhkemp521hkdfsha512.dhKemBase.name = "HPKE_KEM_P521_HKDF_SHA512" + dhkemp521hkdfsha512.dhKemBase.Hash = crypto.SHA512 + dhkemp521hkdfsha512.dhKemBase.dhKEM = dhkemp521hkdfsha512 + + dhkemx25519hkdfsha256.size = x25519.Size + dhkemx25519hkdfsha256.dhKemBase.id = KEM_X25519_HKDF_SHA256 + dhkemx25519hkdfsha256.dhKemBase.name = "HPKE_KEM_X25519_HKDF_SHA256" + dhkemx25519hkdfsha256.dhKemBase.Hash = crypto.SHA256 + dhkemx25519hkdfsha256.dhKemBase.dhKEM = dhkemx25519hkdfsha256 + + dhkemx448hkdfsha512.size = x448.Size + dhkemx448hkdfsha512.dhKemBase.id = KEM_X448_HKDF_SHA512 + dhkemx448hkdfsha512.dhKemBase.name = "HPKE_KEM_X448_HKDF_SHA512" + dhkemx448hkdfsha512.dhKemBase.Hash = crypto.SHA512 + dhkemx448hkdfsha512.dhKemBase.dhKEM = dhkemx448hkdfsha512 + + hybridkemX25519Kyber768.kemBase.id = KEM_X25519_KYBER768_DRAFT00 + hybridkemX25519Kyber768.kemBase.name = "HPKE_KEM_X25519_KYBER768_HKDF_SHA256" + hybridkemX25519Kyber768.kemBase.Hash = crypto.SHA256 + hybridkemX25519Kyber768.kemA = dhkemx25519hkdfsha256 + hybridkemX25519Kyber768.kemB = kyber768.Scheme() +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/hpke.go b/src/vendor/github.com/cloudflare/circl/hpke/hpke.go new file mode 100644 index 00000000000..4075b285e17 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/hpke.go @@ -0,0 +1,271 @@ +// Package hpke implements the Hybrid Public Key Encryption (HPKE) standard +// specified by draft-irtf-cfrg-hpke-07. +// +// HPKE works for any combination of a public-key encapsulation mechanism +// (KEM), a key derivation function (KDF), and an authenticated encryption +// scheme with additional data (AEAD). +// +// Specification in +// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hpke +// +// BUG(cjpatton): This package does not implement the "Export-Only" mode of the +// HPKE context. In particular, it does not recognize the AEAD codepoint +// reserved for this purpose (0xFFFF). +package hpke + +import ( + "crypto/rand" + "encoding" + "errors" + "io" + + "github.com/cloudflare/circl/kem" +) + +const versionLabel = "HPKE-v1" + +// Context defines the capabilities of an HPKE context. +type Context interface { + encoding.BinaryMarshaler + // Export takes a context string exporterContext and a desired length (in + // bytes), and produces a secret derived from the internal exporter secret + // using the corresponding KDF Expand function. It panics if length is + // greater than 255*N bytes, where N is the size (in bytes) of the KDF's + // output. + Export(exporterContext []byte, length uint) []byte + // Suite returns the cipher suite corresponding to this context. + Suite() Suite +} + +// Sealer encrypts a plaintext using an AEAD encryption. +type Sealer interface { + Context + // Seal takes a plaintext and associated data to produce a ciphertext. + // The nonce is handled by the Sealer and incremented after each call. + Seal(pt, aad []byte) (ct []byte, err error) +} + +// Opener decrypts a ciphertext using an AEAD encryption. +type Opener interface { + Context + // Open takes a ciphertext and associated data to recover, if successful, + // the plaintext. The nonce is handled by the Opener and incremented after + // each call. + Open(ct, aad []byte) (pt []byte, err error) +} + +// modeID represents an HPKE variant. +type modeID = uint8 + +const ( + // modeBase to enable encryption to the holder of a given KEM private key. + modeBase modeID = 0x00 + // modePSK extends the base mode by allowing the Receiver to authenticate + // that the sender possessed a given pre-shared key (PSK). + modePSK modeID = 0x01 + // modeAuth extends the base mode by allowing the Receiver to authenticate + // that the sender possessed a given KEM private key. + modeAuth modeID = 0x02 + // modeAuthPSK provides a combination of the PSK and Auth modes. + modeAuthPSK modeID = 0x03 +) + +// Suite is an HPKE cipher suite consisting of a KEM, KDF, and AEAD algorithm. +type Suite struct { + kemID KEM + kdfID KDF + aeadID AEAD +} + +// NewSuite builds a Suite from a specified set of algorithms. Panics +// if an algorithm identifier is not valid. +func NewSuite(kemID KEM, kdfID KDF, aeadID AEAD) Suite { + s := Suite{kemID, kdfID, aeadID} + if !s.isValid() { + panic(ErrInvalidHPKESuite) + } + return s +} + +type state struct { + Suite + modeID modeID + skS kem.PrivateKey + pkS kem.PublicKey + psk []byte + pskID []byte + info []byte +} + +// Sender performs hybrid public-key encryption. +type Sender struct { + state + pkR kem.PublicKey +} + +// NewSender creates a Sender with knowledge of the receiver's public-key. +func (suite Suite) NewSender(pkR kem.PublicKey, info []byte) (*Sender, error) { + return &Sender{ + state: state{Suite: suite, info: info}, + pkR: pkR, + }, nil +} + +// Setup generates a new HPKE context used for Base Mode encryption. +// Returns the Sealer and corresponding encapsulated key. +func (s *Sender) Setup(rnd io.Reader) (enc []byte, seal Sealer, err error) { + s.modeID = modeBase + return s.allSetup(rnd) +} + +// SetupAuth generates a new HPKE context used for Auth Mode encryption. +// Returns the Sealer and corresponding encapsulated key. +func (s *Sender) SetupAuth(rnd io.Reader, skS kem.PrivateKey) ( + enc []byte, seal Sealer, err error, +) { + s.modeID = modeAuth + s.state.skS = skS + return s.allSetup(rnd) +} + +// SetupPSK generates a new HPKE context used for PSK Mode encryption. +// Returns the Sealer and corresponding encapsulated key. +func (s *Sender) SetupPSK(rnd io.Reader, psk, pskID []byte) ( + enc []byte, seal Sealer, err error, +) { + s.modeID = modePSK + s.state.psk = psk + s.state.pskID = pskID + return s.allSetup(rnd) +} + +// SetupAuthPSK generates a new HPKE context used for Auth-PSK Mode encryption. +// Returns the Sealer and corresponding encapsulated key. +func (s *Sender) SetupAuthPSK(rnd io.Reader, skS kem.PrivateKey, psk, pskID []byte) ( + enc []byte, seal Sealer, err error, +) { + s.modeID = modeAuthPSK + s.state.skS = skS + s.state.psk = psk + s.state.pskID = pskID + return s.allSetup(rnd) +} + +// Receiver performs hybrid public-key decryption. +type Receiver struct { + state + skR kem.PrivateKey + enc []byte +} + +// NewReceiver creates a Receiver with knowledge of a private key. +func (suite Suite) NewReceiver(skR kem.PrivateKey, info []byte) ( + *Receiver, error, +) { + return &Receiver{state: state{Suite: suite, info: info}, skR: skR}, nil +} + +// Setup generates a new HPKE context used for Base Mode encryption. +// Setup takes an encapsulated key and returns an Opener. +func (r *Receiver) Setup(enc []byte) (Opener, error) { + r.modeID = modeBase + r.enc = enc + return r.allSetup() +} + +// SetupAuth generates a new HPKE context used for Auth Mode encryption. +// SetupAuth takes an encapsulated key and a public key, and returns an Opener. +func (r *Receiver) SetupAuth(enc []byte, pkS kem.PublicKey) (Opener, error) { + r.modeID = modeAuth + r.enc = enc + r.state.pkS = pkS + return r.allSetup() +} + +// SetupPSK generates a new HPKE context used for PSK Mode encryption. +// SetupPSK takes an encapsulated key, and a pre-shared key; and returns an +// Opener. +func (r *Receiver) SetupPSK(enc, psk, pskID []byte) (Opener, error) { + r.modeID = modePSK + r.enc = enc + r.state.psk = psk + r.state.pskID = pskID + return r.allSetup() +} + +// SetupAuthPSK generates a new HPKE context used for Auth-PSK Mode encryption. +// SetupAuthPSK takes an encapsulated key, a public key, and a pre-shared key; +// and returns an Opener. +func (r *Receiver) SetupAuthPSK( + enc, psk, pskID []byte, pkS kem.PublicKey, +) (Opener, error) { + r.modeID = modeAuthPSK + r.enc = enc + r.state.psk = psk + r.state.pskID = pskID + r.state.pkS = pkS + return r.allSetup() +} + +func (s *Sender) allSetup(rnd io.Reader) ([]byte, Sealer, error) { + scheme := s.kemID.Scheme() + + if rnd == nil { + rnd = rand.Reader + } + seed := make([]byte, scheme.EncapsulationSeedSize()) + _, err := io.ReadFull(rnd, seed) + if err != nil { + return nil, nil, err + } + + var enc, ss []byte + switch s.modeID { + case modeBase, modePSK: + enc, ss, err = scheme.EncapsulateDeterministically(s.pkR, seed) + case modeAuth, modeAuthPSK: + enc, ss, err = scheme.AuthEncapsulateDeterministically(s.pkR, s.skS, seed) + } + if err != nil { + return nil, nil, err + } + + ctx, err := s.keySchedule(ss, s.info, s.psk, s.pskID) + if err != nil { + return nil, nil, err + } + + return enc, &sealContext{ctx}, nil +} + +func (r *Receiver) allSetup() (Opener, error) { + var err error + var ss []byte + scheme := r.kemID.Scheme() + switch r.modeID { + case modeBase, modePSK: + ss, err = scheme.Decapsulate(r.skR, r.enc) + case modeAuth, modeAuthPSK: + ss, err = scheme.AuthDecapsulate(r.skR, r.enc, r.pkS) + } + if err != nil { + return nil, err + } + + ctx, err := r.keySchedule(ss, r.info, r.psk, r.pskID) + if err != nil { + return nil, err + } + return &openContext{ctx}, nil +} + +var ( + ErrInvalidHPKESuite = errors.New("hpke: invalid HPKE suite") + ErrInvalidKDF = errors.New("hpke: invalid KDF identifier") + ErrInvalidKEM = errors.New("hpke: invalid KEM identifier") + ErrInvalidAEAD = errors.New("hpke: invalid AEAD identifier") + ErrInvalidKEMPublicKey = errors.New("hpke: invalid KEM public key") + ErrInvalidKEMPrivateKey = errors.New("hpke: invalid KEM private key") + ErrInvalidKEMSharedSecret = errors.New("hpke: invalid KEM shared secret") + ErrAEADSeqOverflows = errors.New("hpke: AEAD sequence number overflows") +) diff --git a/src/vendor/github.com/cloudflare/circl/hpke/hybridkem.go b/src/vendor/github.com/cloudflare/circl/hpke/hybridkem.go new file mode 100644 index 00000000000..74e1ea6f1f3 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/hybridkem.go @@ -0,0 +1,232 @@ +package hpke + +// This file implements a hybrid KEM for HPKE using a simple concatenation +// combiner. +// +// WARNING It is not safe to combine arbitrary KEMs using this combiner. +// See the draft specification for more details: +// https://bwesterb.github.io/draft-westerbaan-cfrg-hpke-xyber768d00/draft-westerbaan-cfrg-hpke-xyber768d00.html#name-security-considerations + +import ( + "crypto/rand" + + "github.com/cloudflare/circl/kem" +) + +type hybridKEM struct { + kemBase + kemA kem.Scheme + kemB kem.Scheme +} + +func (h hybridKEM) PrivateKeySize() int { return h.kemA.PrivateKeySize() + h.kemB.PrivateKeySize() } +func (h hybridKEM) SeedSize() int { return 32 } +func (h hybridKEM) CiphertextSize() int { return h.kemA.CiphertextSize() + h.kemB.CiphertextSize() } +func (h hybridKEM) PublicKeySize() int { return h.kemA.PublicKeySize() + h.kemB.PublicKeySize() } +func (h hybridKEM) EncapsulationSeedSize() int { + return h.kemA.EncapsulationSeedSize() + h.kemB.EncapsulationSeedSize() +} +func (h hybridKEM) SharedKeySize() int { return h.kemA.SharedKeySize() + h.kemB.SharedKeySize() } +func (h hybridKEM) Name() string { return h.name } + +func (h hybridKEM) AuthDecapsulate(skR kem.PrivateKey, + ct []byte, + pkS kem.PublicKey, +) ([]byte, error) { + panic("AuthDecapsulate is not supported for this KEM") +} + +func (h hybridKEM) AuthEncapsulate(pkr kem.PublicKey, sks kem.PrivateKey) ( + ct []byte, ss []byte, err error, +) { + panic("AuthEncapsulate is not supported for this KEM") +} + +func (h hybridKEM) AuthEncapsulateDeterministically(pkr kem.PublicKey, sks kem.PrivateKey, seed []byte) (ct, ss []byte, err error) { + panic("AuthEncapsulateDeterministically is not supported for this KEM") +} + +func (h hybridKEM) Encapsulate(pkr kem.PublicKey) ( + ct []byte, ss []byte, err error, +) { + panic("Encapsulate is not implemented") +} + +func (h hybridKEM) Decapsulate(skr kem.PrivateKey, ct []byte) ([]byte, error) { + hybridSk := skr.(*hybridKEMPrivKey) + ssA, err := h.kemA.Decapsulate(hybridSk.privA, ct[0:h.kemA.CiphertextSize()]) + if err != nil { + return nil, err + } + ssB, err := h.kemB.Decapsulate(hybridSk.privB, ct[h.kemA.CiphertextSize():]) + if err != nil { + return nil, err + } + + ss := append(ssA, ssB...) + + return ss, nil +} + +func (h hybridKEM) EncapsulateDeterministically( + pkr kem.PublicKey, seed []byte, +) (ct, ss []byte, err error) { + hybridPk := pkr.(*hybridKEMPubKey) + encA, ssA, err := h.kemA.EncapsulateDeterministically(hybridPk.pubA, seed[0:h.kemA.EncapsulationSeedSize()]) + if err != nil { + return nil, nil, err + } + encB, ssB, err := h.kemB.EncapsulateDeterministically(hybridPk.pubB, seed[h.kemA.EncapsulationSeedSize():]) + if err != nil { + return nil, nil, err + } + + ct = append(encA, encB...) + ss = append(ssA, ssB...) + + return ct, ss, nil +} + +type hybridKEMPrivKey struct { + scheme kem.Scheme + privA kem.PrivateKey + privB kem.PrivateKey +} + +func (k *hybridKEMPrivKey) Scheme() kem.Scheme { + return k.scheme +} + +func (k *hybridKEMPrivKey) MarshalBinary() ([]byte, error) { + skA, err := k.privA.MarshalBinary() + if err != nil { + return nil, err + } + skB, err := k.privB.MarshalBinary() + if err != nil { + return nil, err + } + return append(skA, skB...), nil +} + +func (k *hybridKEMPrivKey) Equal(sk kem.PrivateKey) bool { + k1, ok := sk.(*hybridKEMPrivKey) + return ok && + k.privA.Equal(k1.privA) && + k.privB.Equal(k1.privB) +} + +func (k *hybridKEMPrivKey) Public() kem.PublicKey { + return &hybridKEMPubKey{ + scheme: k.scheme, + pubA: k.privA.Public(), + pubB: k.privB.Public(), + } +} + +type hybridKEMPubKey struct { + scheme kem.Scheme + pubA kem.PublicKey + pubB kem.PublicKey +} + +func (k *hybridKEMPubKey) Scheme() kem.Scheme { + return k.scheme +} + +func (k hybridKEMPubKey) MarshalBinary() ([]byte, error) { + pkA, err := k.pubA.MarshalBinary() + if err != nil { + return nil, err + } + pkB, err := k.pubB.MarshalBinary() + if err != nil { + return nil, err + } + return append(pkA, pkB...), nil +} + +func (k *hybridKEMPubKey) Equal(pk kem.PublicKey) bool { + k1, ok := pk.(*hybridKEMPubKey) + return ok && + k.pubA.Equal(k1.pubA) && + k.pubB.Equal(k1.pubB) +} + +// Deterministically derives a keypair from a seed. If you're unsure, +// you're better off using GenerateKey(). +// +// Panics if seed is not of length SeedSize(). +func (h hybridKEM) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + // Implementation based on + // https://www.ietf.org/archive/id/draft-irtf-cfrg-hpke-07.html#name-derivekeypair + if len(seed) != h.SeedSize() { + panic(kem.ErrSeedSize) + } + + outputSeedSize := h.kemA.SeedSize() + h.kemB.SeedSize() + dkpPrk := h.labeledExtract([]byte(""), []byte("dkp_prk"), seed) + bytes := h.labeledExpand( + dkpPrk, + []byte("sk"), + nil, + uint16(outputSeedSize), + ) + seedA := bytes[0:h.kemA.SeedSize()] + seedB := bytes[h.kemA.SeedSize():] + pubA, privA := h.kemA.DeriveKeyPair(seedA) + pubB, privB := h.kemB.DeriveKeyPair(seedB) + + privKey := &hybridKEMPrivKey{ + privA: privA, + privB: privB, + } + pubKey := &hybridKEMPubKey{ + pubA: pubA, + pubB: pubB, + } + + return pubKey, privKey +} + +func (h hybridKEM) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + seed := make([]byte, h.SeedSize()) + _, err := rand.Read(seed) + if err != nil { + return nil, nil, err + } + pk, sk := h.DeriveKeyPair(seed) + return pk, sk, nil +} + +func (h hybridKEM) UnmarshalBinaryPrivateKey(data []byte) (kem.PrivateKey, error) { + skA, err := h.kemA.UnmarshalBinaryPrivateKey(data[0:h.kemA.PrivateKeySize()]) + if err != nil { + return nil, err + } + skB, err := h.kemB.UnmarshalBinaryPrivateKey(data[h.kemA.PrivateKeySize():]) + if err != nil { + return nil, err + } + + return &hybridKEMPrivKey{ + privA: skA, + privB: skB, + }, nil +} + +func (h hybridKEM) UnmarshalBinaryPublicKey(data []byte) (kem.PublicKey, error) { + pkA, err := h.kemA.UnmarshalBinaryPublicKey(data[0:h.kemA.PublicKeySize()]) + if err != nil { + return nil, err + } + pkB, err := h.kemB.UnmarshalBinaryPublicKey(data[h.kemA.PublicKeySize():]) + if err != nil { + return nil, err + } + + return &hybridKEMPubKey{ + pubA: pkA, + pubB: pkB, + }, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/kembase.go b/src/vendor/github.com/cloudflare/circl/hpke/kembase.go new file mode 100644 index 00000000000..a15765f6df2 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/kembase.go @@ -0,0 +1,241 @@ +package hpke + +import ( + "crypto" + "crypto/rand" + "encoding/binary" + "io" + + "github.com/cloudflare/circl/kem" + "golang.org/x/crypto/hkdf" +) + +type dhKEM interface { + sizeDH() int + calcDH(dh []byte, sk kem.PrivateKey, pk kem.PublicKey) error + SeedSize() int + DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) + UnmarshalBinaryPrivateKey(data []byte) (kem.PrivateKey, error) + UnmarshalBinaryPublicKey(data []byte) (kem.PublicKey, error) +} + +type kemBase struct { + id KEM + name string + crypto.Hash +} + +type dhKemBase struct { + kemBase + dhKEM +} + +func (k kemBase) Name() string { return k.name } +func (k kemBase) SharedKeySize() int { return k.Hash.Size() } + +func (k kemBase) getSuiteID() (sid [5]byte) { + sid[0], sid[1], sid[2] = 'K', 'E', 'M' + binary.BigEndian.PutUint16(sid[3:5], uint16(k.id)) + return +} + +func (k kemBase) extractExpand(dh, kemCtx []byte) []byte { + eaePkr := k.labeledExtract([]byte(""), []byte("eae_prk"), dh) + return k.labeledExpand( + eaePkr, + []byte("shared_secret"), + kemCtx, + uint16(k.Size()), + ) +} + +func (k kemBase) labeledExtract(salt, label, info []byte) []byte { + suiteID := k.getSuiteID() + labeledIKM := append(append(append(append( + make([]byte, 0, len(versionLabel)+len(suiteID)+len(label)+len(info)), + versionLabel...), + suiteID[:]...), + label...), + info...) + return hkdf.Extract(k.New, labeledIKM, salt) +} + +func (k kemBase) labeledExpand(prk, label, info []byte, l uint16) []byte { + suiteID := k.getSuiteID() + labeledInfo := make( + []byte, + 2, + 2+len(versionLabel)+len(suiteID)+len(label)+len(info), + ) + binary.BigEndian.PutUint16(labeledInfo[0:2], l) + labeledInfo = append(append(append(append(labeledInfo, + versionLabel...), + suiteID[:]...), + label...), + info...) + b := make([]byte, l) + rd := hkdf.Expand(k.New, prk, labeledInfo) + if _, err := io.ReadFull(rd, b); err != nil { + panic(err) + } + return b +} + +func (k dhKemBase) AuthEncapsulate(pkr kem.PublicKey, sks kem.PrivateKey) ( + ct []byte, ss []byte, err error, +) { + seed := make([]byte, k.SeedSize()) + _, err = io.ReadFull(rand.Reader, seed) + if err != nil { + return nil, nil, err + } + + return k.authEncap(pkr, sks, seed) +} + +func (k dhKemBase) Encapsulate(pkr kem.PublicKey) ( + ct []byte, ss []byte, err error, +) { + seed := make([]byte, k.SeedSize()) + _, err = io.ReadFull(rand.Reader, seed) + if err != nil { + return nil, nil, err + } + + return k.encap(pkr, seed) +} + +func (k dhKemBase) AuthEncapsulateDeterministically( + pkr kem.PublicKey, sks kem.PrivateKey, seed []byte, +) (ct, ss []byte, err error) { + return k.authEncap(pkr, sks, seed) +} + +func (k dhKemBase) EncapsulateDeterministically( + pkr kem.PublicKey, seed []byte, +) (ct, ss []byte, err error) { + return k.encap(pkr, seed) +} + +func (k dhKemBase) encap( + pkR kem.PublicKey, + seed []byte, +) (ct []byte, ss []byte, err error) { + dh := make([]byte, k.sizeDH()) + enc, kemCtx, err := k.coreEncap(dh, pkR, seed) + if err != nil { + return nil, nil, err + } + ss = k.extractExpand(dh, kemCtx) + return enc, ss, nil +} + +func (k dhKemBase) authEncap( + pkR kem.PublicKey, + skS kem.PrivateKey, + seed []byte, +) (ct []byte, ss []byte, err error) { + dhLen := k.sizeDH() + dh := make([]byte, 2*dhLen) + enc, kemCtx, err := k.coreEncap(dh[:dhLen], pkR, seed) + if err != nil { + return nil, nil, err + } + + err = k.calcDH(dh[dhLen:], skS, pkR) + if err != nil { + return nil, nil, err + } + + pkS := skS.Public() + pkSm, err := pkS.MarshalBinary() + if err != nil { + return nil, nil, err + } + kemCtx = append(kemCtx, pkSm...) + + ss = k.extractExpand(dh, kemCtx) + return enc, ss, nil +} + +func (k dhKemBase) coreEncap( + dh []byte, + pkR kem.PublicKey, + seed []byte, +) (enc []byte, kemCtx []byte, err error) { + pkE, skE := k.DeriveKeyPair(seed) + err = k.calcDH(dh, skE, pkR) + if err != nil { + return nil, nil, err + } + + enc, err = pkE.MarshalBinary() + if err != nil { + return nil, nil, err + } + pkRm, err := pkR.MarshalBinary() + if err != nil { + return nil, nil, err + } + kemCtx = append(append([]byte{}, enc...), pkRm...) + + return enc, kemCtx, nil +} + +func (k dhKemBase) Decapsulate(skr kem.PrivateKey, ct []byte) ([]byte, error) { + dh := make([]byte, k.sizeDH()) + kemCtx, err := k.coreDecap(dh, skr, ct) + if err != nil { + return nil, err + } + return k.extractExpand(dh, kemCtx), nil +} + +func (k dhKemBase) AuthDecapsulate( + skR kem.PrivateKey, + ct []byte, + pkS kem.PublicKey, +) ([]byte, error) { + dhLen := k.sizeDH() + dh := make([]byte, 2*dhLen) + kemCtx, err := k.coreDecap(dh[:dhLen], skR, ct) + if err != nil { + return nil, err + } + + err = k.calcDH(dh[dhLen:], skR, pkS) + if err != nil { + return nil, err + } + + pkSm, err := pkS.MarshalBinary() + if err != nil { + return nil, err + } + kemCtx = append(kemCtx, pkSm...) + return k.extractExpand(dh, kemCtx), nil +} + +func (k dhKemBase) coreDecap( + dh []byte, + skR kem.PrivateKey, + ct []byte, +) ([]byte, error) { + pkE, err := k.UnmarshalBinaryPublicKey(ct) + if err != nil { + return nil, err + } + + err = k.calcDH(dh, skR, pkE) + if err != nil { + return nil, err + } + + pkR := skR.Public() + pkRm, err := pkR.MarshalBinary() + if err != nil { + return nil, err + } + + return append(append([]byte{}, ct...), pkRm...), nil +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/marshal.go b/src/vendor/github.com/cloudflare/circl/hpke/marshal.go new file mode 100644 index 00000000000..4ce02eedaac --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/marshal.go @@ -0,0 +1,151 @@ +package hpke + +import ( + "errors" + + "golang.org/x/crypto/cryptobyte" +) + +// marshal serializes an HPKE context. +func (c *encdecContext) marshal() ([]byte, error) { + var b cryptobyte.Builder + b.AddUint16(uint16(c.suite.kemID)) + b.AddUint16(uint16(c.suite.kdfID)) + b.AddUint16(uint16(c.suite.aeadID)) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(c.exporterSecret) + }) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(c.key) + }) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(c.baseNonce) + }) + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(c.sequenceNumber) + }) + return b.Bytes() +} + +// unmarshalContext parses an HPKE context. +func unmarshalContext(raw []byte) (*encdecContext, error) { + var ( + err error + t cryptobyte.String + ) + + c := new(encdecContext) + s := cryptobyte.String(raw) + if !s.ReadUint16((*uint16)(&c.suite.kemID)) || + !s.ReadUint16((*uint16)(&c.suite.kdfID)) || + !s.ReadUint16((*uint16)(&c.suite.aeadID)) || + !s.ReadUint8LengthPrefixed(&t) || + !t.ReadBytes(&c.exporterSecret, len(t)) || + !s.ReadUint8LengthPrefixed(&t) || + !t.ReadBytes(&c.key, len(t)) || + !s.ReadUint8LengthPrefixed(&t) || + !t.ReadBytes(&c.baseNonce, len(t)) || + !s.ReadUint8LengthPrefixed(&t) || + !t.ReadBytes(&c.sequenceNumber, len(t)) { + return nil, errors.New("failed to parse context") + } + + if !c.suite.isValid() { + return nil, ErrInvalidHPKESuite + } + + Nh := c.suite.kdfID.ExtractSize() + if len(c.exporterSecret) != Nh { + return nil, errors.New("invalid exporter secret length") + } + + Nk := int(c.suite.aeadID.KeySize()) + if len(c.key) != Nk { + return nil, errors.New("invalid key length") + } + + c.AEAD, err = c.suite.aeadID.New(c.key) + if err != nil { + return nil, err + } + + Nn := int(c.suite.aeadID.NonceSize()) + if len(c.baseNonce) != Nn { + return nil, errors.New("invalid base nonce length") + } + if len(c.sequenceNumber) != Nn { + return nil, errors.New("invalid sequence number length") + } + c.nonce = make([]byte, Nn) + + return c, nil +} + +// MarshalBinary serializes an HPKE sealer according to the format specified +// below. (Expressed in TLS syntax.) Note that this format is not defined by +// the HPKE standard. +// +// enum { sealer(0), opener(1) } HpkeRole; +// +// struct { +// HpkeKemId kem_id; // draft-irtf-cfrg-hpke-07 +// HpkeKdfId kdf_id; // draft-irtf-cfrg-hpke-07 +// HpkeAeadId aead_id; // draft-irtf-cfrg-hpke-07 +// opaque exporter_secret<0..255>; +// opaque key<0..255>; +// opaque base_nonce<0..255>; +// opaque seq<0..255>; +// } HpkeContext; +// +// struct { +// HpkeRole role = 0; // sealer +// HpkeContext context; +// } HpkeSealer; +func (c *sealContext) MarshalBinary() ([]byte, error) { + rawContext, err := c.encdecContext.marshal() + if err != nil { + return nil, err + } + return append([]byte{0}, rawContext...), nil +} + +// UnmarshalSealer parses an HPKE sealer. +func UnmarshalSealer(raw []byte) (Sealer, error) { + if raw[0] != 0 { + return nil, errors.New("incorrect role") + } + context, err := unmarshalContext(raw[1:]) + if err != nil { + return nil, err + } + return &sealContext{context}, nil +} + +// MarshalBinary serializes an HPKE opener according to the format specified +// below. (Expressed in TLS syntax.) Note that this format is not defined by the +// HPKE standard. +// +// struct { +// HpkeRole role = 1; // opener +// HpkeContext context; +// } HpkeOpener; +func (c *openContext) MarshalBinary() ([]byte, error) { + rawContext, err := c.encdecContext.marshal() + if err != nil { + return nil, err + } + return append([]byte{1}, rawContext...), nil +} + +// UnmarshalOpener parses a serialized HPKE opener and returns the corresponding +// Opener. +func UnmarshalOpener(raw []byte) (Opener, error) { + if raw[0] != 1 { + return nil, errors.New("incorrect role") + } + context, err := unmarshalContext(raw[1:]) + if err != nil { + return nil, err + } + return &openContext{context}, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/shortkem.go b/src/vendor/github.com/cloudflare/circl/hpke/shortkem.go new file mode 100644 index 00000000000..e5c55e991be --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/shortkem.go @@ -0,0 +1,170 @@ +package hpke + +import ( + "crypto/elliptic" + "crypto/rand" + "crypto/subtle" + "fmt" + "math/big" + + "github.com/cloudflare/circl/kem" +) + +type shortKEM struct { + dhKemBase + elliptic.Curve +} + +func (s shortKEM) PrivateKeySize() int { return s.byteSize() } +func (s shortKEM) SeedSize() int { return s.byteSize() } +func (s shortKEM) CiphertextSize() int { return 1 + 2*s.byteSize() } +func (s shortKEM) PublicKeySize() int { return 1 + 2*s.byteSize() } +func (s shortKEM) EncapsulationSeedSize() int { return s.byteSize() } + +func (s shortKEM) byteSize() int { return (s.Params().BitSize + 7) / 8 } + +func (s shortKEM) sizeDH() int { return s.byteSize() } +func (s shortKEM) calcDH(dh []byte, sk kem.PrivateKey, pk kem.PublicKey) error { + PK := pk.(*shortKEMPubKey) + SK := sk.(*shortKEMPrivKey) + l := len(dh) + x, _ := s.ScalarMult(PK.x, PK.y, SK.priv) // only x-coordinate is used. + if x.Sign() == 0 { + return ErrInvalidKEMSharedSecret + } + b := x.Bytes() + copy(dh[l-len(b):l], b) + return nil +} + +// Deterministically derives a keypair from a seed. If you're unsure, +// you're better off using GenerateKey(). +// +// Panics if seed is not of length SeedSize(). +func (s shortKEM) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + // Implementation based on + // https://www.ietf.org/archive/id/draft-irtf-cfrg-hpke-07.html#name-derivekeypair + if len(seed) != s.SeedSize() { + panic(kem.ErrSeedSize) + } + + bitmask := byte(0xFF) + if s.Params().BitSize == 521 { + bitmask = 0x01 + } + + dkpPrk := s.labeledExtract([]byte(""), []byte("dkp_prk"), seed) + var bytes []byte + ctr := 0 + for skBig := new(big.Int); skBig.Sign() == 0 || skBig.Cmp(s.Params().N) >= 0; ctr++ { + if ctr > 255 { + panic("derive key error") + } + bytes = s.labeledExpand( + dkpPrk, + []byte("candidate"), + []byte{byte(ctr)}, + uint16(s.byteSize()), + ) + bytes[0] &= bitmask + skBig.SetBytes(bytes) + } + l := s.PrivateKeySize() + sk := &shortKEMPrivKey{s, make([]byte, l), nil} + copy(sk.priv[l-len(bytes):], bytes) + return sk.Public(), sk +} + +func (s shortKEM) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + sk, x, y, err := elliptic.GenerateKey(s, rand.Reader) + pub := &shortKEMPubKey{s, x, y} + return pub, &shortKEMPrivKey{s, sk, pub}, err +} + +func (s shortKEM) UnmarshalBinaryPrivateKey(data []byte) (kem.PrivateKey, error) { + l := s.PrivateKeySize() + if len(data) < l { + return nil, ErrInvalidKEMPrivateKey + } + sk := &shortKEMPrivKey{s, make([]byte, l), nil} + copy(sk.priv[l-len(data):l], data[:l]) + if !sk.validate() { + return nil, ErrInvalidKEMPrivateKey + } + + return sk, nil +} + +func (s shortKEM) UnmarshalBinaryPublicKey(data []byte) (kem.PublicKey, error) { + x, y := elliptic.Unmarshal(s, data) + if x == nil { + return nil, ErrInvalidKEMPublicKey + } + key := &shortKEMPubKey{s, x, y} + if !key.validate() { + return nil, ErrInvalidKEMPublicKey + } + return key, nil +} + +type shortKEMPubKey struct { + scheme shortKEM + x, y *big.Int +} + +func (k *shortKEMPubKey) String() string { + return fmt.Sprintf("x: %v\ny: %v", k.x.Text(16), k.y.Text(16)) +} +func (k *shortKEMPubKey) Scheme() kem.Scheme { return k.scheme } +func (k *shortKEMPubKey) MarshalBinary() ([]byte, error) { + return elliptic.Marshal(k.scheme, k.x, k.y), nil +} + +func (k *shortKEMPubKey) Equal(pk kem.PublicKey) bool { + k1, ok := pk.(*shortKEMPubKey) + return ok && + k.scheme.Params().Name == k1.scheme.Params().Name && + k.x.Cmp(k1.x) == 0 && + k.y.Cmp(k1.y) == 0 +} + +func (k *shortKEMPubKey) validate() bool { + p := k.scheme.Params().P + notAtInfinity := k.x.Sign() > 0 && k.y.Sign() > 0 + lessThanP := k.x.Cmp(p) < 0 && k.y.Cmp(p) < 0 + onCurve := k.scheme.IsOnCurve(k.x, k.y) + return notAtInfinity && lessThanP && onCurve +} + +type shortKEMPrivKey struct { + scheme shortKEM + priv []byte + pub *shortKEMPubKey +} + +func (k *shortKEMPrivKey) String() string { return fmt.Sprintf("%x", k.priv) } +func (k *shortKEMPrivKey) Scheme() kem.Scheme { return k.scheme } +func (k *shortKEMPrivKey) MarshalBinary() ([]byte, error) { + return append(make([]byte, 0, k.scheme.PrivateKeySize()), k.priv...), nil +} + +func (k *shortKEMPrivKey) Equal(pk kem.PrivateKey) bool { + k1, ok := pk.(*shortKEMPrivKey) + return ok && + k.scheme.Params().Name == k1.scheme.Params().Name && + subtle.ConstantTimeCompare(k.priv, k1.priv) == 1 +} + +func (k *shortKEMPrivKey) Public() kem.PublicKey { + if k.pub == nil { + x, y := k.scheme.ScalarBaseMult(k.priv) + k.pub = &shortKEMPubKey{k.scheme, x, y} + } + return k.pub +} + +func (k *shortKEMPrivKey) validate() bool { + n := new(big.Int).SetBytes(k.priv) + order := k.scheme.Curve.Params().N + return len(k.priv) == k.scheme.PrivateKeySize() && n.Cmp(order) < 0 +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/util.go b/src/vendor/github.com/cloudflare/circl/hpke/util.go new file mode 100644 index 00000000000..c9fed4fcf74 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/util.go @@ -0,0 +1,121 @@ +package hpke + +import ( + "encoding/binary" + "errors" + "fmt" +) + +func (st state) keySchedule(ss, info, psk, pskID []byte) (*encdecContext, error) { + if err := st.verifyPSKInputs(psk, pskID); err != nil { + return nil, err + } + + pskIDHash := st.labeledExtract(nil, []byte("psk_id_hash"), pskID) + infoHash := st.labeledExtract(nil, []byte("info_hash"), info) + keySchCtx := append(append( + []byte{st.modeID}, + pskIDHash...), + infoHash...) + + secret := st.labeledExtract(ss, []byte("secret"), psk) + + Nk := uint16(st.aeadID.KeySize()) + key := st.labeledExpand(secret, []byte("key"), keySchCtx, Nk) + + aead, err := st.aeadID.New(key) + if err != nil { + return nil, err + } + + Nn := uint16(aead.NonceSize()) + baseNonce := st.labeledExpand(secret, []byte("base_nonce"), keySchCtx, Nn) + exporterSecret := st.labeledExpand( + secret, + []byte("exp"), + keySchCtx, + uint16(st.kdfID.ExtractSize()), + ) + + return &encdecContext{ + st.Suite, + ss, + secret, + keySchCtx, + exporterSecret, + key, + baseNonce, + make([]byte, Nn), + aead, + make([]byte, Nn), + }, nil +} + +func (st state) verifyPSKInputs(psk, pskID []byte) error { + gotPSK := psk != nil + gotPSKID := pskID != nil + if gotPSK != gotPSKID { + return errors.New("inconsistent PSK inputs") + } + switch st.modeID { + case modeBase | modeAuth: + if gotPSK { + return errors.New("PSK input provided when not needed") + } + case modePSK | modeAuthPSK: + if !gotPSK { + return errors.New("missing required PSK input") + } + } + return nil +} + +// Params returns the codepoints for the algorithms comprising the suite. +func (suite Suite) Params() (KEM, KDF, AEAD) { + return suite.kemID, suite.kdfID, suite.aeadID +} + +func (suite Suite) String() string { + return fmt.Sprintf( + "kem_id: %v kdf_id: %v aead_id: %v", + suite.kemID, suite.kdfID, suite.aeadID, + ) +} + +func (suite Suite) getSuiteID() (id [10]byte) { + id[0], id[1], id[2], id[3] = 'H', 'P', 'K', 'E' + binary.BigEndian.PutUint16(id[4:6], uint16(suite.kemID)) + binary.BigEndian.PutUint16(id[6:8], uint16(suite.kdfID)) + binary.BigEndian.PutUint16(id[8:10], uint16(suite.aeadID)) + return +} + +func (suite Suite) isValid() bool { + return suite.kemID.IsValid() && + suite.kdfID.IsValid() && + suite.aeadID.IsValid() +} + +func (suite Suite) labeledExtract(salt, label, ikm []byte) []byte { + suiteID := suite.getSuiteID() + labeledIKM := append(append(append(append( + make([]byte, 0, len(versionLabel)+len(suiteID)+len(label)+len(ikm)), + versionLabel...), + suiteID[:]...), + label...), + ikm...) + return suite.kdfID.Extract(labeledIKM, salt) +} + +func (suite Suite) labeledExpand(prk, label, info []byte, l uint16) []byte { + suiteID := suite.getSuiteID() + labeledInfo := make([]byte, + 2, 2+len(versionLabel)+len(suiteID)+len(label)+len(info)) + binary.BigEndian.PutUint16(labeledInfo[0:2], l) + labeledInfo = append(append(append(append(labeledInfo, + versionLabel...), + suiteID[:]...), + label...), + info...) + return suite.kdfID.Expand(prk, labeledInfo, uint(l)) +} diff --git a/src/vendor/github.com/cloudflare/circl/hpke/xkem.go b/src/vendor/github.com/cloudflare/circl/hpke/xkem.go new file mode 100644 index 00000000000..f11ab6b374a --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/hpke/xkem.go @@ -0,0 +1,164 @@ +package hpke + +import ( + "bytes" + "crypto/rand" + "crypto/subtle" + "fmt" + "io" + + "github.com/cloudflare/circl/dh/x25519" + "github.com/cloudflare/circl/dh/x448" + "github.com/cloudflare/circl/kem" +) + +type xKEM struct { + dhKemBase + size int +} + +func (x xKEM) PrivateKeySize() int { return x.size } +func (x xKEM) SeedSize() int { return x.size } +func (x xKEM) CiphertextSize() int { return x.size } +func (x xKEM) PublicKeySize() int { return x.size } +func (x xKEM) EncapsulationSeedSize() int { return x.size } + +func (x xKEM) sizeDH() int { return x.size } +func (x xKEM) calcDH(dh []byte, sk kem.PrivateKey, pk kem.PublicKey) error { + PK := pk.(*xKEMPubKey) + SK := sk.(*xKEMPrivKey) + switch x.size { + case x25519.Size: + var ss, sKey, pKey x25519.Key + copy(sKey[:], SK.priv) + copy(pKey[:], PK.pub) + if !x25519.Shared(&ss, &sKey, &pKey) { + return ErrInvalidKEMSharedSecret + } + copy(dh, ss[:]) + case x448.Size: + var ss, sKey, pKey x448.Key + copy(sKey[:], SK.priv) + copy(pKey[:], PK.pub) + if !x448.Shared(&ss, &sKey, &pKey) { + return ErrInvalidKEMSharedSecret + } + copy(dh, ss[:]) + } + return nil +} + +// Deterministically derives a keypair from a seed. If you're unsure, +// you're better off using GenerateKey(). +// +// Panics if seed is not of length SeedSize(). +func (x xKEM) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + // Implementation based on + // https://www.ietf.org/archive/id/draft-irtf-cfrg-hpke-07.html#name-derivekeypair + if len(seed) != x.SeedSize() { + panic(kem.ErrSeedSize) + } + sk := &xKEMPrivKey{scheme: x, priv: make([]byte, x.size)} + dkpPrk := x.labeledExtract([]byte(""), []byte("dkp_prk"), seed) + bytes := x.labeledExpand( + dkpPrk, + []byte("sk"), + nil, + uint16(x.PrivateKeySize()), + ) + copy(sk.priv, bytes) + return sk.Public(), sk +} + +func (x xKEM) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + sk := &xKEMPrivKey{scheme: x, priv: make([]byte, x.PrivateKeySize())} + _, err := io.ReadFull(rand.Reader, sk.priv) + if err != nil { + return nil, nil, err + } + return sk.Public(), sk, nil +} + +func (x xKEM) UnmarshalBinaryPrivateKey(data []byte) (kem.PrivateKey, error) { + l := x.PrivateKeySize() + if len(data) < l { + return nil, ErrInvalidKEMPrivateKey + } + sk := &xKEMPrivKey{x, make([]byte, l), nil} + copy(sk.priv, data[:l]) + if !sk.validate() { + return nil, ErrInvalidKEMPrivateKey + } + return sk, nil +} + +func (x xKEM) UnmarshalBinaryPublicKey(data []byte) (kem.PublicKey, error) { + l := x.PublicKeySize() + if len(data) < l { + return nil, ErrInvalidKEMPublicKey + } + pk := &xKEMPubKey{x, make([]byte, l)} + copy(pk.pub, data[:l]) + if !pk.validate() { + return nil, ErrInvalidKEMPublicKey + } + return pk, nil +} + +type xKEMPubKey struct { + scheme xKEM + pub []byte +} + +func (k *xKEMPubKey) String() string { return fmt.Sprintf("%x", k.pub) } +func (k *xKEMPubKey) Scheme() kem.Scheme { return k.scheme } +func (k *xKEMPubKey) MarshalBinary() ([]byte, error) { + return append(make([]byte, 0, k.scheme.PublicKeySize()), k.pub...), nil +} + +func (k *xKEMPubKey) Equal(pk kem.PublicKey) bool { + k1, ok := pk.(*xKEMPubKey) + return ok && + k.scheme.id == k1.scheme.id && + bytes.Equal(k.pub, k1.pub) +} +func (k *xKEMPubKey) validate() bool { return len(k.pub) == k.scheme.PublicKeySize() } + +type xKEMPrivKey struct { + scheme xKEM + priv []byte + pub *xKEMPubKey +} + +func (k *xKEMPrivKey) String() string { return fmt.Sprintf("%x", k.priv) } +func (k *xKEMPrivKey) Scheme() kem.Scheme { return k.scheme } +func (k *xKEMPrivKey) MarshalBinary() ([]byte, error) { + return append(make([]byte, 0, k.scheme.PrivateKeySize()), k.priv...), nil +} + +func (k *xKEMPrivKey) Equal(pk kem.PrivateKey) bool { + k1, ok := pk.(*xKEMPrivKey) + return ok && + k.scheme.id == k1.scheme.id && + subtle.ConstantTimeCompare(k.priv, k1.priv) == 1 +} + +func (k *xKEMPrivKey) Public() kem.PublicKey { + if k.pub == nil { + k.pub = &xKEMPubKey{scheme: k.scheme, pub: make([]byte, k.scheme.size)} + switch k.scheme.size { + case x25519.Size: + var sk, pk x25519.Key + copy(sk[:], k.priv) + x25519.KeyGen(&pk, &sk) + copy(k.pub.pub, pk[:]) + case x448.Size: + var sk, pk x448.Key + copy(sk[:], k.priv) + x448.KeyGen(&pk, &sk) + copy(k.pub.pub, pk[:]) + } + } + return k.pub +} +func (k *xKEMPrivKey) validate() bool { return len(k.priv) == k.scheme.PrivateKeySize() } diff --git a/src/vendor/github.com/cloudflare/circl/internal/conv/conv.go b/src/vendor/github.com/cloudflare/circl/internal/conv/conv.go new file mode 100644 index 00000000000..649a8e931d6 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/conv/conv.go @@ -0,0 +1,140 @@ +package conv + +import ( + "encoding/binary" + "fmt" + "math/big" + "strings" +) + +// BytesLe2Hex returns an hexadecimal string of a number stored in a +// little-endian order slice x. +func BytesLe2Hex(x []byte) string { + b := &strings.Builder{} + b.Grow(2*len(x) + 2) + fmt.Fprint(b, "0x") + if len(x) == 0 { + fmt.Fprint(b, "00") + } + for i := len(x) - 1; i >= 0; i-- { + fmt.Fprintf(b, "%02x", x[i]) + } + return b.String() +} + +// BytesLe2BigInt converts a little-endian slice x into a big-endian +// math/big.Int. +func BytesLe2BigInt(x []byte) *big.Int { + n := len(x) + b := new(big.Int) + if len(x) > 0 { + y := make([]byte, n) + for i := 0; i < n; i++ { + y[n-1-i] = x[i] + } + b.SetBytes(y) + } + return b +} + +// BytesBe2Uint64Le converts a big-endian slice x to a little-endian slice of uint64. +func BytesBe2Uint64Le(x []byte) []uint64 { + l := len(x) + z := make([]uint64, (l+7)/8) + blocks := l / 8 + for i := 0; i < blocks; i++ { + z[i] = binary.BigEndian.Uint64(x[l-8*(i+1):]) + } + remBytes := l % 8 + for i := 0; i < remBytes; i++ { + z[blocks] |= uint64(x[l-1-8*blocks-i]) << uint(8*i) + } + return z +} + +// BigInt2BytesLe stores a positive big.Int number x into a little-endian slice z. +// The slice is modified if the bitlength of x <= 8*len(z) (padding with zeros). +// If x does not fit in the slice or is negative, z is not modified. +func BigInt2BytesLe(z []byte, x *big.Int) { + xLen := (x.BitLen() + 7) >> 3 + zLen := len(z) + if zLen >= xLen && x.Sign() >= 0 { + y := x.Bytes() + for i := 0; i < xLen; i++ { + z[i] = y[xLen-1-i] + } + for i := xLen; i < zLen; i++ { + z[i] = 0 + } + } +} + +// Uint64Le2BigInt converts a little-endian slice x into a big number. +func Uint64Le2BigInt(x []uint64) *big.Int { + n := len(x) + b := new(big.Int) + var bi big.Int + for i := n - 1; i >= 0; i-- { + bi.SetUint64(x[i]) + b.Lsh(b, 64) + b.Add(b, &bi) + } + return b +} + +// Uint64Le2BytesLe converts a little-endian slice x to a little-endian slice of bytes. +func Uint64Le2BytesLe(x []uint64) []byte { + b := make([]byte, 8*len(x)) + n := len(x) + for i := 0; i < n; i++ { + binary.LittleEndian.PutUint64(b[i*8:], x[i]) + } + return b +} + +// Uint64Le2BytesBe converts a little-endian slice x to a big-endian slice of bytes. +func Uint64Le2BytesBe(x []uint64) []byte { + b := make([]byte, 8*len(x)) + n := len(x) + for i := 0; i < n; i++ { + binary.BigEndian.PutUint64(b[i*8:], x[n-1-i]) + } + return b +} + +// Uint64Le2Hex returns an hexadecimal string of a number stored in a +// little-endian order slice x. +func Uint64Le2Hex(x []uint64) string { + b := new(strings.Builder) + b.Grow(16*len(x) + 2) + fmt.Fprint(b, "0x") + if len(x) == 0 { + fmt.Fprint(b, "00") + } + for i := len(x) - 1; i >= 0; i-- { + fmt.Fprintf(b, "%016x", x[i]) + } + return b.String() +} + +// BigInt2Uint64Le stores a positive big.Int number x into a little-endian slice z. +// The slice is modified if the bitlength of x <= 8*len(z) (padding with zeros). +// If x does not fit in the slice or is negative, z is not modified. +func BigInt2Uint64Le(z []uint64, x *big.Int) { + xLen := (x.BitLen() + 63) >> 6 // number of 64-bit words + zLen := len(z) + if zLen >= xLen && x.Sign() > 0 { + var y, yi big.Int + y.Set(x) + two64 := big.NewInt(1) + two64.Lsh(two64, 64).Sub(two64, big.NewInt(1)) + for i := 0; i < xLen; i++ { + yi.And(&y, two64) + z[i] = yi.Uint64() + y.Rsh(&y, 64) + } + } + for i := xLen; i < zLen; i++ { + z[i] = 0 + } +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/doc.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/doc.go new file mode 100644 index 00000000000..7e023090707 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/doc.go @@ -0,0 +1,62 @@ +// Copyright 2014 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 sha3 implements the SHA-3 fixed-output-length hash functions and +// the SHAKE variable-output-length hash functions defined by FIPS-202. +// +// Both types of hash function use the "sponge" construction and the Keccak +// permutation. For a detailed specification see http://keccak.noekeon.org/ +// +// # Guidance +// +// If you aren't sure what function you need, use SHAKE256 with at least 64 +// bytes of output. The SHAKE instances are faster than the SHA3 instances; +// the latter have to allocate memory to conform to the hash.Hash interface. +// +// If you need a secret-key MAC (message authentication code), prepend the +// secret key to the input, hash with SHAKE256 and read at least 32 bytes of +// output. +// +// # Security strengths +// +// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security +// strength against preimage attacks of x bits. Since they only produce "x" +// bits of output, their collision-resistance is only "x/2" bits. +// +// The SHAKE-256 and -128 functions have a generic security strength of 256 and +// 128 bits against all attacks, provided that at least 2x bits of their output +// is used. Requesting more than 64 or 32 bytes of output, respectively, does +// not increase the collision-resistance of the SHAKE functions. +// +// # The sponge construction +// +// A sponge builds a pseudo-random function from a public pseudo-random +// permutation, by applying the permutation to a state of "rate + capacity" +// bytes, but hiding "capacity" of the bytes. +// +// A sponge starts out with a zero state. To hash an input using a sponge, up +// to "rate" bytes of the input are XORed into the sponge's state. The sponge +// is then "full" and the permutation is applied to "empty" it. This process is +// repeated until all the input has been "absorbed". The input is then padded. +// The digest is "squeezed" from the sponge in the same way, except that output +// is copied out instead of input being XORed in. +// +// A sponge is parameterized by its generic security strength, which is equal +// to half its capacity; capacity + rate is equal to the permutation's width. +// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means +// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. +// +// # Recommendations +// +// The SHAKE functions are recommended for most new uses. They can produce +// output of arbitrary length. SHAKE256, with an output length of at least +// 64 bytes, provides 256-bit security against all attacks. The Keccak team +// recommends it for most applications upgrading from SHA2-512. (NIST chose a +// much stronger, but much slower, sponge instance for SHA3-512.) +// +// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. +// They produce output of the same length, with the same security strengths +// against all attacks. This means, in particular, that SHA3-256 only has +// 128-bit collision resistance, because its output length is 32 bytes. +package sha3 diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/hashes.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/hashes.go new file mode 100644 index 00000000000..7d2365a76ed --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/hashes.go @@ -0,0 +1,69 @@ +// Copyright 2014 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 sha3 + +// This file provides functions for creating instances of the SHA-3 +// and SHAKE hash functions, as well as utility functions for hashing +// bytes. + +// New224 creates a new SHA3-224 hash. +// Its generic security strength is 224 bits against preimage attacks, +// and 112 bits against collision attacks. +func New224() State { + return State{rate: 144, outputLen: 28, dsbyte: 0x06} +} + +// New256 creates a new SHA3-256 hash. +// Its generic security strength is 256 bits against preimage attacks, +// and 128 bits against collision attacks. +func New256() State { + return State{rate: 136, outputLen: 32, dsbyte: 0x06} +} + +// New384 creates a new SHA3-384 hash. +// Its generic security strength is 384 bits against preimage attacks, +// and 192 bits against collision attacks. +func New384() State { + return State{rate: 104, outputLen: 48, dsbyte: 0x06} +} + +// New512 creates a new SHA3-512 hash. +// Its generic security strength is 512 bits against preimage attacks, +// and 256 bits against collision attacks. +func New512() State { + return State{rate: 72, outputLen: 64, dsbyte: 0x06} +} + +// Sum224 returns the SHA3-224 digest of the data. +func Sum224(data []byte) (digest [28]byte) { + h := New224() + _, _ = h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum256 returns the SHA3-256 digest of the data. +func Sum256(data []byte) (digest [32]byte) { + h := New256() + _, _ = h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum384 returns the SHA3-384 digest of the data. +func Sum384(data []byte) (digest [48]byte) { + h := New384() + _, _ = h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum512 returns the SHA3-512 digest of the data. +func Sum512(data []byte) (digest [64]byte) { + h := New512() + _, _ = h.Write(data) + h.Sum(digest[:0]) + return +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go new file mode 100644 index 00000000000..1755fd1e6dc --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go @@ -0,0 +1,391 @@ +// Copyright 2014 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 sha3 + +// KeccakF1600 applies the Keccak permutation to a 1600b-wide +// state represented as a slice of 25 uint64s. +// If turbo is true, applies the 12-round variant instead of the +// regular 24-round variant. +// nolint:funlen +func KeccakF1600(a *[25]uint64, turbo bool) { + // Implementation translated from Keccak-inplace.c + // in the keccak reference code. + var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 + + i := 0 + + if turbo { + i = 12 + } + + for ; i < 24; i += 4 { + // Combines the 5 steps in each round into 2 steps. + // Unrolls 4 rounds per loop and spreads some steps across rounds. + + // Round 1 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[6] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[12] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[18] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[24] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i] + a[6] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[16] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[22] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[3] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[10] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[1] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[7] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[19] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[20] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[11] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[23] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[4] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[5] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[2] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[8] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[14] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[15] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + // Round 2 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[16] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[7] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[23] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[14] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+1] + a[16] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[11] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[2] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[18] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[20] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[6] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[22] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[4] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[15] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[1] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[8] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[24] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[10] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[12] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[3] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[19] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[5] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + // Round 3 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[11] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[22] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[8] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[19] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+2] + a[11] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[1] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[12] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[23] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[15] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[16] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[2] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[24] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[5] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[6] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[3] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[14] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[20] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[7] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[18] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[4] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[10] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + // Round 4 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[1] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[2] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[3] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[4] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+3] + a[1] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[6] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[7] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[8] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[5] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[11] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[12] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[14] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[10] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[16] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[18] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[19] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[15] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[22] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[23] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[24] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[20] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/rc.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/rc.go new file mode 100644 index 00000000000..6a3df42f305 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/rc.go @@ -0,0 +1,29 @@ +package sha3 + +// RC stores the round constants for use in the ι step. +var RC = [24]uint64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/sha3.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/sha3.go new file mode 100644 index 00000000000..a0df5aa6c59 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/sha3.go @@ -0,0 +1,200 @@ +// Copyright 2014 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 sha3 + +// spongeDirection indicates the direction bytes are flowing through the sponge. +type spongeDirection int + +const ( + // spongeAbsorbing indicates that the sponge is absorbing input. + spongeAbsorbing spongeDirection = iota + // spongeSqueezing indicates that the sponge is being squeezed. + spongeSqueezing +) + +const ( + // maxRate is the maximum size of the internal buffer. SHAKE-256 + // currently needs the largest buffer. + maxRate = 168 +) + +func (d *State) buf() []byte { + return d.storage.asBytes()[d.bufo:d.bufe] +} + +type State struct { + // Generic sponge components. + a [25]uint64 // main state of the hash + rate int // the number of bytes of state to use + + bufo int // offset of buffer in storage + bufe int // end of buffer in storage + + // dsbyte contains the "domain separation" bits and the first bit of + // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the + // SHA-3 and SHAKE functions by appending bitstrings to the message. + // Using a little-endian bit-ordering convention, these are "01" for SHA-3 + // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the + // padding rule from section 5.1 is applied to pad the message to a multiple + // of the rate, which involves adding a "1" bit, zero or more "0" bits, and + // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, + // giving 00000110b (0x06) and 00011111b (0x1f). + // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf + // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and + // Extendable-Output Functions (May 2014)" + dsbyte byte + + storage storageBuf + + // Specific to SHA-3 and SHAKE. + outputLen int // the default output size in bytes + state spongeDirection // whether the sponge is absorbing or squeezing + turbo bool // Whether we're using 12 rounds instead of 24 +} + +// BlockSize returns the rate of sponge underlying this hash function. +func (d *State) BlockSize() int { return d.rate } + +// Size returns the output size of the hash function in bytes. +func (d *State) Size() int { return d.outputLen } + +// Reset clears the internal state by zeroing the sponge state and +// the byte buffer, and setting Sponge.state to absorbing. +func (d *State) Reset() { + // Zero the permutation's state. + for i := range d.a { + d.a[i] = 0 + } + d.state = spongeAbsorbing + d.bufo = 0 + d.bufe = 0 +} + +func (d *State) clone() *State { + ret := *d + return &ret +} + +// permute applies the KeccakF-1600 permutation. It handles +// any input-output buffering. +func (d *State) permute() { + switch d.state { + case spongeAbsorbing: + // If we're absorbing, we need to xor the input into the state + // before applying the permutation. + xorIn(d, d.buf()) + d.bufe = 0 + d.bufo = 0 + KeccakF1600(&d.a, d.turbo) + case spongeSqueezing: + // If we're squeezing, we need to apply the permutation before + // copying more output. + KeccakF1600(&d.a, d.turbo) + d.bufe = d.rate + d.bufo = 0 + copyOut(d, d.buf()) + } +} + +// pads appends the domain separation bits in dsbyte, applies +// the multi-bitrate 10..1 padding rule, and permutes the state. +func (d *State) padAndPermute(dsbyte byte) { + // Pad with this instance's domain-separator bits. We know that there's + // at least one byte of space in d.buf() because, if it were full, + // permute would have been called to empty it. dsbyte also contains the + // first one bit for the padding. See the comment in the state struct. + zerosStart := d.bufe + 1 + d.bufe = d.rate + buf := d.buf() + buf[zerosStart-1] = dsbyte + for i := zerosStart; i < d.rate; i++ { + buf[i] = 0 + } + // This adds the final one bit for the padding. Because of the way that + // bits are numbered from the LSB upwards, the final bit is the MSB of + // the last byte. + buf[d.rate-1] ^= 0x80 + // Apply the permutation + d.permute() + d.state = spongeSqueezing + d.bufe = d.rate + copyOut(d, buf) +} + +// Write absorbs more data into the hash's state. It produces an error +// if more data is written to the ShakeHash after writing +func (d *State) Write(p []byte) (written int, err error) { + if d.state != spongeAbsorbing { + panic("sha3: write to sponge after read") + } + written = len(p) + + for len(p) > 0 { + bufl := d.bufe - d.bufo + if bufl == 0 && len(p) >= d.rate { + // The fast path; absorb a full "rate" bytes of input and apply the permutation. + xorIn(d, p[:d.rate]) + p = p[d.rate:] + KeccakF1600(&d.a, d.turbo) + } else { + // The slow path; buffer the input until we can fill the sponge, and then xor it in. + todo := d.rate - bufl + if todo > len(p) { + todo = len(p) + } + d.bufe += todo + buf := d.buf() + copy(buf[bufl:], p[:todo]) + p = p[todo:] + + // If the sponge is full, apply the permutation. + if d.bufe == d.rate { + d.permute() + } + } + } + + return written, nil +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (d *State) Read(out []byte) (n int, err error) { + // If we're still absorbing, pad and apply the permutation. + if d.state == spongeAbsorbing { + d.padAndPermute(d.dsbyte) + } + + n = len(out) + + // Now, do the squeezing. + for len(out) > 0 { + buf := d.buf() + n := copy(out, buf) + d.bufo += n + out = out[n:] + + // Apply the permutation if we've squeezed the sponge dry. + if d.bufo == d.bufe { + d.permute() + } + } + + return +} + +// Sum applies padding to the hash state and then squeezes out the desired +// number of output bytes. +func (d *State) Sum(in []byte) []byte { + // Make a copy of the original hash so that caller can keep writing + // and summing. + dup := d.clone() + hash := make([]byte, dup.outputLen) + _, _ = dup.Read(hash) + return append(in, hash...) +} + +func (d *State) IsAbsorbing() bool { + return d.state == spongeAbsorbing +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s b/src/vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s new file mode 100644 index 00000000000..8a4458f63f9 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s @@ -0,0 +1,33 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo,!appengine + +#include "textflag.h" + +// func kimd(function code, chain *[200]byte, src []byte) +TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 + MOVD function+0(FP), R0 + MOVD chain+8(FP), R1 + LMG src+16(FP), R2, R3 // R2=base, R3=len + +continue: + WORD $0xB93E0002 // KIMD --, R2 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET + +// func klmd(function code, chain *[200]byte, dst, src []byte) +TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 + // TODO: SHAKE support + MOVD function+0(FP), R0 + MOVD chain+8(FP), R1 + LMG dst+16(FP), R2, R3 // R2=base, R3=len + LMG src+40(FP), R4, R5 // R4=base, R5=len + +continue: + WORD $0xB93F0024 // KLMD R2, R4 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/shake.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/shake.go new file mode 100644 index 00000000000..77817f758cb --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/shake.go @@ -0,0 +1,119 @@ +// Copyright 2014 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 sha3 + +// This file defines the ShakeHash interface, and provides +// functions for creating SHAKE and cSHAKE instances, as well as utility +// functions for hashing bytes to arbitrary-length output. +// +// +// SHAKE implementation is based on FIPS PUB 202 [1] +// cSHAKE implementations is based on NIST SP 800-185 [2] +// +// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf +// [2] https://doi.org/10.6028/NIST.SP.800-185 + +import ( + "io" +) + +// ShakeHash defines the interface to hash functions that +// support arbitrary-length output. +type ShakeHash interface { + // Write absorbs more data into the hash's state. It panics if input is + // written to it after output has been read from it. + io.Writer + + // Read reads more output from the hash; reading affects the hash's + // state. (ShakeHash.Read is thus very different from Hash.Sum) + // It never returns an error. + io.Reader + + // Clone returns a copy of the ShakeHash in its current state. + Clone() ShakeHash + + // Reset resets the ShakeHash to its initial state. + Reset() +} + +// Consts for configuring initial SHA-3 state +const ( + dsbyteShake = 0x1f + rate128 = 168 + rate256 = 136 +) + +// Clone returns copy of SHAKE context within its current state. +func (d *State) Clone() ShakeHash { + return d.clone() +} + +// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. +// Its generic security strength is 128 bits against all attacks if at +// least 32 bytes of its output are used. +func NewShake128() State { + return State{rate: rate128, dsbyte: dsbyteShake} +} + +// NewTurboShake128 creates a new TurboSHAKE128 variable-output-length ShakeHash. +// Its generic security strength is 128 bits against all attacks if at +// least 32 bytes of its output are used. +// D is the domain separation byte and must be between 0x01 and 0x7f inclusive. +func NewTurboShake128(D byte) State { + if D == 0 || D > 0x7f { + panic("turboshake: D out of range") + } + return State{rate: rate128, dsbyte: D, turbo: true} +} + +// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. +// Its generic security strength is 256 bits against all attacks if +// at least 64 bytes of its output are used. +func NewShake256() State { + return State{rate: rate256, dsbyte: dsbyteShake} +} + +// NewTurboShake256 creates a new TurboSHAKE256 variable-output-length ShakeHash. +// Its generic security strength is 256 bits against all attacks if +// at least 64 bytes of its output are used. +// D is the domain separation byte and must be between 0x01 and 0x7f inclusive. +func NewTurboShake256(D byte) State { + if D == 0 || D > 0x7f { + panic("turboshake: D out of range") + } + return State{rate: rate256, dsbyte: D, turbo: true} +} + +// ShakeSum128 writes an arbitrary-length digest of data into hash. +func ShakeSum128(hash, data []byte) { + h := NewShake128() + _, _ = h.Write(data) + _, _ = h.Read(hash) +} + +// ShakeSum256 writes an arbitrary-length digest of data into hash. +func ShakeSum256(hash, data []byte) { + h := NewShake256() + _, _ = h.Write(data) + _, _ = h.Read(hash) +} + +// TurboShakeSum128 writes an arbitrary-length digest of data into hash. +func TurboShakeSum128(hash, data []byte, D byte) { + h := NewTurboShake128(D) + _, _ = h.Write(data) + _, _ = h.Read(hash) +} + +// TurboShakeSum256 writes an arbitrary-length digest of data into hash. +func TurboShakeSum256(hash, data []byte, D byte) { + h := NewTurboShake256(D) + _, _ = h.Write(data) + _, _ = h.Read(hash) +} + +func (d *State) SwitchDS(D byte) { + d.dsbyte = D +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/xor.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/xor.go new file mode 100644 index 00000000000..1e21337454f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/xor.go @@ -0,0 +1,15 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !386 && !ppc64le) || appengine +// +build !amd64,!386,!ppc64le appengine + +package sha3 + +// A storageBuf is an aligned array of maxRate bytes. +type storageBuf [maxRate]byte + +func (b *storageBuf) asBytes() *[maxRate]byte { + return (*[maxRate]byte)(b) +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go new file mode 100644 index 00000000000..2b0c6617906 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go @@ -0,0 +1,33 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 || appengine) && (!386 || appengine) && (!ppc64le || appengine) +// +build !amd64 appengine +// +build !386 appengine +// +build !ppc64le appengine + +package sha3 + +import "encoding/binary" + +// xorIn xors the bytes in buf into the state; it +// makes no non-portable assumptions about memory layout +// or alignment. +func xorIn(d *State, buf []byte) { + n := len(buf) / 8 + + for i := 0; i < n; i++ { + a := binary.LittleEndian.Uint64(buf) + d.a[i] ^= a + buf = buf[8:] + } +} + +// copyOut copies ulint64s to a byte buffer. +func copyOut(d *State, b []byte) { + for i := 0; len(b) >= 8; i++ { + binary.LittleEndian.PutUint64(b, d.a[i]) + b = b[8:] + } +} diff --git a/src/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go b/src/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go new file mode 100644 index 00000000000..052fc8d32d2 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go @@ -0,0 +1,61 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (amd64 || 386 || ppc64le) && !appengine +// +build amd64 386 ppc64le +// +build !appengine + +package sha3 + +import "unsafe" + +// A storageBuf is an aligned array of maxRate bytes. +type storageBuf [maxRate / 8]uint64 + +func (b *storageBuf) asBytes() *[maxRate]byte { + return (*[maxRate]byte)(unsafe.Pointer(b)) +} + +// xorInuses unaligned reads and writes to update d.a to contain d.a +// XOR buf. +func xorIn(d *State, buf []byte) { + n := len(buf) + bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] + if n >= 72 { + d.a[0] ^= bw[0] + d.a[1] ^= bw[1] + d.a[2] ^= bw[2] + d.a[3] ^= bw[3] + d.a[4] ^= bw[4] + d.a[5] ^= bw[5] + d.a[6] ^= bw[6] + d.a[7] ^= bw[7] + d.a[8] ^= bw[8] + } + if n >= 104 { + d.a[9] ^= bw[9] + d.a[10] ^= bw[10] + d.a[11] ^= bw[11] + d.a[12] ^= bw[12] + } + if n >= 136 { + d.a[13] ^= bw[13] + d.a[14] ^= bw[14] + d.a[15] ^= bw[15] + d.a[16] ^= bw[16] + } + if n >= 144 { + d.a[17] ^= bw[17] + } + if n >= 168 { + d.a[18] ^= bw[18] + d.a[19] ^= bw[19] + d.a[20] ^= bw[20] + } +} + +func copyOut(d *State, buf []byte) { + ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) + copy(buf, ab[:]) +} diff --git a/src/vendor/github.com/cloudflare/circl/kem/hybrid/ckem.go b/src/vendor/github.com/cloudflare/circl/kem/hybrid/ckem.go new file mode 100644 index 00000000000..c0620e8db99 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/hybrid/ckem.go @@ -0,0 +1,207 @@ +package hybrid + +// TODO move over to crypto/ecdh once we can assume Go 1.20. + +import ( + "crypto/elliptic" + cryptoRand "crypto/rand" + "crypto/subtle" + "math/big" + + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/xof" +) + +type cPublicKey struct { + scheme *cScheme + x, y *big.Int +} +type cPrivateKey struct { + scheme *cScheme + key []byte +} +type cScheme struct { + curve elliptic.Curve +} + +var p256Kem = &cScheme{elliptic.P256()} + +func (sch *cScheme) scSize() int { + return (sch.curve.Params().N.BitLen() + 7) / 8 +} + +func (sch *cScheme) ptSize() int { + return (sch.curve.Params().BitSize + 7) / 8 +} + +func (sch *cScheme) Name() string { + return sch.curve.Params().Name +} + +func (sch *cScheme) PublicKeySize() int { + return 2*sch.ptSize() + 1 +} + +func (sch *cScheme) PrivateKeySize() int { + return sch.scSize() +} + +func (sch *cScheme) SeedSize() int { + return sch.PrivateKeySize() +} + +func (sch *cScheme) SharedKeySize() int { + return sch.ptSize() +} + +func (sch *cScheme) CiphertextSize() int { + return sch.PublicKeySize() +} + +func (sch *cScheme) EncapsulationSeedSize() int { + return sch.SeedSize() +} + +func (sk *cPrivateKey) Scheme() kem.Scheme { return sk.scheme } +func (pk *cPublicKey) Scheme() kem.Scheme { return pk.scheme } + +func (sk *cPrivateKey) MarshalBinary() ([]byte, error) { + ret := make([]byte, len(sk.key)) + copy(ret, sk.key) + return ret, nil +} + +func (sk *cPrivateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*cPrivateKey) + if !ok { + return false + } + if oth.scheme != sk.scheme { + return false + } + return subtle.ConstantTimeCompare(oth.key, sk.key) == 1 +} + +func (sk *cPrivateKey) Public() kem.PublicKey { + x, y := sk.scheme.curve.ScalarBaseMult(sk.key) + return &cPublicKey{ + sk.scheme, + x, + y, + } +} + +func (pk *cPublicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*cPublicKey) + if !ok { + return false + } + if oth.scheme != pk.scheme { + return false + } + return oth.x.Cmp(pk.x) == 0 && oth.y.Cmp(pk.y) == 0 +} + +func (pk *cPublicKey) MarshalBinary() ([]byte, error) { + return elliptic.Marshal(pk.scheme.curve, pk.x, pk.y), nil +} + +func (sch *cScheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + seed := make([]byte, sch.SeedSize()) + _, err := cryptoRand.Read(seed) + if err != nil { + return nil, nil, err + } + pk, sk := sch.DeriveKeyPair(seed) + return pk, sk, nil +} + +func (sch *cScheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + if len(seed) != sch.SeedSize() { + panic(kem.ErrSeedSize) + } + h := xof.SHAKE256.New() + _, _ = h.Write(seed) + key, x, y, err := elliptic.GenerateKey(sch.curve, h) + if err != nil { + panic(err) + } + + sk := cPrivateKey{scheme: sch, key: key} + pk := cPublicKey{scheme: sch, x: x, y: y} + + return &pk, &sk +} + +func (sch *cScheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + seed := make([]byte, sch.EncapsulationSeedSize()) + _, err = cryptoRand.Read(seed) + if err != nil { + return + } + return sch.EncapsulateDeterministically(pk, seed) +} + +func (pk *cPublicKey) X(sk *cPrivateKey) []byte { + if pk.scheme != sk.scheme { + panic(kem.ErrTypeMismatch) + } + + sharedKey := make([]byte, pk.scheme.SharedKeySize()) + xShared, _ := pk.scheme.curve.ScalarMult(pk.x, pk.y, sk.key) + xShared.FillBytes(sharedKey) + return sharedKey +} + +func (sch *cScheme) EncapsulateDeterministically( + pk kem.PublicKey, seed []byte, +) (ct, ss []byte, err error) { + if len(seed) != sch.EncapsulationSeedSize() { + return nil, nil, kem.ErrSeedSize + } + pub, ok := pk.(*cPublicKey) + if !ok || pub.scheme != sch { + return nil, nil, kem.ErrTypeMismatch + } + + pk2, sk2 := sch.DeriveKeyPair(seed) + ss = pub.X(sk2.(*cPrivateKey)) + ct, _ = pk2.MarshalBinary() + return +} + +func (sch *cScheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != sch.CiphertextSize() { + return nil, kem.ErrCiphertextSize + } + + priv, ok := sk.(*cPrivateKey) + if !ok || priv.scheme != sch { + return nil, kem.ErrTypeMismatch + } + + pk, err := sch.UnmarshalBinaryPublicKey(ct) + if err != nil { + return nil, err + } + + ss := pk.(*cPublicKey).X(priv) + return ss, nil +} + +func (sch *cScheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + if len(buf) != sch.PublicKeySize() { + return nil, kem.ErrPubKeySize + } + x, y := elliptic.Unmarshal(sch.curve, buf) + return &cPublicKey{sch, x, y}, nil +} + +func (sch *cScheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != sch.PrivateKeySize() { + return nil, kem.ErrPrivKeySize + } + ret := cPrivateKey{sch, make([]byte, sch.PrivateKeySize())} + copy(ret.key, buf) + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go b/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go new file mode 100644 index 00000000000..8be85d70c81 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go @@ -0,0 +1,355 @@ +// Package hybrid defines several hybrid classical/quantum KEMs for use in TLS. +// +// Hybrid KEMs in TLS are created by simple concatenation +// of shared secrets, cipher texts, public keys, etc. +// This is safe for TLS, see eg. +// +// https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/ +// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf +// +// Note that this approach is not proven secure in broader context. +// +// For deriving a KEM keypair deterministically and encapsulating +// deterministically, we expand a single seed to both using SHAKE256, +// so that a non-uniform seed (such as a shared secret generated by a hybrid +// KEM where one of the KEMs is weak) doesn't impact just one of the KEMs. +// +// Of our XOF (SHAKE256), we desire two security properties: +// +// 1. The internal state of the XOF should be big enough so that we +// do not loose entropy. +// 2. From one of the new seeds, we shouldn't be able to derive +// the other or the original seed. +// +// SHAKE256, and all siblings in the SHA3 family, have a 200B internal +// state, so (1) is fine if our seeds are less than 200B. +// If SHAKE256 is computationally indistinguishable from a random +// sponge, then it affords us 256b security against (2) by the +// flat sponge claim [https://keccak.team/files/SpongeFunctions.pdf]. +// None of the implemented schemes claim more than 256b security +// and so SHAKE256 will do fine. +package hybrid + +import ( + "errors" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/kem/kyber/kyber1024" + "github.com/cloudflare/circl/kem/kyber/kyber512" + "github.com/cloudflare/circl/kem/kyber/kyber768" + "github.com/cloudflare/circl/kem/mlkem/mlkem768" +) + +var ErrUninitialized = errors.New("public or private key not initialized") + +// Returns the hybrid KEM of Kyber512Draft00 and X25519. +func Kyber512X25519() kem.Scheme { return kyber512X } + +// Returns the hybrid KEM of Kyber768Draft00 and X25519. +func Kyber768X25519() kem.Scheme { return kyber768X } + +// Returns the hybrid KEM of Kyber768Draft00 and X448. +func Kyber768X448() kem.Scheme { return kyber768X4 } + +// Returns the hybrid KEM of Kyber1024Draft00 and X448. +func Kyber1024X448() kem.Scheme { return kyber1024X } + +// Returns the hybrid KEM of Kyber768Draft00 and P-256. +func P256Kyber768Draft00() kem.Scheme { return p256Kyber768Draft00 } + +// Returns the hybrid KEM of ML-KEM-768 and X25519. +// https://www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-01.html +func X25519MLKEM768() kem.Scheme { return xmlkem768 } + +var p256Kyber768Draft00 kem.Scheme = &scheme{ + "P256Kyber768Draft00", + p256Kem, + kyber768.Scheme(), +} + +var kyber512X kem.Scheme = &scheme{ + "Kyber512-X25519", + x25519Kem, + kyber512.Scheme(), +} + +var kyber768X kem.Scheme = &scheme{ + "Kyber768-X25519", + x25519Kem, + kyber768.Scheme(), +} + +var kyber768X4 kem.Scheme = &scheme{ + "Kyber768-X448", + x448Kem, + kyber768.Scheme(), +} + +var kyber1024X kem.Scheme = &scheme{ + "Kyber1024-X448", + x448Kem, + kyber1024.Scheme(), +} + +var xmlkem768 kem.Scheme = &scheme{ + "X25519MLKEM768", + mlkem768.Scheme(), + x25519Kem, +} + +// Public key of a hybrid KEM. +type publicKey struct { + scheme *scheme + first kem.PublicKey + second kem.PublicKey +} + +// Private key of a hybrid KEM. +type privateKey struct { + scheme *scheme + first kem.PrivateKey + second kem.PrivateKey +} + +// Scheme for a hybrid KEM. +type scheme struct { + name string + first kem.Scheme + second kem.Scheme +} + +func (sch *scheme) Name() string { return sch.name } +func (sch *scheme) PublicKeySize() int { + return sch.first.PublicKeySize() + sch.second.PublicKeySize() +} + +func (sch *scheme) PrivateKeySize() int { + return sch.first.PrivateKeySize() + sch.second.PrivateKeySize() +} + +func (sch *scheme) SeedSize() int { + first := sch.first.SeedSize() + second := sch.second.SeedSize() + ret := second + if first > second { + ret = first + } + return ret +} + +func (sch *scheme) SharedKeySize() int { + return sch.first.SharedKeySize() + sch.second.SharedKeySize() +} + +func (sch *scheme) CiphertextSize() int { + return sch.first.CiphertextSize() + sch.second.CiphertextSize() +} + +func (sch *scheme) EncapsulationSeedSize() int { + first := sch.first.EncapsulationSeedSize() + second := sch.second.EncapsulationSeedSize() + ret := second + if first > second { + ret = first + } + return ret +} + +func (sk *privateKey) Scheme() kem.Scheme { return sk.scheme } +func (pk *publicKey) Scheme() kem.Scheme { return pk.scheme } + +func (sk *privateKey) MarshalBinary() ([]byte, error) { + if sk.first == nil || sk.second == nil { + return nil, ErrUninitialized + } + first, err := sk.first.MarshalBinary() + if err != nil { + return nil, err + } + second, err := sk.second.MarshalBinary() + if err != nil { + return nil, err + } + return append(first, second...), nil +} + +func (sk *privateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*privateKey) + if !ok { + return false + } + if sk.first == nil && sk.second == nil && oth.first == nil && oth.second == nil { + return true + } + if sk.first == nil || sk.second == nil || oth.first == nil || oth.second == nil { + return false + } + return sk.first.Equal(oth.first) && sk.second.Equal(oth.second) +} + +func (sk *privateKey) Public() kem.PublicKey { + return &publicKey{sk.scheme, sk.first.Public(), sk.second.Public()} +} + +func (pk *publicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*publicKey) + if !ok { + return false + } + if pk.first == nil && pk.second == nil && oth.first == nil && oth.second == nil { + return true + } + if pk.first == nil || pk.second == nil || oth.first == nil || oth.second == nil { + return false + } + return pk.first.Equal(oth.first) && pk.second.Equal(oth.second) +} + +func (pk *publicKey) MarshalBinary() ([]byte, error) { + if pk.first == nil || pk.second == nil { + return nil, ErrUninitialized + } + first, err := pk.first.MarshalBinary() + if err != nil { + return nil, err + } + second, err := pk.second.MarshalBinary() + if err != nil { + return nil, err + } + return append(first, second...), nil +} + +func (sch *scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + pk1, sk1, err := sch.first.GenerateKeyPair() + if err != nil { + return nil, nil, err + } + pk2, sk2, err := sch.second.GenerateKeyPair() + if err != nil { + return nil, nil, err + } + + return &publicKey{sch, pk1, pk2}, &privateKey{sch, sk1, sk2}, nil +} + +func (sch *scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + if len(seed) != sch.SeedSize() { + panic(kem.ErrSeedSize) + } + h := sha3.NewShake256() + _, _ = h.Write(seed) + first := make([]byte, sch.first.SeedSize()) + second := make([]byte, sch.second.SeedSize()) + _, _ = h.Read(first) + _, _ = h.Read(second) + + pk1, sk1 := sch.first.DeriveKeyPair(first) + pk2, sk2 := sch.second.DeriveKeyPair(second) + + return &publicKey{sch, pk1, pk2}, &privateKey{sch, sk1, sk2} +} + +func (sch *scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + pub, ok := pk.(*publicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + + ct1, ss1, err := sch.first.Encapsulate(pub.first) + if err != nil { + return nil, nil, err + } + + ct2, ss2, err := sch.second.Encapsulate(pub.second) + if err != nil { + return nil, nil, err + } + + return append(ct1, ct2...), append(ss1, ss2...), nil +} + +func (sch *scheme) EncapsulateDeterministically( + pk kem.PublicKey, seed []byte, +) (ct, ss []byte, err error) { + if len(seed) != sch.EncapsulationSeedSize() { + return nil, nil, kem.ErrSeedSize + } + + h := sha3.NewShake256() + _, _ = h.Write(seed) + first := make([]byte, sch.first.EncapsulationSeedSize()) + second := make([]byte, sch.second.EncapsulationSeedSize()) + _, _ = h.Read(first) + _, _ = h.Read(second) + + pub, ok := pk.(*publicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + + ct1, ss1, err := sch.first.EncapsulateDeterministically(pub.first, first) + if err != nil { + return nil, nil, err + } + ct2, ss2, err := sch.second.EncapsulateDeterministically(pub.second, second) + if err != nil { + return nil, nil, err + } + return append(ct1, ct2...), append(ss1, ss2...), nil +} + +func (sch *scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != sch.CiphertextSize() { + return nil, kem.ErrCiphertextSize + } + + priv, ok := sk.(*privateKey) + if !ok { + return nil, kem.ErrTypeMismatch + } + + firstSize := sch.first.CiphertextSize() + ss1, err := sch.first.Decapsulate(priv.first, ct[:firstSize]) + if err != nil { + return nil, err + } + ss2, err := sch.second.Decapsulate(priv.second, ct[firstSize:]) + if err != nil { + return nil, err + } + return append(ss1, ss2...), nil +} + +func (sch *scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + if len(buf) != sch.PublicKeySize() { + return nil, kem.ErrPubKeySize + } + firstSize := sch.first.PublicKeySize() + pk1, err := sch.first.UnmarshalBinaryPublicKey(buf[:firstSize]) + if err != nil { + return nil, err + } + pk2, err := sch.second.UnmarshalBinaryPublicKey(buf[firstSize:]) + if err != nil { + return nil, err + } + return &publicKey{sch, pk1, pk2}, nil +} + +func (sch *scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != sch.PrivateKeySize() { + return nil, kem.ErrPrivKeySize + } + firstSize := sch.first.PrivateKeySize() + sk1, err := sch.first.UnmarshalBinaryPrivateKey(buf[:firstSize]) + if err != nil { + return nil, err + } + sk2, err := sch.second.UnmarshalBinaryPrivateKey(buf[firstSize:]) + if err != nil { + return nil, err + } + return &privateKey{sch, sk1, sk2}, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/kem/hybrid/xkem.go b/src/vendor/github.com/cloudflare/circl/kem/hybrid/xkem.go new file mode 100644 index 00000000000..919fb8a9c21 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/hybrid/xkem.go @@ -0,0 +1,208 @@ +package hybrid + +import ( + "bytes" + cryptoRand "crypto/rand" + "crypto/subtle" + + "github.com/cloudflare/circl/dh/x25519" + "github.com/cloudflare/circl/dh/x448" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" +) + +type xPublicKey struct { + scheme *xScheme + key []byte +} +type xPrivateKey struct { + scheme *xScheme + key []byte +} +type xScheme struct { + size int +} + +var ( + x25519Kem = &xScheme{x25519.Size} + x448Kem = &xScheme{x448.Size} +) + +func (sch *xScheme) Name() string { + switch sch.size { + case x25519.Size: + return "X25519" + case x448.Size: + return "X448" + } + panic(kem.ErrTypeMismatch) +} + +func (sch *xScheme) PublicKeySize() int { return sch.size } +func (sch *xScheme) PrivateKeySize() int { return sch.size } +func (sch *xScheme) SeedSize() int { return sch.size } +func (sch *xScheme) SharedKeySize() int { return sch.size } +func (sch *xScheme) CiphertextSize() int { return sch.size } +func (sch *xScheme) EncapsulationSeedSize() int { return sch.size } + +func (sk *xPrivateKey) Scheme() kem.Scheme { return sk.scheme } +func (pk *xPublicKey) Scheme() kem.Scheme { return pk.scheme } + +func (sk *xPrivateKey) MarshalBinary() ([]byte, error) { + ret := make([]byte, len(sk.key)) + copy(ret, sk.key) + return ret, nil +} + +func (sk *xPrivateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*xPrivateKey) + if !ok { + return false + } + if oth.scheme != sk.scheme { + return false + } + return subtle.ConstantTimeCompare(oth.key, sk.key) == 1 +} + +func (sk *xPrivateKey) Public() kem.PublicKey { + pk := xPublicKey{sk.scheme, make([]byte, sk.scheme.size)} + switch sk.scheme.size { + case x25519.Size: + var sk2, pk2 x25519.Key + copy(sk2[:], sk.key) + x25519.KeyGen(&pk2, &sk2) + copy(pk.key, pk2[:]) + case x448.Size: + var sk2, pk2 x448.Key + copy(sk2[:], sk.key) + x448.KeyGen(&pk2, &sk2) + copy(pk.key, pk2[:]) + } + return &pk +} + +func (pk *xPublicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*xPublicKey) + if !ok { + return false + } + if oth.scheme != pk.scheme { + return false + } + return bytes.Equal(oth.key, pk.key) +} + +func (pk *xPublicKey) MarshalBinary() ([]byte, error) { + ret := make([]byte, pk.scheme.size) + copy(ret, pk.key) + return ret, nil +} + +func (sch *xScheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + seed := make([]byte, sch.SeedSize()) + _, err := cryptoRand.Read(seed) + if err != nil { + return nil, nil, err + } + pk, sk := sch.DeriveKeyPair(seed) + return pk, sk, nil +} + +func (sch *xScheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + if len(seed) != sch.SeedSize() { + panic(kem.ErrSeedSize) + } + sk := xPrivateKey{scheme: sch, key: make([]byte, sch.size)} + + h := sha3.NewShake256() + _, _ = h.Write(seed) + _, _ = h.Read(sk.key) + + return sk.Public(), &sk +} + +func (sch *xScheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + seed := make([]byte, sch.EncapsulationSeedSize()) + _, err = cryptoRand.Read(seed) + if err != nil { + return + } + return sch.EncapsulateDeterministically(pk, seed) +} + +func (pk *xPublicKey) X(sk *xPrivateKey) []byte { + if pk.scheme != sk.scheme { + panic(kem.ErrTypeMismatch) + } + + switch pk.scheme.size { + case x25519.Size: + var ss2, pk2, sk2 x25519.Key + copy(pk2[:], pk.key) + copy(sk2[:], sk.key) + x25519.Shared(&ss2, &sk2, &pk2) + return ss2[:] + case x448.Size: + var ss2, pk2, sk2 x448.Key + copy(pk2[:], pk.key) + copy(sk2[:], sk.key) + x448.Shared(&ss2, &sk2, &pk2) + return ss2[:] + } + panic(kem.ErrTypeMismatch) +} + +func (sch *xScheme) EncapsulateDeterministically( + pk kem.PublicKey, seed []byte, +) (ct, ss []byte, err error) { + if len(seed) != sch.EncapsulationSeedSize() { + return nil, nil, kem.ErrSeedSize + } + pub, ok := pk.(*xPublicKey) + if !ok || pub.scheme != sch { + return nil, nil, kem.ErrTypeMismatch + } + + pk2, sk2 := sch.DeriveKeyPair(seed) + ss = pub.X(sk2.(*xPrivateKey)) + ct, _ = pk2.MarshalBinary() + return +} + +func (sch *xScheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != sch.CiphertextSize() { + return nil, kem.ErrCiphertextSize + } + + priv, ok := sk.(*xPrivateKey) + if !ok || priv.scheme != sch { + return nil, kem.ErrTypeMismatch + } + + pk, err := sch.UnmarshalBinaryPublicKey(ct) + if err != nil { + return nil, err + } + + ss := pk.(*xPublicKey).X(priv) + return ss, nil +} + +func (sch *xScheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + if len(buf) != sch.PublicKeySize() { + return nil, kem.ErrPubKeySize + } + ret := xPublicKey{sch, make([]byte, sch.size)} + copy(ret.key, buf) + return &ret, nil +} + +func (sch *xScheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != sch.PrivateKeySize() { + return nil, kem.ErrPrivKeySize + } + ret := xPrivateKey{sch, make([]byte, sch.size)} + copy(ret.key, buf) + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/kem/kem.go b/src/vendor/github.com/cloudflare/circl/kem/kem.go new file mode 100644 index 00000000000..a2f6a2aae7a --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kem.go @@ -0,0 +1,121 @@ +// Package kem provides a unified interface for KEM schemes. +// +// A register of schemes is available in the package +// +// github.com/cloudflare/circl/kem/schemes +package kem + +import ( + "encoding" + "errors" +) + +// A KEM public key +type PublicKey interface { + // Returns the scheme for this public key + Scheme() Scheme + + encoding.BinaryMarshaler + Equal(PublicKey) bool +} + +// A KEM private key +type PrivateKey interface { + // Returns the scheme for this private key + Scheme() Scheme + + encoding.BinaryMarshaler + Equal(PrivateKey) bool + Public() PublicKey +} + +// A Scheme represents a specific instance of a KEM. +type Scheme interface { + // Name of the scheme + Name() string + + // GenerateKeyPair creates a new key pair. + GenerateKeyPair() (PublicKey, PrivateKey, error) + + // Encapsulate generates a shared key ss for the public key and + // encapsulates it into a ciphertext ct. + Encapsulate(pk PublicKey) (ct, ss []byte, err error) + + // Returns the shared key encapsulated in ciphertext ct for the + // private key sk. + Decapsulate(sk PrivateKey, ct []byte) ([]byte, error) + + // Unmarshals a PublicKey from the provided buffer. + UnmarshalBinaryPublicKey([]byte) (PublicKey, error) + + // Unmarshals a PrivateKey from the provided buffer. + UnmarshalBinaryPrivateKey([]byte) (PrivateKey, error) + + // Size of encapsulated keys. + CiphertextSize() int + + // Size of established shared keys. + SharedKeySize() int + + // Size of packed private keys. + PrivateKeySize() int + + // Size of packed public keys. + PublicKeySize() int + + // DeriveKeyPair deterministically derives a pair of keys from a seed. + // Panics if the length of seed is not equal to the value returned by + // SeedSize. + DeriveKeyPair(seed []byte) (PublicKey, PrivateKey) + + // Size of seed used in DeriveKey + SeedSize() int + + // EncapsulateDeterministically generates a shared key ss for the public + // key deterministically from the given seed and encapsulates it into + // a ciphertext ct. If unsure, you're better off using Encapsulate(). + EncapsulateDeterministically(pk PublicKey, seed []byte) ( + ct, ss []byte, err error) + + // Size of seed used in EncapsulateDeterministically(). + EncapsulationSeedSize() int +} + +// AuthScheme represents a KEM that supports authenticated key encapsulation. +type AuthScheme interface { + Scheme + AuthEncapsulate(pkr PublicKey, sks PrivateKey) (ct, ss []byte, err error) + AuthEncapsulateDeterministically(pkr PublicKey, sks PrivateKey, seed []byte) (ct, ss []byte, err error) + AuthDecapsulate(skr PrivateKey, ct []byte, pks PublicKey) ([]byte, error) +} + +var ( + // ErrTypeMismatch is the error used if types of, for instance, private + // and public keys don't match + ErrTypeMismatch = errors.New("types mismatch") + + // ErrSeedSize is the error used if the provided seed is of the wrong + // size. + ErrSeedSize = errors.New("wrong seed size") + + // ErrPubKeySize is the error used if the provided public key is of + // the wrong size. + ErrPubKeySize = errors.New("wrong size for public key") + + // ErrCiphertextSize is the error used if the provided ciphertext + // is of the wrong size. + ErrCiphertextSize = errors.New("wrong size for ciphertext") + + // ErrPrivKeySize is the error used if the provided private key is of + // the wrong size. + ErrPrivKeySize = errors.New("wrong size for private key") + + // ErrPubKey is the error used if the provided public key is invalid. + ErrPubKey = errors.New("invalid public key") + + // ErrPrivKey is the error used if the provided private key is invalid. + ErrPrivKey = errors.New("invalid private key") + + // ErrCipherText is the error used if the provided ciphertext is invalid. + ErrCipherText = errors.New("invalid ciphertext") +) diff --git a/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber1024/kyber.go b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber1024/kyber.go new file mode 100644 index 00000000000..c2f767cbe72 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber1024/kyber.go @@ -0,0 +1,405 @@ +// Code generated from pkg.templ.go. DO NOT EDIT. + +// Package kyber1024 implements the IND-CCA2 secure key encapsulation mechanism +// Kyber1024.CCAKEM as submitted to round 3 of the NIST PQC competition and +// described in +// +// https://pq-crystals.org/kyber/data/kyber-specification-round3.pdf +package kyber1024 + +import ( + "bytes" + "crypto/subtle" + "io" + + cryptoRand "crypto/rand" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + cpapke "github.com/cloudflare/circl/pke/kyber/kyber1024" +) + +const ( + // Size of seed for NewKeyFromSeed + KeySeedSize = cpapke.KeySeedSize + 32 + + // Size of seed for EncapsulateTo. + EncapsulationSeedSize = 32 + + // Size of the established shared key. + SharedKeySize = 32 + + // Size of the encapsulated shared key. + CiphertextSize = cpapke.CiphertextSize + + // Size of a packed public key. + PublicKeySize = cpapke.PublicKeySize + + // Size of a packed private key. + PrivateKeySize = cpapke.PrivateKeySize + cpapke.PublicKeySize + 64 +) + +// Type of a Kyber1024.CCAKEM public key +type PublicKey struct { + pk *cpapke.PublicKey + + hpk [32]byte // H(pk) +} + +// Type of a Kyber1024.CCAKEM private key +type PrivateKey struct { + sk *cpapke.PrivateKey + pk *cpapke.PublicKey + hpk [32]byte // H(pk) + z [32]byte +} + +// NewKeyFromSeed derives a public/private keypair deterministically +// from the given seed. +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + var sk PrivateKey + var pk PublicKey + + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + + pk.pk, sk.sk = cpapke.NewKeyFromSeed(seed[:cpapke.KeySeedSize]) + sk.pk = pk.pk + copy(sk.z[:], seed[cpapke.KeySeedSize:]) + + // Compute H(pk) + var ppk [cpapke.PublicKeySize]byte + sk.pk.Pack(ppk[:]) + h := sha3.New256() + h.Write(ppk[:]) + h.Read(sk.hpk[:]) + copy(pk.hpk[:], sk.hpk[:]) + + return &pk, &sk +} + +// GenerateKeyPair generates public and private keys using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKeyPair(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [KeySeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := NewKeyFromSeed(seed[:]) + return pk, sk, nil +} + +// EncapsulateTo generates a shared key and ciphertext that contains it +// for the public key using randomness from seed and writes the shared key +// to ss and ciphertext to ct. +// +// Panics if ss, ct or seed are not of length SharedKeySize, CiphertextSize +// and EncapsulationSeedSize respectively. +// +// seed may be nil, in which case crypto/rand.Reader is used to generate one. +func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { + if seed == nil { + seed = make([]byte, EncapsulationSeedSize) + if _, err := cryptoRand.Read(seed[:]); err != nil { + panic(err) + } + } else { + if len(seed) != EncapsulationSeedSize { + panic("seed must be of length EncapsulationSeedSize") + } + } + + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + var m [32]byte + // m = H(seed), the hash of shame + h := sha3.New256() + h.Write(seed) + h.Read(m[:]) + + // (K', r) = G(m ‖ H(pk)) + var kr [64]byte + g := sha3.New512() + g.Write(m[:]) + g.Write(pk.hpk[:]) + g.Read(kr[:]) + + // c = Kyber.CPAPKE.Enc(pk, m, r) + pk.pk.EncryptTo(ct, m[:], kr[32:]) + + // Compute H(c) and put in second slot of kr, which will be (K', H(c)). + h.Reset() + h.Write(ct[:CiphertextSize]) + h.Read(kr[32:]) + + // K = KDF(K' ‖ H(c)) + kdf := sha3.NewShake256() + kdf.Write(kr[:]) + kdf.Read(ss[:SharedKeySize]) +} + +// DecapsulateTo computes the shared key which is encapsulated in ct +// for the private key. +// +// Panics if ct or ss are not of length CiphertextSize and SharedKeySize +// respectively. +func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) { + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + // m' = Kyber.CPAPKE.Dec(sk, ct) + var m2 [32]byte + sk.sk.DecryptTo(m2[:], ct) + + // (K'', r') = G(m' ‖ H(pk)) + var kr2 [64]byte + g := sha3.New512() + g.Write(m2[:]) + g.Write(sk.hpk[:]) + g.Read(kr2[:]) + + // c' = Kyber.CPAPKE.Enc(pk, m', r') + var ct2 [CiphertextSize]byte + sk.pk.EncryptTo(ct2[:], m2[:], kr2[32:]) + + // Compute H(c) and put in second slot of kr2, which will be (K'', H(c)). + h := sha3.New256() + h.Write(ct[:CiphertextSize]) + h.Read(kr2[32:]) + + // Replace K'' by z in the first slot of kr2 if c ≠ c'. + subtle.ConstantTimeCopy( + 1-subtle.ConstantTimeCompare(ct, ct2[:]), + kr2[:32], + sk.z[:], + ) + + // K = KDF(K''/z, H(c)) + kdf := sha3.NewShake256() + kdf.Write(kr2[:]) + kdf.Read(ss) +} + +// Packs sk to buf. +// +// Panics if buf is not of size PrivateKeySize. +func (sk *PrivateKey) Pack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of length PrivateKeySize") + } + + sk.sk.Pack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk.Pack(buf[:cpapke.PublicKeySize]) + buf = buf[cpapke.PublicKeySize:] + copy(buf, sk.hpk[:]) + buf = buf[32:] + copy(buf, sk.z[:]) +} + +// Unpacks sk from buf. +// +// Panics if buf is not of size PrivateKeySize. +func (sk *PrivateKey) Unpack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of length PrivateKeySize") + } + + sk.sk = new(cpapke.PrivateKey) + sk.sk.Unpack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk = new(cpapke.PublicKey) + sk.pk.Unpack(buf[:cpapke.PublicKeySize]) + buf = buf[cpapke.PublicKeySize:] + copy(sk.hpk[:], buf[:32]) + copy(sk.z[:], buf[32:]) +} + +// Packs pk to buf. +// +// Panics if buf is not of size PublicKeySize. +func (pk *PublicKey) Pack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of length PublicKeySize") + } + + pk.pk.Pack(buf) +} + +// Unpacks pk from buf. +// +// Panics if buf is not of size PublicKeySize. +func (pk *PublicKey) Unpack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of length PublicKeySize") + } + + pk.pk = new(cpapke.PublicKey) + pk.pk.Unpack(buf) + + // Compute cached H(pk) + h := sha3.New256() + h.Write(buf) + h.Read(pk.hpk[:]) + +} + +// Boilerplate down below for the KEM scheme API. + +type scheme struct{} + +var sch kem.Scheme = &scheme{} + +// Scheme returns a KEM interface. +func Scheme() kem.Scheme { return sch } + +func (*scheme) Name() string { return "Kyber1024" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SeedSize() int { return KeySeedSize } +func (*scheme) SharedKeySize() int { return SharedKeySize } +func (*scheme) CiphertextSize() int { return CiphertextSize } +func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize } + +func (sk *PrivateKey) Scheme() kem.Scheme { return sch } +func (pk *PublicKey) Scheme() kem.Scheme { return sch } + +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + var ret [PrivateKeySize]byte + sk.Pack(ret[:]) + return ret[:], nil +} + +func (sk *PrivateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*PrivateKey) + if !ok { + return false + } + if sk.pk == nil && oth.pk == nil { + return true + } + if sk.pk == nil || oth.pk == nil { + return false + } + if !bytes.Equal(sk.hpk[:], oth.hpk[:]) || + subtle.ConstantTimeCompare(sk.z[:], oth.z[:]) != 1 { + return false + } + return sk.sk.Equal(oth.sk) +} + +func (pk *PublicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*PublicKey) + if !ok { + return false + } + if pk.pk == nil && oth.pk == nil { + return true + } + if pk.pk == nil || oth.pk == nil { + return false + } + return bytes.Equal(pk.hpk[:], oth.hpk[:]) +} + +func (sk *PrivateKey) Public() kem.PublicKey { + pk := new(PublicKey) + pk.pk = sk.pk + copy(pk.hpk[:], sk.hpk[:]) + return pk +} + +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + var ret [PublicKeySize]byte + pk.Pack(ret[:]) + return ret[:], nil +} + +func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + return GenerateKeyPair(cryptoRand.Reader) +} + +func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + if len(seed) != KeySeedSize { + panic(kem.ErrSeedSize) + } + return NewKeyFromSeed(seed[:]) +} + +func (*scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, nil) + return +} + +func (*scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) ( + ct, ss []byte, err error) { + if len(seed) != EncapsulationSeedSize { + return nil, nil, kem.ErrSeedSize + } + + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, seed) + return +} + +func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != CiphertextSize { + return nil, kem.ErrCiphertextSize + } + + priv, ok := sk.(*PrivateKey) + if !ok { + return nil, kem.ErrTypeMismatch + } + ss := make([]byte, SharedKeySize) + priv.DecapsulateTo(ss, ct) + return ss, nil +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + var ret PublicKey + if len(buf) != PublicKeySize { + return nil, kem.ErrPubKeySize + } + ret.Unpack(buf) + return &ret, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, kem.ErrPrivKeySize + } + var ret PrivateKey + ret.Unpack(buf) + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber512/kyber.go b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber512/kyber.go new file mode 100644 index 00000000000..e60ca0fe58b --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber512/kyber.go @@ -0,0 +1,405 @@ +// Code generated from pkg.templ.go. DO NOT EDIT. + +// Package kyber512 implements the IND-CCA2 secure key encapsulation mechanism +// Kyber512.CCAKEM as submitted to round 3 of the NIST PQC competition and +// described in +// +// https://pq-crystals.org/kyber/data/kyber-specification-round3.pdf +package kyber512 + +import ( + "bytes" + "crypto/subtle" + "io" + + cryptoRand "crypto/rand" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + cpapke "github.com/cloudflare/circl/pke/kyber/kyber512" +) + +const ( + // Size of seed for NewKeyFromSeed + KeySeedSize = cpapke.KeySeedSize + 32 + + // Size of seed for EncapsulateTo. + EncapsulationSeedSize = 32 + + // Size of the established shared key. + SharedKeySize = 32 + + // Size of the encapsulated shared key. + CiphertextSize = cpapke.CiphertextSize + + // Size of a packed public key. + PublicKeySize = cpapke.PublicKeySize + + // Size of a packed private key. + PrivateKeySize = cpapke.PrivateKeySize + cpapke.PublicKeySize + 64 +) + +// Type of a Kyber512.CCAKEM public key +type PublicKey struct { + pk *cpapke.PublicKey + + hpk [32]byte // H(pk) +} + +// Type of a Kyber512.CCAKEM private key +type PrivateKey struct { + sk *cpapke.PrivateKey + pk *cpapke.PublicKey + hpk [32]byte // H(pk) + z [32]byte +} + +// NewKeyFromSeed derives a public/private keypair deterministically +// from the given seed. +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + var sk PrivateKey + var pk PublicKey + + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + + pk.pk, sk.sk = cpapke.NewKeyFromSeed(seed[:cpapke.KeySeedSize]) + sk.pk = pk.pk + copy(sk.z[:], seed[cpapke.KeySeedSize:]) + + // Compute H(pk) + var ppk [cpapke.PublicKeySize]byte + sk.pk.Pack(ppk[:]) + h := sha3.New256() + h.Write(ppk[:]) + h.Read(sk.hpk[:]) + copy(pk.hpk[:], sk.hpk[:]) + + return &pk, &sk +} + +// GenerateKeyPair generates public and private keys using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKeyPair(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [KeySeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := NewKeyFromSeed(seed[:]) + return pk, sk, nil +} + +// EncapsulateTo generates a shared key and ciphertext that contains it +// for the public key using randomness from seed and writes the shared key +// to ss and ciphertext to ct. +// +// Panics if ss, ct or seed are not of length SharedKeySize, CiphertextSize +// and EncapsulationSeedSize respectively. +// +// seed may be nil, in which case crypto/rand.Reader is used to generate one. +func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { + if seed == nil { + seed = make([]byte, EncapsulationSeedSize) + if _, err := cryptoRand.Read(seed[:]); err != nil { + panic(err) + } + } else { + if len(seed) != EncapsulationSeedSize { + panic("seed must be of length EncapsulationSeedSize") + } + } + + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + var m [32]byte + // m = H(seed), the hash of shame + h := sha3.New256() + h.Write(seed) + h.Read(m[:]) + + // (K', r) = G(m ‖ H(pk)) + var kr [64]byte + g := sha3.New512() + g.Write(m[:]) + g.Write(pk.hpk[:]) + g.Read(kr[:]) + + // c = Kyber.CPAPKE.Enc(pk, m, r) + pk.pk.EncryptTo(ct, m[:], kr[32:]) + + // Compute H(c) and put in second slot of kr, which will be (K', H(c)). + h.Reset() + h.Write(ct[:CiphertextSize]) + h.Read(kr[32:]) + + // K = KDF(K' ‖ H(c)) + kdf := sha3.NewShake256() + kdf.Write(kr[:]) + kdf.Read(ss[:SharedKeySize]) +} + +// DecapsulateTo computes the shared key which is encapsulated in ct +// for the private key. +// +// Panics if ct or ss are not of length CiphertextSize and SharedKeySize +// respectively. +func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) { + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + // m' = Kyber.CPAPKE.Dec(sk, ct) + var m2 [32]byte + sk.sk.DecryptTo(m2[:], ct) + + // (K'', r') = G(m' ‖ H(pk)) + var kr2 [64]byte + g := sha3.New512() + g.Write(m2[:]) + g.Write(sk.hpk[:]) + g.Read(kr2[:]) + + // c' = Kyber.CPAPKE.Enc(pk, m', r') + var ct2 [CiphertextSize]byte + sk.pk.EncryptTo(ct2[:], m2[:], kr2[32:]) + + // Compute H(c) and put in second slot of kr2, which will be (K'', H(c)). + h := sha3.New256() + h.Write(ct[:CiphertextSize]) + h.Read(kr2[32:]) + + // Replace K'' by z in the first slot of kr2 if c ≠ c'. + subtle.ConstantTimeCopy( + 1-subtle.ConstantTimeCompare(ct, ct2[:]), + kr2[:32], + sk.z[:], + ) + + // K = KDF(K''/z, H(c)) + kdf := sha3.NewShake256() + kdf.Write(kr2[:]) + kdf.Read(ss) +} + +// Packs sk to buf. +// +// Panics if buf is not of size PrivateKeySize. +func (sk *PrivateKey) Pack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of length PrivateKeySize") + } + + sk.sk.Pack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk.Pack(buf[:cpapke.PublicKeySize]) + buf = buf[cpapke.PublicKeySize:] + copy(buf, sk.hpk[:]) + buf = buf[32:] + copy(buf, sk.z[:]) +} + +// Unpacks sk from buf. +// +// Panics if buf is not of size PrivateKeySize. +func (sk *PrivateKey) Unpack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of length PrivateKeySize") + } + + sk.sk = new(cpapke.PrivateKey) + sk.sk.Unpack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk = new(cpapke.PublicKey) + sk.pk.Unpack(buf[:cpapke.PublicKeySize]) + buf = buf[cpapke.PublicKeySize:] + copy(sk.hpk[:], buf[:32]) + copy(sk.z[:], buf[32:]) +} + +// Packs pk to buf. +// +// Panics if buf is not of size PublicKeySize. +func (pk *PublicKey) Pack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of length PublicKeySize") + } + + pk.pk.Pack(buf) +} + +// Unpacks pk from buf. +// +// Panics if buf is not of size PublicKeySize. +func (pk *PublicKey) Unpack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of length PublicKeySize") + } + + pk.pk = new(cpapke.PublicKey) + pk.pk.Unpack(buf) + + // Compute cached H(pk) + h := sha3.New256() + h.Write(buf) + h.Read(pk.hpk[:]) + +} + +// Boilerplate down below for the KEM scheme API. + +type scheme struct{} + +var sch kem.Scheme = &scheme{} + +// Scheme returns a KEM interface. +func Scheme() kem.Scheme { return sch } + +func (*scheme) Name() string { return "Kyber512" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SeedSize() int { return KeySeedSize } +func (*scheme) SharedKeySize() int { return SharedKeySize } +func (*scheme) CiphertextSize() int { return CiphertextSize } +func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize } + +func (sk *PrivateKey) Scheme() kem.Scheme { return sch } +func (pk *PublicKey) Scheme() kem.Scheme { return sch } + +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + var ret [PrivateKeySize]byte + sk.Pack(ret[:]) + return ret[:], nil +} + +func (sk *PrivateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*PrivateKey) + if !ok { + return false + } + if sk.pk == nil && oth.pk == nil { + return true + } + if sk.pk == nil || oth.pk == nil { + return false + } + if !bytes.Equal(sk.hpk[:], oth.hpk[:]) || + subtle.ConstantTimeCompare(sk.z[:], oth.z[:]) != 1 { + return false + } + return sk.sk.Equal(oth.sk) +} + +func (pk *PublicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*PublicKey) + if !ok { + return false + } + if pk.pk == nil && oth.pk == nil { + return true + } + if pk.pk == nil || oth.pk == nil { + return false + } + return bytes.Equal(pk.hpk[:], oth.hpk[:]) +} + +func (sk *PrivateKey) Public() kem.PublicKey { + pk := new(PublicKey) + pk.pk = sk.pk + copy(pk.hpk[:], sk.hpk[:]) + return pk +} + +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + var ret [PublicKeySize]byte + pk.Pack(ret[:]) + return ret[:], nil +} + +func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + return GenerateKeyPair(cryptoRand.Reader) +} + +func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + if len(seed) != KeySeedSize { + panic(kem.ErrSeedSize) + } + return NewKeyFromSeed(seed[:]) +} + +func (*scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, nil) + return +} + +func (*scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) ( + ct, ss []byte, err error) { + if len(seed) != EncapsulationSeedSize { + return nil, nil, kem.ErrSeedSize + } + + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, seed) + return +} + +func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != CiphertextSize { + return nil, kem.ErrCiphertextSize + } + + priv, ok := sk.(*PrivateKey) + if !ok { + return nil, kem.ErrTypeMismatch + } + ss := make([]byte, SharedKeySize) + priv.DecapsulateTo(ss, ct) + return ss, nil +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + var ret PublicKey + if len(buf) != PublicKeySize { + return nil, kem.ErrPubKeySize + } + ret.Unpack(buf) + return &ret, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, kem.ErrPrivKeySize + } + var ret PrivateKey + ret.Unpack(buf) + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber768/kyber.go b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber768/kyber.go new file mode 100644 index 00000000000..0e03c40ddd6 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber768/kyber.go @@ -0,0 +1,405 @@ +// Code generated from pkg.templ.go. DO NOT EDIT. + +// Package kyber768 implements the IND-CCA2 secure key encapsulation mechanism +// Kyber768.CCAKEM as submitted to round 3 of the NIST PQC competition and +// described in +// +// https://pq-crystals.org/kyber/data/kyber-specification-round3.pdf +package kyber768 + +import ( + "bytes" + "crypto/subtle" + "io" + + cryptoRand "crypto/rand" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + cpapke "github.com/cloudflare/circl/pke/kyber/kyber768" +) + +const ( + // Size of seed for NewKeyFromSeed + KeySeedSize = cpapke.KeySeedSize + 32 + + // Size of seed for EncapsulateTo. + EncapsulationSeedSize = 32 + + // Size of the established shared key. + SharedKeySize = 32 + + // Size of the encapsulated shared key. + CiphertextSize = cpapke.CiphertextSize + + // Size of a packed public key. + PublicKeySize = cpapke.PublicKeySize + + // Size of a packed private key. + PrivateKeySize = cpapke.PrivateKeySize + cpapke.PublicKeySize + 64 +) + +// Type of a Kyber768.CCAKEM public key +type PublicKey struct { + pk *cpapke.PublicKey + + hpk [32]byte // H(pk) +} + +// Type of a Kyber768.CCAKEM private key +type PrivateKey struct { + sk *cpapke.PrivateKey + pk *cpapke.PublicKey + hpk [32]byte // H(pk) + z [32]byte +} + +// NewKeyFromSeed derives a public/private keypair deterministically +// from the given seed. +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + var sk PrivateKey + var pk PublicKey + + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + + pk.pk, sk.sk = cpapke.NewKeyFromSeed(seed[:cpapke.KeySeedSize]) + sk.pk = pk.pk + copy(sk.z[:], seed[cpapke.KeySeedSize:]) + + // Compute H(pk) + var ppk [cpapke.PublicKeySize]byte + sk.pk.Pack(ppk[:]) + h := sha3.New256() + h.Write(ppk[:]) + h.Read(sk.hpk[:]) + copy(pk.hpk[:], sk.hpk[:]) + + return &pk, &sk +} + +// GenerateKeyPair generates public and private keys using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKeyPair(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [KeySeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := NewKeyFromSeed(seed[:]) + return pk, sk, nil +} + +// EncapsulateTo generates a shared key and ciphertext that contains it +// for the public key using randomness from seed and writes the shared key +// to ss and ciphertext to ct. +// +// Panics if ss, ct or seed are not of length SharedKeySize, CiphertextSize +// and EncapsulationSeedSize respectively. +// +// seed may be nil, in which case crypto/rand.Reader is used to generate one. +func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { + if seed == nil { + seed = make([]byte, EncapsulationSeedSize) + if _, err := cryptoRand.Read(seed[:]); err != nil { + panic(err) + } + } else { + if len(seed) != EncapsulationSeedSize { + panic("seed must be of length EncapsulationSeedSize") + } + } + + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + var m [32]byte + // m = H(seed), the hash of shame + h := sha3.New256() + h.Write(seed) + h.Read(m[:]) + + // (K', r) = G(m ‖ H(pk)) + var kr [64]byte + g := sha3.New512() + g.Write(m[:]) + g.Write(pk.hpk[:]) + g.Read(kr[:]) + + // c = Kyber.CPAPKE.Enc(pk, m, r) + pk.pk.EncryptTo(ct, m[:], kr[32:]) + + // Compute H(c) and put in second slot of kr, which will be (K', H(c)). + h.Reset() + h.Write(ct[:CiphertextSize]) + h.Read(kr[32:]) + + // K = KDF(K' ‖ H(c)) + kdf := sha3.NewShake256() + kdf.Write(kr[:]) + kdf.Read(ss[:SharedKeySize]) +} + +// DecapsulateTo computes the shared key which is encapsulated in ct +// for the private key. +// +// Panics if ct or ss are not of length CiphertextSize and SharedKeySize +// respectively. +func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) { + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + // m' = Kyber.CPAPKE.Dec(sk, ct) + var m2 [32]byte + sk.sk.DecryptTo(m2[:], ct) + + // (K'', r') = G(m' ‖ H(pk)) + var kr2 [64]byte + g := sha3.New512() + g.Write(m2[:]) + g.Write(sk.hpk[:]) + g.Read(kr2[:]) + + // c' = Kyber.CPAPKE.Enc(pk, m', r') + var ct2 [CiphertextSize]byte + sk.pk.EncryptTo(ct2[:], m2[:], kr2[32:]) + + // Compute H(c) and put in second slot of kr2, which will be (K'', H(c)). + h := sha3.New256() + h.Write(ct[:CiphertextSize]) + h.Read(kr2[32:]) + + // Replace K'' by z in the first slot of kr2 if c ≠ c'. + subtle.ConstantTimeCopy( + 1-subtle.ConstantTimeCompare(ct, ct2[:]), + kr2[:32], + sk.z[:], + ) + + // K = KDF(K''/z, H(c)) + kdf := sha3.NewShake256() + kdf.Write(kr2[:]) + kdf.Read(ss) +} + +// Packs sk to buf. +// +// Panics if buf is not of size PrivateKeySize. +func (sk *PrivateKey) Pack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of length PrivateKeySize") + } + + sk.sk.Pack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk.Pack(buf[:cpapke.PublicKeySize]) + buf = buf[cpapke.PublicKeySize:] + copy(buf, sk.hpk[:]) + buf = buf[32:] + copy(buf, sk.z[:]) +} + +// Unpacks sk from buf. +// +// Panics if buf is not of size PrivateKeySize. +func (sk *PrivateKey) Unpack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of length PrivateKeySize") + } + + sk.sk = new(cpapke.PrivateKey) + sk.sk.Unpack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk = new(cpapke.PublicKey) + sk.pk.Unpack(buf[:cpapke.PublicKeySize]) + buf = buf[cpapke.PublicKeySize:] + copy(sk.hpk[:], buf[:32]) + copy(sk.z[:], buf[32:]) +} + +// Packs pk to buf. +// +// Panics if buf is not of size PublicKeySize. +func (pk *PublicKey) Pack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of length PublicKeySize") + } + + pk.pk.Pack(buf) +} + +// Unpacks pk from buf. +// +// Panics if buf is not of size PublicKeySize. +func (pk *PublicKey) Unpack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of length PublicKeySize") + } + + pk.pk = new(cpapke.PublicKey) + pk.pk.Unpack(buf) + + // Compute cached H(pk) + h := sha3.New256() + h.Write(buf) + h.Read(pk.hpk[:]) + +} + +// Boilerplate down below for the KEM scheme API. + +type scheme struct{} + +var sch kem.Scheme = &scheme{} + +// Scheme returns a KEM interface. +func Scheme() kem.Scheme { return sch } + +func (*scheme) Name() string { return "Kyber768" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SeedSize() int { return KeySeedSize } +func (*scheme) SharedKeySize() int { return SharedKeySize } +func (*scheme) CiphertextSize() int { return CiphertextSize } +func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize } + +func (sk *PrivateKey) Scheme() kem.Scheme { return sch } +func (pk *PublicKey) Scheme() kem.Scheme { return sch } + +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + var ret [PrivateKeySize]byte + sk.Pack(ret[:]) + return ret[:], nil +} + +func (sk *PrivateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*PrivateKey) + if !ok { + return false + } + if sk.pk == nil && oth.pk == nil { + return true + } + if sk.pk == nil || oth.pk == nil { + return false + } + if !bytes.Equal(sk.hpk[:], oth.hpk[:]) || + subtle.ConstantTimeCompare(sk.z[:], oth.z[:]) != 1 { + return false + } + return sk.sk.Equal(oth.sk) +} + +func (pk *PublicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*PublicKey) + if !ok { + return false + } + if pk.pk == nil && oth.pk == nil { + return true + } + if pk.pk == nil || oth.pk == nil { + return false + } + return bytes.Equal(pk.hpk[:], oth.hpk[:]) +} + +func (sk *PrivateKey) Public() kem.PublicKey { + pk := new(PublicKey) + pk.pk = sk.pk + copy(pk.hpk[:], sk.hpk[:]) + return pk +} + +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + var ret [PublicKeySize]byte + pk.Pack(ret[:]) + return ret[:], nil +} + +func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + return GenerateKeyPair(cryptoRand.Reader) +} + +func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + if len(seed) != KeySeedSize { + panic(kem.ErrSeedSize) + } + return NewKeyFromSeed(seed[:]) +} + +func (*scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, nil) + return +} + +func (*scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) ( + ct, ss []byte, err error) { + if len(seed) != EncapsulationSeedSize { + return nil, nil, kem.ErrSeedSize + } + + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, seed) + return +} + +func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != CiphertextSize { + return nil, kem.ErrCiphertextSize + } + + priv, ok := sk.(*PrivateKey) + if !ok { + return nil, kem.ErrTypeMismatch + } + ss := make([]byte, SharedKeySize) + priv.DecapsulateTo(ss, ct) + return ss, nil +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + var ret PublicKey + if len(buf) != PublicKeySize { + return nil, kem.ErrPubKeySize + } + ret.Unpack(buf) + return &ret, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, kem.ErrPrivKeySize + } + var ret PrivateKey + ret.Unpack(buf) + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/kem/mlkem/mlkem768/kyber.go b/src/vendor/github.com/cloudflare/circl/kem/mlkem/mlkem768/kyber.go new file mode 100644 index 00000000000..afa48315671 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/mlkem/mlkem768/kyber.go @@ -0,0 +1,407 @@ +// Code generated from pkg.templ.go. DO NOT EDIT. + +// Package mlkem768 implements the IND-CCA2 secure key encapsulation mechanism +// ML-KEM-768 as defined in FIPS203. +package mlkem768 + +import ( + "bytes" + "crypto/subtle" + "io" + + cryptoRand "crypto/rand" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + cpapke "github.com/cloudflare/circl/pke/kyber/kyber768" +) + +const ( + // Size of seed for NewKeyFromSeed + KeySeedSize = cpapke.KeySeedSize + 32 + + // Size of seed for EncapsulateTo. + EncapsulationSeedSize = 32 + + // Size of the established shared key. + SharedKeySize = 32 + + // Size of the encapsulated shared key. + CiphertextSize = cpapke.CiphertextSize + + // Size of a packed public key. + PublicKeySize = cpapke.PublicKeySize + + // Size of a packed private key. + PrivateKeySize = cpapke.PrivateKeySize + cpapke.PublicKeySize + 64 +) + +// Type of a ML-KEM-768 public key +type PublicKey struct { + pk *cpapke.PublicKey + + hpk [32]byte // H(pk) +} + +// Type of a ML-KEM-768 private key +type PrivateKey struct { + sk *cpapke.PrivateKey + pk *cpapke.PublicKey + hpk [32]byte // H(pk) + z [32]byte +} + +// NewKeyFromSeed derives a public/private keypair deterministically +// from the given seed. +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + var sk PrivateKey + var pk PublicKey + + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + + pk.pk, sk.sk = cpapke.NewKeyFromSeedMLKEM(seed[:cpapke.KeySeedSize]) + sk.pk = pk.pk + copy(sk.z[:], seed[cpapke.KeySeedSize:]) + + // Compute H(pk) + var ppk [cpapke.PublicKeySize]byte + sk.pk.Pack(ppk[:]) + h := sha3.New256() + h.Write(ppk[:]) + h.Read(sk.hpk[:]) + copy(pk.hpk[:], sk.hpk[:]) + + return &pk, &sk +} + +// GenerateKeyPair generates public and private keys using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKeyPair(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [KeySeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := NewKeyFromSeed(seed[:]) + return pk, sk, nil +} + +// EncapsulateTo generates a shared key and ciphertext that contains it +// for the public key using randomness from seed and writes the shared key +// to ss and ciphertext to ct. +// +// Panics if ss, ct or seed are not of length SharedKeySize, CiphertextSize +// and EncapsulationSeedSize respectively. +// +// seed may be nil, in which case crypto/rand.Reader is used to generate one. +func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { + if seed == nil { + seed = make([]byte, EncapsulationSeedSize) + if _, err := cryptoRand.Read(seed[:]); err != nil { + panic(err) + } + } else { + if len(seed) != EncapsulationSeedSize { + panic("seed must be of length EncapsulationSeedSize") + } + } + + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + var m [32]byte + copy(m[:], seed) + + // (K', r) = G(m ‖ H(pk)) + var kr [64]byte + g := sha3.New512() + g.Write(m[:]) + g.Write(pk.hpk[:]) + g.Read(kr[:]) + + // c = Kyber.CPAPKE.Enc(pk, m, r) + pk.pk.EncryptTo(ct, m[:], kr[32:]) + + copy(ss, kr[:SharedKeySize]) +} + +// DecapsulateTo computes the shared key which is encapsulated in ct +// for the private key. +// +// Panics if ct or ss are not of length CiphertextSize and SharedKeySize +// respectively. +func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) { + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + + if len(ss) != SharedKeySize { + panic("ss must be of length SharedKeySize") + } + + // m' = Kyber.CPAPKE.Dec(sk, ct) + var m2 [32]byte + sk.sk.DecryptTo(m2[:], ct) + + // (K'', r') = G(m' ‖ H(pk)) + var kr2 [64]byte + g := sha3.New512() + g.Write(m2[:]) + g.Write(sk.hpk[:]) + g.Read(kr2[:]) + + // c' = Kyber.CPAPKE.Enc(pk, m', r') + var ct2 [CiphertextSize]byte + sk.pk.EncryptTo(ct2[:], m2[:], kr2[32:]) + + var ss2 [SharedKeySize]byte + + // Compute shared secret in case of rejection: ss₂ = PRF(z ‖ c) + prf := sha3.NewShake256() + prf.Write(sk.z[:]) + prf.Write(ct[:CiphertextSize]) + prf.Read(ss2[:]) + + // Set ss2 to the real shared secret if c = c'. + subtle.ConstantTimeCopy( + subtle.ConstantTimeCompare(ct, ct2[:]), + ss2[:], + kr2[:SharedKeySize], + ) + + copy(ss, ss2[:]) +} + +// Packs sk to buf. +// +// Panics if buf is not of size PrivateKeySize. +func (sk *PrivateKey) Pack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of length PrivateKeySize") + } + + sk.sk.Pack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk.Pack(buf[:cpapke.PublicKeySize]) + buf = buf[cpapke.PublicKeySize:] + copy(buf, sk.hpk[:]) + buf = buf[32:] + copy(buf, sk.z[:]) +} + +// Unpacks sk from buf. +// +// Panics if buf is not of size PrivateKeySize. +// +// Returns an error if buf is not of size PrivateKeySize, or private key +// doesn't pass the ML-KEM decapsulation key check. +func (sk *PrivateKey) Unpack(buf []byte) error { + if len(buf) != PrivateKeySize { + return kem.ErrPrivKeySize + } + + sk.sk = new(cpapke.PrivateKey) + sk.sk.Unpack(buf[:cpapke.PrivateKeySize]) + buf = buf[cpapke.PrivateKeySize:] + sk.pk = new(cpapke.PublicKey) + sk.pk.Unpack(buf[:cpapke.PublicKeySize]) + var hpk [32]byte + h := sha3.New256() + h.Write(buf[:cpapke.PublicKeySize]) + h.Read(hpk[:]) + buf = buf[cpapke.PublicKeySize:] + copy(sk.hpk[:], buf[:32]) + copy(sk.z[:], buf[32:]) + if !bytes.Equal(hpk[:], sk.hpk[:]) { + return kem.ErrPrivKey + } + return nil +} + +// Packs pk to buf. +// +// Panics if buf is not of size PublicKeySize. +func (pk *PublicKey) Pack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of length PublicKeySize") + } + + pk.pk.Pack(buf) +} + +// Unpacks pk from buf. +// +// Returns an error if buf is not of size PublicKeySize, or the public key +// is not normalized. +func (pk *PublicKey) Unpack(buf []byte) error { + if len(buf) != PublicKeySize { + return kem.ErrPubKeySize + } + + pk.pk = new(cpapke.PublicKey) + if err := pk.pk.UnpackMLKEM(buf); err != nil { + return err + } + + // Compute cached H(pk) + h := sha3.New256() + h.Write(buf) + h.Read(pk.hpk[:]) + + return nil +} + +// Boilerplate down below for the KEM scheme API. + +type scheme struct{} + +var sch kem.Scheme = &scheme{} + +// Scheme returns a KEM interface. +func Scheme() kem.Scheme { return sch } + +func (*scheme) Name() string { return "ML-KEM-768" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SeedSize() int { return KeySeedSize } +func (*scheme) SharedKeySize() int { return SharedKeySize } +func (*scheme) CiphertextSize() int { return CiphertextSize } +func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize } + +func (sk *PrivateKey) Scheme() kem.Scheme { return sch } +func (pk *PublicKey) Scheme() kem.Scheme { return sch } + +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + var ret [PrivateKeySize]byte + sk.Pack(ret[:]) + return ret[:], nil +} + +func (sk *PrivateKey) Equal(other kem.PrivateKey) bool { + oth, ok := other.(*PrivateKey) + if !ok { + return false + } + if sk.pk == nil && oth.pk == nil { + return true + } + if sk.pk == nil || oth.pk == nil { + return false + } + if !bytes.Equal(sk.hpk[:], oth.hpk[:]) || + subtle.ConstantTimeCompare(sk.z[:], oth.z[:]) != 1 { + return false + } + return sk.sk.Equal(oth.sk) +} + +func (pk *PublicKey) Equal(other kem.PublicKey) bool { + oth, ok := other.(*PublicKey) + if !ok { + return false + } + if pk.pk == nil && oth.pk == nil { + return true + } + if pk.pk == nil || oth.pk == nil { + return false + } + return bytes.Equal(pk.hpk[:], oth.hpk[:]) +} + +func (sk *PrivateKey) Public() kem.PublicKey { + pk := new(PublicKey) + pk.pk = sk.pk + copy(pk.hpk[:], sk.hpk[:]) + return pk +} + +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + var ret [PublicKeySize]byte + pk.Pack(ret[:]) + return ret[:], nil +} + +func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { + return GenerateKeyPair(cryptoRand.Reader) +} + +func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { + if len(seed) != KeySeedSize { + panic(kem.ErrSeedSize) + } + return NewKeyFromSeed(seed[:]) +} + +func (*scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, nil) + return +} + +func (*scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) ( + ct, ss []byte, err error) { + if len(seed) != EncapsulationSeedSize { + return nil, nil, kem.ErrSeedSize + } + + ct = make([]byte, CiphertextSize) + ss = make([]byte, SharedKeySize) + + pub, ok := pk.(*PublicKey) + if !ok { + return nil, nil, kem.ErrTypeMismatch + } + pub.EncapsulateTo(ct, ss, seed) + return +} + +func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { + if len(ct) != CiphertextSize { + return nil, kem.ErrCiphertextSize + } + + priv, ok := sk.(*PrivateKey) + if !ok { + return nil, kem.ErrTypeMismatch + } + ss := make([]byte, SharedKeySize) + priv.DecapsulateTo(ss, ct) + return ss, nil +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + var ret PublicKey + if err := ret.Unpack(buf); err != nil { + return nil, err + } + return &ret, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, kem.ErrPrivKeySize + } + var ret PrivateKey + if err := ret.Unpack(buf); err != nil { + return nil, err + } + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/math/fp25519/fp.go b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp.go new file mode 100644 index 00000000000..57a50ff5e9b --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp.go @@ -0,0 +1,205 @@ +// Package fp25519 provides prime field arithmetic over GF(2^255-19). +package fp25519 + +import ( + "errors" + + "github.com/cloudflare/circl/internal/conv" +) + +// Size in bytes of an element. +const Size = 32 + +// Elt is a prime field element. +type Elt [Size]byte + +func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) } + +// p is the prime modulus 2^255-19. +var p = Elt{ + 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, +} + +// P returns the prime modulus 2^255-19. +func P() Elt { return p } + +// ToBytes stores in b the little-endian byte representation of x. +func ToBytes(b []byte, x *Elt) error { + if len(b) != Size { + return errors.New("wrong size") + } + Modp(x) + copy(b, x[:]) + return nil +} + +// IsZero returns true if x is equal to 0. +func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} } + +// SetOne assigns x=1. +func SetOne(x *Elt) { *x = Elt{}; x[0] = 1 } + +// Neg calculates z = -x. +func Neg(z, x *Elt) { Sub(z, &p, x) } + +// InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue, which is +// indicated by returning isQR = true. Otherwise, when x/y is a quadratic +// non-residue, z will have an undetermined value and isQR = false. +func InvSqrt(z, x, y *Elt) (isQR bool) { + sqrtMinusOne := &Elt{ + 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4, + 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f, + 0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b, + 0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b, + } + t0, t1, t2, t3 := &Elt{}, &Elt{}, &Elt{}, &Elt{} + + Mul(t0, x, y) // t0 = u*v + Sqr(t1, y) // t1 = v^2 + Mul(t2, t0, t1) // t2 = u*v^3 + Sqr(t0, t1) // t0 = v^4 + Mul(t1, t0, t2) // t1 = u*v^7 + + var Tab [4]*Elt + Tab[0] = &Elt{} + Tab[1] = &Elt{} + Tab[2] = t3 + Tab[3] = t1 + + *Tab[0] = *t1 + Sqr(Tab[0], Tab[0]) + Sqr(Tab[1], Tab[0]) + Sqr(Tab[1], Tab[1]) + Mul(Tab[1], Tab[1], Tab[3]) + Mul(Tab[0], Tab[0], Tab[1]) + Sqr(Tab[0], Tab[0]) + Mul(Tab[0], Tab[0], Tab[1]) + Sqr(Tab[1], Tab[0]) + for i := 0; i < 4; i++ { + Sqr(Tab[1], Tab[1]) + } + Mul(Tab[1], Tab[1], Tab[0]) + Sqr(Tab[2], Tab[1]) + for i := 0; i < 4; i++ { + Sqr(Tab[2], Tab[2]) + } + Mul(Tab[2], Tab[2], Tab[0]) + Sqr(Tab[1], Tab[2]) + for i := 0; i < 14; i++ { + Sqr(Tab[1], Tab[1]) + } + Mul(Tab[1], Tab[1], Tab[2]) + Sqr(Tab[2], Tab[1]) + for i := 0; i < 29; i++ { + Sqr(Tab[2], Tab[2]) + } + Mul(Tab[2], Tab[2], Tab[1]) + Sqr(Tab[1], Tab[2]) + for i := 0; i < 59; i++ { + Sqr(Tab[1], Tab[1]) + } + Mul(Tab[1], Tab[1], Tab[2]) + for i := 0; i < 5; i++ { + Sqr(Tab[1], Tab[1]) + } + Mul(Tab[1], Tab[1], Tab[0]) + Sqr(Tab[2], Tab[1]) + for i := 0; i < 124; i++ { + Sqr(Tab[2], Tab[2]) + } + Mul(Tab[2], Tab[2], Tab[1]) + Sqr(Tab[2], Tab[2]) + Sqr(Tab[2], Tab[2]) + Mul(Tab[2], Tab[2], Tab[3]) + + Mul(z, t3, t2) // z = xy^(p+3)/8 = xy^3*(xy^7)^(p-5)/8 + // Checking whether y z^2 == x + Sqr(t0, z) // t0 = z^2 + Mul(t0, t0, y) // t0 = yz^2 + Sub(t1, t0, x) // t1 = t0-u + Add(t2, t0, x) // t2 = t0+u + if IsZero(t1) { + return true + } else if IsZero(t2) { + Mul(z, z, sqrtMinusOne) // z = z*sqrt(-1) + return true + } else { + return false + } +} + +// Inv calculates z = 1/x mod p. +func Inv(z, x *Elt) { + x0, x1, x2 := &Elt{}, &Elt{}, &Elt{} + Sqr(x1, x) + Sqr(x0, x1) + Sqr(x0, x0) + Mul(x0, x0, x) + Mul(z, x0, x1) + Sqr(x1, z) + Mul(x0, x0, x1) + Sqr(x1, x0) + for i := 0; i < 4; i++ { + Sqr(x1, x1) + } + Mul(x0, x0, x1) + Sqr(x1, x0) + for i := 0; i < 9; i++ { + Sqr(x1, x1) + } + Mul(x1, x1, x0) + Sqr(x2, x1) + for i := 0; i < 19; i++ { + Sqr(x2, x2) + } + Mul(x2, x2, x1) + for i := 0; i < 10; i++ { + Sqr(x2, x2) + } + Mul(x2, x2, x0) + Sqr(x0, x2) + for i := 0; i < 49; i++ { + Sqr(x0, x0) + } + Mul(x0, x0, x2) + Sqr(x1, x0) + for i := 0; i < 99; i++ { + Sqr(x1, x1) + } + Mul(x1, x1, x0) + for i := 0; i < 50; i++ { + Sqr(x1, x1) + } + Mul(x1, x1, x2) + for i := 0; i < 5; i++ { + Sqr(x1, x1) + } + Mul(z, z, x1) +} + +// Cmov assigns y to x if n is 1. +func Cmov(x, y *Elt, n uint) { cmov(x, y, n) } + +// Cswap interchanges x and y if n is 1. +func Cswap(x, y *Elt, n uint) { cswap(x, y, n) } + +// Add calculates z = x+y mod p. +func Add(z, x, y *Elt) { add(z, x, y) } + +// Sub calculates z = x-y mod p. +func Sub(z, x, y *Elt) { sub(z, x, y) } + +// AddSub calculates (x,y) = (x+y mod p, x-y mod p). +func AddSub(x, y *Elt) { addsub(x, y) } + +// Mul calculates z = x*y mod p. +func Mul(z, x, y *Elt) { mul(z, x, y) } + +// Sqr calculates z = x^2 mod p. +func Sqr(z, x *Elt) { sqr(z, x) } + +// Modp ensures that z is between [0,p-1]. +func Modp(z *Elt) { modp(z) } diff --git a/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go new file mode 100644 index 00000000000..057f0d2803f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go @@ -0,0 +1,45 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package fp25519 + +import ( + "golang.org/x/sys/cpu" +) + +var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX + +var _ = hasBmi2Adx + +func cmov(x, y *Elt, n uint) { cmovAmd64(x, y, n) } +func cswap(x, y *Elt, n uint) { cswapAmd64(x, y, n) } +func add(z, x, y *Elt) { addAmd64(z, x, y) } +func sub(z, x, y *Elt) { subAmd64(z, x, y) } +func addsub(x, y *Elt) { addsubAmd64(x, y) } +func mul(z, x, y *Elt) { mulAmd64(z, x, y) } +func sqr(z, x *Elt) { sqrAmd64(z, x) } +func modp(z *Elt) { modpAmd64(z) } + +//go:noescape +func cmovAmd64(x, y *Elt, n uint) + +//go:noescape +func cswapAmd64(x, y *Elt, n uint) + +//go:noescape +func addAmd64(z, x, y *Elt) + +//go:noescape +func subAmd64(z, x, y *Elt) + +//go:noescape +func addsubAmd64(x, y *Elt) + +//go:noescape +func mulAmd64(z, x, y *Elt) + +//go:noescape +func sqrAmd64(z, x *Elt) + +//go:noescape +func modpAmd64(z *Elt) diff --git a/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h new file mode 100644 index 00000000000..b884b584ab3 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h @@ -0,0 +1,351 @@ +// This code was imported from https://github.com/armfazh/rfc7748_precomputed + +// CHECK_BMI2ADX triggers bmi2adx if supported, +// otherwise it fallbacks to legacy code. +#define CHECK_BMI2ADX(label, legacy, bmi2adx) \ + CMPB ·hasBmi2Adx(SB), $0 \ + JE label \ + bmi2adx \ + RET \ + label: \ + legacy \ + RET + +// cselect is a conditional move +// if b=1: it copies y into x; +// if b=0: x remains with the same value; +// if b<> 0,1: undefined. +// Uses: AX, DX, FLAGS +// Instr: x86_64, cmov +#define cselect(x,y,b) \ + TESTQ b, b \ + MOVQ 0+x, AX; MOVQ 0+y, DX; CMOVQNE DX, AX; MOVQ AX, 0+x; \ + MOVQ 8+x, AX; MOVQ 8+y, DX; CMOVQNE DX, AX; MOVQ AX, 8+x; \ + MOVQ 16+x, AX; MOVQ 16+y, DX; CMOVQNE DX, AX; MOVQ AX, 16+x; \ + MOVQ 24+x, AX; MOVQ 24+y, DX; CMOVQNE DX, AX; MOVQ AX, 24+x; + +// cswap is a conditional swap +// if b=1: x,y <- y,x; +// if b=0: x,y remain with the same values; +// if b<> 0,1: undefined. +// Uses: AX, DX, R8, FLAGS +// Instr: x86_64, cmov +#define cswap(x,y,b) \ + TESTQ b, b \ + MOVQ 0+x, AX; MOVQ AX, R8; MOVQ 0+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 0+x; MOVQ DX, 0+y; \ + MOVQ 8+x, AX; MOVQ AX, R8; MOVQ 8+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 8+x; MOVQ DX, 8+y; \ + MOVQ 16+x, AX; MOVQ AX, R8; MOVQ 16+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 16+x; MOVQ DX, 16+y; \ + MOVQ 24+x, AX; MOVQ AX, R8; MOVQ 24+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 24+x; MOVQ DX, 24+y; + +// additionLeg adds x and y and stores in z +// Uses: AX, DX, R8-R11, FLAGS +// Instr: x86_64, cmov +#define additionLeg(z,x,y) \ + MOVL $38, AX; \ + MOVL $0, DX; \ + MOVQ 0+x, R8; ADDQ 0+y, R8; \ + MOVQ 8+x, R9; ADCQ 8+y, R9; \ + MOVQ 16+x, R10; ADCQ 16+y, R10; \ + MOVQ 24+x, R11; ADCQ 24+y, R11; \ + CMOVQCS AX, DX; \ + ADDQ DX, R8; \ + ADCQ $0, R9; MOVQ R9, 8+z; \ + ADCQ $0, R10; MOVQ R10, 16+z; \ + ADCQ $0, R11; MOVQ R11, 24+z; \ + MOVL $0, DX; \ + CMOVQCS AX, DX; \ + ADDQ DX, R8; MOVQ R8, 0+z; + +// additionAdx adds x and y and stores in z +// Uses: AX, DX, R8-R11, FLAGS +// Instr: x86_64, cmov, adx +#define additionAdx(z,x,y) \ + MOVL $38, AX; \ + XORL DX, DX; \ + MOVQ 0+x, R8; ADCXQ 0+y, R8; \ + MOVQ 8+x, R9; ADCXQ 8+y, R9; \ + MOVQ 16+x, R10; ADCXQ 16+y, R10; \ + MOVQ 24+x, R11; ADCXQ 24+y, R11; \ + CMOVQCS AX, DX ; \ + XORL AX, AX; \ + ADCXQ DX, R8; \ + ADCXQ AX, R9; MOVQ R9, 8+z; \ + ADCXQ AX, R10; MOVQ R10, 16+z; \ + ADCXQ AX, R11; MOVQ R11, 24+z; \ + MOVL $38, DX; \ + CMOVQCS DX, AX; \ + ADDQ AX, R8; MOVQ R8, 0+z; + +// subtraction subtracts y from x and stores in z +// Uses: AX, DX, R8-R11, FLAGS +// Instr: x86_64, cmov +#define subtraction(z,x,y) \ + MOVL $38, AX; \ + MOVQ 0+x, R8; SUBQ 0+y, R8; \ + MOVQ 8+x, R9; SBBQ 8+y, R9; \ + MOVQ 16+x, R10; SBBQ 16+y, R10; \ + MOVQ 24+x, R11; SBBQ 24+y, R11; \ + MOVL $0, DX; \ + CMOVQCS AX, DX; \ + SUBQ DX, R8; \ + SBBQ $0, R9; MOVQ R9, 8+z; \ + SBBQ $0, R10; MOVQ R10, 16+z; \ + SBBQ $0, R11; MOVQ R11, 24+z; \ + MOVL $0, DX; \ + CMOVQCS AX, DX; \ + SUBQ DX, R8; MOVQ R8, 0+z; + +// integerMulAdx multiplies x and y and stores in z +// Uses: AX, DX, R8-R15, FLAGS +// Instr: x86_64, bmi2, adx +#define integerMulAdx(z,x,y) \ + MOVL $0,R15; \ + MOVQ 0+y, DX; XORL AX, AX; \ + MULXQ 0+x, AX, R8; MOVQ AX, 0+z; \ + MULXQ 8+x, AX, R9; ADCXQ AX, R8; \ + MULXQ 16+x, AX, R10; ADCXQ AX, R9; \ + MULXQ 24+x, AX, R11; ADCXQ AX, R10; \ + MOVL $0, AX;;;;;;;;; ADCXQ AX, R11; \ + MOVQ 8+y, DX; XORL AX, AX; \ + MULXQ 0+x, AX, R12; ADCXQ R8, AX; MOVQ AX, 8+z; \ + MULXQ 8+x, AX, R13; ADCXQ R9, R12; ADOXQ AX, R12; \ + MULXQ 16+x, AX, R14; ADCXQ R10, R13; ADOXQ AX, R13; \ + MULXQ 24+x, AX, R15; ADCXQ R11, R14; ADOXQ AX, R14; \ + MOVL $0, AX;;;;;;;;; ADCXQ AX, R15; ADOXQ AX, R15; \ + MOVQ 16+y, DX; XORL AX, AX; \ + MULXQ 0+x, AX, R8; ADCXQ R12, AX; MOVQ AX, 16+z; \ + MULXQ 8+x, AX, R9; ADCXQ R13, R8; ADOXQ AX, R8; \ + MULXQ 16+x, AX, R10; ADCXQ R14, R9; ADOXQ AX, R9; \ + MULXQ 24+x, AX, R11; ADCXQ R15, R10; ADOXQ AX, R10; \ + MOVL $0, AX;;;;;;;;; ADCXQ AX, R11; ADOXQ AX, R11; \ + MOVQ 24+y, DX; XORL AX, AX; \ + MULXQ 0+x, AX, R12; ADCXQ R8, AX; MOVQ AX, 24+z; \ + MULXQ 8+x, AX, R13; ADCXQ R9, R12; ADOXQ AX, R12; MOVQ R12, 32+z; \ + MULXQ 16+x, AX, R14; ADCXQ R10, R13; ADOXQ AX, R13; MOVQ R13, 40+z; \ + MULXQ 24+x, AX, R15; ADCXQ R11, R14; ADOXQ AX, R14; MOVQ R14, 48+z; \ + MOVL $0, AX;;;;;;;;; ADCXQ AX, R15; ADOXQ AX, R15; MOVQ R15, 56+z; + +// integerMulLeg multiplies x and y and stores in z +// Uses: AX, DX, R8-R15, FLAGS +// Instr: x86_64 +#define integerMulLeg(z,x,y) \ + MOVQ 0+y, R8; \ + MOVQ 0+x, AX; MULQ R8; MOVQ AX, 0+z; MOVQ DX, R15; \ + MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ + MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ + MOVQ 24+x, AX; MULQ R8; \ + ADDQ R13, R15; \ + ADCQ R14, R10; MOVQ R10, 16+z; \ + ADCQ AX, R11; MOVQ R11, 24+z; \ + ADCQ $0, DX; MOVQ DX, 32+z; \ + MOVQ 8+y, R8; \ + MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \ + MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ + MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ + MOVQ 24+x, AX; MULQ R8; \ + ADDQ R12, R15; MOVQ R15, 8+z; \ + ADCQ R13, R9; \ + ADCQ R14, R10; \ + ADCQ AX, R11; \ + ADCQ $0, DX; \ + ADCQ 16+z, R9; MOVQ R9, R15; \ + ADCQ 24+z, R10; MOVQ R10, 24+z; \ + ADCQ 32+z, R11; MOVQ R11, 32+z; \ + ADCQ $0, DX; MOVQ DX, 40+z; \ + MOVQ 16+y, R8; \ + MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \ + MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ + MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ + MOVQ 24+x, AX; MULQ R8; \ + ADDQ R12, R15; MOVQ R15, 16+z; \ + ADCQ R13, R9; \ + ADCQ R14, R10; \ + ADCQ AX, R11; \ + ADCQ $0, DX; \ + ADCQ 24+z, R9; MOVQ R9, R15; \ + ADCQ 32+z, R10; MOVQ R10, 32+z; \ + ADCQ 40+z, R11; MOVQ R11, 40+z; \ + ADCQ $0, DX; MOVQ DX, 48+z; \ + MOVQ 24+y, R8; \ + MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \ + MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ + MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ + MOVQ 24+x, AX; MULQ R8; \ + ADDQ R12, R15; MOVQ R15, 24+z; \ + ADCQ R13, R9; \ + ADCQ R14, R10; \ + ADCQ AX, R11; \ + ADCQ $0, DX; \ + ADCQ 32+z, R9; MOVQ R9, 32+z; \ + ADCQ 40+z, R10; MOVQ R10, 40+z; \ + ADCQ 48+z, R11; MOVQ R11, 48+z; \ + ADCQ $0, DX; MOVQ DX, 56+z; + +// integerSqrLeg squares x and stores in z +// Uses: AX, CX, DX, R8-R15, FLAGS +// Instr: x86_64 +#define integerSqrLeg(z,x) \ + MOVQ 0+x, R8; \ + MOVQ 8+x, AX; MULQ R8; MOVQ AX, R9; MOVQ DX, R10; /* A[0]*A[1] */ \ + MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; /* A[0]*A[2] */ \ + MOVQ 24+x, AX; MULQ R8; MOVQ AX, R15; MOVQ DX, R12; /* A[0]*A[3] */ \ + MOVQ 24+x, R8; \ + MOVQ 8+x, AX; MULQ R8; MOVQ AX, CX; MOVQ DX, R13; /* A[3]*A[1] */ \ + MOVQ 16+x, AX; MULQ R8; /* A[3]*A[2] */ \ + \ + ADDQ R14, R10;\ + ADCQ R15, R11; MOVL $0, R15;\ + ADCQ CX, R12;\ + ADCQ AX, R13;\ + ADCQ $0, DX; MOVQ DX, R14;\ + MOVQ 8+x, AX; MULQ 16+x;\ + \ + ADDQ AX, R11;\ + ADCQ DX, R12;\ + ADCQ $0, R13;\ + ADCQ $0, R14;\ + ADCQ $0, R15;\ + \ + SHLQ $1, R14, R15; MOVQ R15, 56+z;\ + SHLQ $1, R13, R14; MOVQ R14, 48+z;\ + SHLQ $1, R12, R13; MOVQ R13, 40+z;\ + SHLQ $1, R11, R12; MOVQ R12, 32+z;\ + SHLQ $1, R10, R11; MOVQ R11, 24+z;\ + SHLQ $1, R9, R10; MOVQ R10, 16+z;\ + SHLQ $1, R9; MOVQ R9, 8+z;\ + \ + MOVQ 0+x,AX; MULQ AX; MOVQ AX, 0+z; MOVQ DX, R9;\ + MOVQ 8+x,AX; MULQ AX; MOVQ AX, R10; MOVQ DX, R11;\ + MOVQ 16+x,AX; MULQ AX; MOVQ AX, R12; MOVQ DX, R13;\ + MOVQ 24+x,AX; MULQ AX; MOVQ AX, R14; MOVQ DX, R15;\ + \ + ADDQ 8+z, R9; MOVQ R9, 8+z;\ + ADCQ 16+z, R10; MOVQ R10, 16+z;\ + ADCQ 24+z, R11; MOVQ R11, 24+z;\ + ADCQ 32+z, R12; MOVQ R12, 32+z;\ + ADCQ 40+z, R13; MOVQ R13, 40+z;\ + ADCQ 48+z, R14; MOVQ R14, 48+z;\ + ADCQ 56+z, R15; MOVQ R15, 56+z; + +// integerSqrAdx squares x and stores in z +// Uses: AX, CX, DX, R8-R15, FLAGS +// Instr: x86_64, bmi2, adx +#define integerSqrAdx(z,x) \ + MOVQ 0+x, DX; /* A[0] */ \ + MULXQ 8+x, R8, R14; /* A[1]*A[0] */ XORL R15, R15; \ + MULXQ 16+x, R9, R10; /* A[2]*A[0] */ ADCXQ R14, R9; \ + MULXQ 24+x, AX, CX; /* A[3]*A[0] */ ADCXQ AX, R10; \ + MOVQ 24+x, DX; /* A[3] */ \ + MULXQ 8+x, R11, R12; /* A[1]*A[3] */ ADCXQ CX, R11; \ + MULXQ 16+x, AX, R13; /* A[2]*A[3] */ ADCXQ AX, R12; \ + MOVQ 8+x, DX; /* A[1] */ ADCXQ R15, R13; \ + MULXQ 16+x, AX, CX; /* A[2]*A[1] */ MOVL $0, R14; \ + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADCXQ R15, R14; \ + XORL R15, R15; \ + ADOXQ AX, R10; ADCXQ R8, R8; \ + ADOXQ CX, R11; ADCXQ R9, R9; \ + ADOXQ R15, R12; ADCXQ R10, R10; \ + ADOXQ R15, R13; ADCXQ R11, R11; \ + ADOXQ R15, R14; ADCXQ R12, R12; \ + ;;;;;;;;;;;;;;; ADCXQ R13, R13; \ + ;;;;;;;;;;;;;;; ADCXQ R14, R14; \ + MOVQ 0+x, DX; MULXQ DX, AX, CX; /* A[0]^2 */ \ + ;;;;;;;;;;;;;;; MOVQ AX, 0+z; \ + ADDQ CX, R8; MOVQ R8, 8+z; \ + MOVQ 8+x, DX; MULXQ DX, AX, CX; /* A[1]^2 */ \ + ADCQ AX, R9; MOVQ R9, 16+z; \ + ADCQ CX, R10; MOVQ R10, 24+z; \ + MOVQ 16+x, DX; MULXQ DX, AX, CX; /* A[2]^2 */ \ + ADCQ AX, R11; MOVQ R11, 32+z; \ + ADCQ CX, R12; MOVQ R12, 40+z; \ + MOVQ 24+x, DX; MULXQ DX, AX, CX; /* A[3]^2 */ \ + ADCQ AX, R13; MOVQ R13, 48+z; \ + ADCQ CX, R14; MOVQ R14, 56+z; + +// reduceFromDouble finds z congruent to x modulo p such that 0> 63) + // PUT BIT 255 IN CARRY FLAG AND CLEAR + x3 &^= 1 << 63 + + x0, c0 := bits.Add64(x0, cx, 0) + x1, c1 := bits.Add64(x1, 0, c0) + x2, c2 := bits.Add64(x2, 0, c1) + x3, _ = bits.Add64(x3, 0, c2) + + // TEST FOR BIT 255 AGAIN; ONLY TRIGGERED ON OVERFLOW MODULO 2^255-19 + // cx = C[255] ? 0 : 19 + cx = uint64(19) &^ (-(x3 >> 63)) + // CLEAR BIT 255 + x3 &^= 1 << 63 + + x0, c0 = bits.Sub64(x0, cx, 0) + x1, c1 = bits.Sub64(x1, 0, c0) + x2, c2 = bits.Sub64(x2, 0, c1) + x3, _ = bits.Sub64(x3, 0, c2) + + binary.LittleEndian.PutUint64(x[0*8:1*8], x0) + binary.LittleEndian.PutUint64(x[1*8:2*8], x1) + binary.LittleEndian.PutUint64(x[2*8:3*8], x2) + binary.LittleEndian.PutUint64(x[3*8:4*8], x3) +} + +func red64(z *Elt, x0, x1, x2, x3, x4, x5, x6, x7 uint64) { + h0, l0 := bits.Mul64(x4, 38) + h1, l1 := bits.Mul64(x5, 38) + h2, l2 := bits.Mul64(x6, 38) + h3, l3 := bits.Mul64(x7, 38) + + l1, c0 := bits.Add64(h0, l1, 0) + l2, c1 := bits.Add64(h1, l2, c0) + l3, c2 := bits.Add64(h2, l3, c1) + l4, _ := bits.Add64(h3, 0, c2) + + l0, c0 = bits.Add64(l0, x0, 0) + l1, c1 = bits.Add64(l1, x1, c0) + l2, c2 = bits.Add64(l2, x2, c1) + l3, c3 := bits.Add64(l3, x3, c2) + l4, _ = bits.Add64(l4, 0, c3) + + _, l4 = bits.Mul64(l4, 38) + l0, c0 = bits.Add64(l0, l4, 0) + z1, c1 := bits.Add64(l1, 0, c0) + z2, c2 := bits.Add64(l2, 0, c1) + z3, c3 := bits.Add64(l3, 0, c2) + z0, _ := bits.Add64(l0, (-c3)&38, 0) + + binary.LittleEndian.PutUint64(z[0*8:1*8], z0) + binary.LittleEndian.PutUint64(z[1*8:2*8], z1) + binary.LittleEndian.PutUint64(z[2*8:3*8], z2) + binary.LittleEndian.PutUint64(z[3*8:4*8], z3) +} diff --git a/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go new file mode 100644 index 00000000000..26ca4d01b7e --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go @@ -0,0 +1,13 @@ +//go:build !amd64 || purego +// +build !amd64 purego + +package fp25519 + +func cmov(x, y *Elt, n uint) { cmovGeneric(x, y, n) } +func cswap(x, y *Elt, n uint) { cswapGeneric(x, y, n) } +func add(z, x, y *Elt) { addGeneric(z, x, y) } +func sub(z, x, y *Elt) { subGeneric(z, x, y) } +func addsub(x, y *Elt) { addsubGeneric(x, y) } +func mul(z, x, y *Elt) { mulGeneric(z, x, y) } +func sqr(z, x *Elt) { sqrGeneric(z, x) } +func modp(z *Elt) { modpGeneric(z) } diff --git a/src/vendor/github.com/cloudflare/circl/math/fp448/fp.go b/src/vendor/github.com/cloudflare/circl/math/fp448/fp.go new file mode 100644 index 00000000000..a5e36600bb6 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp.go @@ -0,0 +1,164 @@ +// Package fp448 provides prime field arithmetic over GF(2^448-2^224-1). +package fp448 + +import ( + "errors" + + "github.com/cloudflare/circl/internal/conv" +) + +// Size in bytes of an element. +const Size = 56 + +// Elt is a prime field element. +type Elt [Size]byte + +func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) } + +// p is the prime modulus 2^448-2^224-1. +var p = Elt{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +} + +// P returns the prime modulus 2^448-2^224-1. +func P() Elt { return p } + +// ToBytes stores in b the little-endian byte representation of x. +func ToBytes(b []byte, x *Elt) error { + if len(b) != Size { + return errors.New("wrong size") + } + Modp(x) + copy(b, x[:]) + return nil +} + +// IsZero returns true if x is equal to 0. +func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} } + +// IsOne returns true if x is equal to 1. +func IsOne(x *Elt) bool { Modp(x); return *x == Elt{1} } + +// SetOne assigns x=1. +func SetOne(x *Elt) { *x = Elt{1} } + +// One returns the 1 element. +func One() (x Elt) { x = Elt{1}; return } + +// Neg calculates z = -x. +func Neg(z, x *Elt) { Sub(z, &p, x) } + +// Modp ensures that z is between [0,p-1]. +func Modp(z *Elt) { Sub(z, z, &p) } + +// InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue. If so, +// isQR = true; otherwise, isQR = false, since x/y is a quadratic non-residue, +// and z = sqrt(-x/y). +func InvSqrt(z, x, y *Elt) (isQR bool) { + // First note that x^(2(k+1)) = x^(p-1)/2 * x = legendre(x) * x + // so that's x if x is a quadratic residue and -x otherwise. + // Next, y^(6k+3) = y^(4k+2) * y^(2k+1) = y^(p-1) * y^((p-1)/2) = legendre(y). + // So the z we compute satisfies z^2 y = x^(2(k+1)) y^(6k+3) = legendre(x)*legendre(y). + // Thus if x and y are quadratic residues, then z is indeed sqrt(x/y). + t0, t1 := &Elt{}, &Elt{} + Mul(t0, x, y) // x*y + Sqr(t1, y) // y^2 + Mul(t1, t0, t1) // x*y^3 + powPminus3div4(z, t1) // (x*y^3)^k + Mul(z, z, t0) // z = x*y*(x*y^3)^k = x^(k+1) * y^(3k+1) + + // Check if x/y is a quadratic residue + Sqr(t0, z) // z^2 + Mul(t0, t0, y) // y*z^2 + Sub(t0, t0, x) // y*z^2-x + return IsZero(t0) +} + +// Inv calculates z = 1/x mod p. +func Inv(z, x *Elt) { + // Calculates z = x^(4k+1) = x^(p-3+1) = x^(p-2) = x^-1, where k = (p-3)/4. + t := &Elt{} + powPminus3div4(t, x) // t = x^k + Sqr(t, t) // t = x^2k + Sqr(t, t) // t = x^4k + Mul(z, t, x) // z = x^(4k+1) +} + +// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. +func powPminus3div4(z, x *Elt) { + x0, x1 := &Elt{}, &Elt{} + Sqr(z, x) + Mul(z, z, x) + Sqr(x0, z) + Mul(x0, x0, x) + Sqr(z, x0) + Sqr(z, z) + Sqr(z, z) + Mul(z, z, x0) + Sqr(x1, z) + for i := 0; i < 5; i++ { + Sqr(x1, x1) + } + Mul(x1, x1, z) + Sqr(z, x1) + for i := 0; i < 11; i++ { + Sqr(z, z) + } + Mul(z, z, x1) + Sqr(z, z) + Sqr(z, z) + Sqr(z, z) + Mul(z, z, x0) + Sqr(x1, z) + for i := 0; i < 26; i++ { + Sqr(x1, x1) + } + Mul(x1, x1, z) + Sqr(z, x1) + for i := 0; i < 53; i++ { + Sqr(z, z) + } + Mul(z, z, x1) + Sqr(z, z) + Sqr(z, z) + Sqr(z, z) + Mul(z, z, x0) + Sqr(x1, z) + for i := 0; i < 110; i++ { + Sqr(x1, x1) + } + Mul(x1, x1, z) + Sqr(z, x1) + Mul(z, z, x) + for i := 0; i < 223; i++ { + Sqr(z, z) + } + Mul(z, z, x1) +} + +// Cmov assigns y to x if n is 1. +func Cmov(x, y *Elt, n uint) { cmov(x, y, n) } + +// Cswap interchanges x and y if n is 1. +func Cswap(x, y *Elt, n uint) { cswap(x, y, n) } + +// Add calculates z = x+y mod p. +func Add(z, x, y *Elt) { add(z, x, y) } + +// Sub calculates z = x-y mod p. +func Sub(z, x, y *Elt) { sub(z, x, y) } + +// AddSub calculates (x,y) = (x+y mod p, x-y mod p). +func AddSub(x, y *Elt) { addsub(x, y) } + +// Mul calculates z = x*y mod p. +func Mul(z, x, y *Elt) { mul(z, x, y) } + +// Sqr calculates z = x^2 mod p. +func Sqr(z, x *Elt) { sqr(z, x) } diff --git a/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go new file mode 100644 index 00000000000..6a12209a704 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go @@ -0,0 +1,43 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package fp448 + +import ( + "golang.org/x/sys/cpu" +) + +var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX + +var _ = hasBmi2Adx + +func cmov(x, y *Elt, n uint) { cmovAmd64(x, y, n) } +func cswap(x, y *Elt, n uint) { cswapAmd64(x, y, n) } +func add(z, x, y *Elt) { addAmd64(z, x, y) } +func sub(z, x, y *Elt) { subAmd64(z, x, y) } +func addsub(x, y *Elt) { addsubAmd64(x, y) } +func mul(z, x, y *Elt) { mulAmd64(z, x, y) } +func sqr(z, x *Elt) { sqrAmd64(z, x) } + +/* Functions defined in fp_amd64.s */ + +//go:noescape +func cmovAmd64(x, y *Elt, n uint) + +//go:noescape +func cswapAmd64(x, y *Elt, n uint) + +//go:noescape +func addAmd64(z, x, y *Elt) + +//go:noescape +func subAmd64(z, x, y *Elt) + +//go:noescape +func addsubAmd64(x, y *Elt) + +//go:noescape +func mulAmd64(z, x, y *Elt) + +//go:noescape +func sqrAmd64(z, x *Elt) diff --git a/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h new file mode 100644 index 00000000000..536fe5bdfe0 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h @@ -0,0 +1,591 @@ +// This code was imported from https://github.com/armfazh/rfc7748_precomputed + +// CHECK_BMI2ADX triggers bmi2adx if supported, +// otherwise it fallbacks to legacy code. +#define CHECK_BMI2ADX(label, legacy, bmi2adx) \ + CMPB ·hasBmi2Adx(SB), $0 \ + JE label \ + bmi2adx \ + RET \ + label: \ + legacy \ + RET + +// cselect is a conditional move +// if b=1: it copies y into x; +// if b=0: x remains with the same value; +// if b<> 0,1: undefined. +// Uses: AX, DX, FLAGS +// Instr: x86_64, cmov +#define cselect(x,y,b) \ + TESTQ b, b \ + MOVQ 0+x, AX; MOVQ 0+y, DX; CMOVQNE DX, AX; MOVQ AX, 0+x; \ + MOVQ 8+x, AX; MOVQ 8+y, DX; CMOVQNE DX, AX; MOVQ AX, 8+x; \ + MOVQ 16+x, AX; MOVQ 16+y, DX; CMOVQNE DX, AX; MOVQ AX, 16+x; \ + MOVQ 24+x, AX; MOVQ 24+y, DX; CMOVQNE DX, AX; MOVQ AX, 24+x; \ + MOVQ 32+x, AX; MOVQ 32+y, DX; CMOVQNE DX, AX; MOVQ AX, 32+x; \ + MOVQ 40+x, AX; MOVQ 40+y, DX; CMOVQNE DX, AX; MOVQ AX, 40+x; \ + MOVQ 48+x, AX; MOVQ 48+y, DX; CMOVQNE DX, AX; MOVQ AX, 48+x; + +// cswap is a conditional swap +// if b=1: x,y <- y,x; +// if b=0: x,y remain with the same values; +// if b<> 0,1: undefined. +// Uses: AX, DX, R8, FLAGS +// Instr: x86_64, cmov +#define cswap(x,y,b) \ + TESTQ b, b \ + MOVQ 0+x, AX; MOVQ AX, R8; MOVQ 0+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 0+x; MOVQ DX, 0+y; \ + MOVQ 8+x, AX; MOVQ AX, R8; MOVQ 8+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 8+x; MOVQ DX, 8+y; \ + MOVQ 16+x, AX; MOVQ AX, R8; MOVQ 16+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 16+x; MOVQ DX, 16+y; \ + MOVQ 24+x, AX; MOVQ AX, R8; MOVQ 24+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 24+x; MOVQ DX, 24+y; \ + MOVQ 32+x, AX; MOVQ AX, R8; MOVQ 32+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 32+x; MOVQ DX, 32+y; \ + MOVQ 40+x, AX; MOVQ AX, R8; MOVQ 40+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 40+x; MOVQ DX, 40+y; \ + MOVQ 48+x, AX; MOVQ AX, R8; MOVQ 48+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 48+x; MOVQ DX, 48+y; + +// additionLeg adds x and y and stores in z +// Uses: AX, DX, R8-R14, FLAGS +// Instr: x86_64 +#define additionLeg(z,x,y) \ + MOVQ 0+x, R8; ADDQ 0+y, R8; \ + MOVQ 8+x, R9; ADCQ 8+y, R9; \ + MOVQ 16+x, R10; ADCQ 16+y, R10; \ + MOVQ 24+x, R11; ADCQ 24+y, R11; \ + MOVQ 32+x, R12; ADCQ 32+y, R12; \ + MOVQ 40+x, R13; ADCQ 40+y, R13; \ + MOVQ 48+x, R14; ADCQ 48+y, R14; \ + MOVQ $0, AX; ADCQ $0, AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + ADDQ AX, R8; MOVQ $0, AX; \ + ADCQ $0, R9; \ + ADCQ $0, R10; \ + ADCQ DX, R11; \ + ADCQ $0, R12; \ + ADCQ $0, R13; \ + ADCQ $0, R14; \ + ADCQ $0, AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + ADDQ AX, R8; MOVQ R8, 0+z; \ + ADCQ $0, R9; MOVQ R9, 8+z; \ + ADCQ $0, R10; MOVQ R10, 16+z; \ + ADCQ DX, R11; MOVQ R11, 24+z; \ + ADCQ $0, R12; MOVQ R12, 32+z; \ + ADCQ $0, R13; MOVQ R13, 40+z; \ + ADCQ $0, R14; MOVQ R14, 48+z; + + +// additionAdx adds x and y and stores in z +// Uses: AX, DX, R8-R15, FLAGS +// Instr: x86_64, adx +#define additionAdx(z,x,y) \ + MOVL $32, R15; \ + XORL DX, DX; \ + MOVQ 0+x, R8; ADCXQ 0+y, R8; \ + MOVQ 8+x, R9; ADCXQ 8+y, R9; \ + MOVQ 16+x, R10; ADCXQ 16+y, R10; \ + MOVQ 24+x, R11; ADCXQ 24+y, R11; \ + MOVQ 32+x, R12; ADCXQ 32+y, R12; \ + MOVQ 40+x, R13; ADCXQ 40+y, R13; \ + MOVQ 48+x, R14; ADCXQ 48+y, R14; \ + ;;;;;;;;;;;;;;; ADCXQ DX, DX; \ + XORL AX, AX; \ + ADCXQ DX, R8; SHLXQ R15, DX, DX; \ + ADCXQ AX, R9; \ + ADCXQ AX, R10; \ + ADCXQ DX, R11; \ + ADCXQ AX, R12; \ + ADCXQ AX, R13; \ + ADCXQ AX, R14; \ + ADCXQ AX, AX; \ + XORL DX, DX; \ + ADCXQ AX, R8; MOVQ R8, 0+z; SHLXQ R15, AX, AX; \ + ADCXQ DX, R9; MOVQ R9, 8+z; \ + ADCXQ DX, R10; MOVQ R10, 16+z; \ + ADCXQ AX, R11; MOVQ R11, 24+z; \ + ADCXQ DX, R12; MOVQ R12, 32+z; \ + ADCXQ DX, R13; MOVQ R13, 40+z; \ + ADCXQ DX, R14; MOVQ R14, 48+z; + +// subtraction subtracts y from x and stores in z +// Uses: AX, DX, R8-R14, FLAGS +// Instr: x86_64 +#define subtraction(z,x,y) \ + MOVQ 0+x, R8; SUBQ 0+y, R8; \ + MOVQ 8+x, R9; SBBQ 8+y, R9; \ + MOVQ 16+x, R10; SBBQ 16+y, R10; \ + MOVQ 24+x, R11; SBBQ 24+y, R11; \ + MOVQ 32+x, R12; SBBQ 32+y, R12; \ + MOVQ 40+x, R13; SBBQ 40+y, R13; \ + MOVQ 48+x, R14; SBBQ 48+y, R14; \ + MOVQ $0, AX; SETCS AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + SUBQ AX, R8; MOVQ $0, AX; \ + SBBQ $0, R9; \ + SBBQ $0, R10; \ + SBBQ DX, R11; \ + SBBQ $0, R12; \ + SBBQ $0, R13; \ + SBBQ $0, R14; \ + SETCS AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + SUBQ AX, R8; MOVQ R8, 0+z; \ + SBBQ $0, R9; MOVQ R9, 8+z; \ + SBBQ $0, R10; MOVQ R10, 16+z; \ + SBBQ DX, R11; MOVQ R11, 24+z; \ + SBBQ $0, R12; MOVQ R12, 32+z; \ + SBBQ $0, R13; MOVQ R13, 40+z; \ + SBBQ $0, R14; MOVQ R14, 48+z; + +// maddBmi2Adx multiplies x and y and accumulates in z +// Uses: AX, DX, R15, FLAGS +// Instr: x86_64, bmi2, adx +#define maddBmi2Adx(z,x,y,i,r0,r1,r2,r3,r4,r5,r6) \ + MOVQ i+y, DX; XORL AX, AX; \ + MULXQ 0+x, AX, R8; ADOXQ AX, r0; ADCXQ R8, r1; MOVQ r0,i+z; \ + MULXQ 8+x, AX, r0; ADOXQ AX, r1; ADCXQ r0, r2; MOVQ $0, R8; \ + MULXQ 16+x, AX, r0; ADOXQ AX, r2; ADCXQ r0, r3; \ + MULXQ 24+x, AX, r0; ADOXQ AX, r3; ADCXQ r0, r4; \ + MULXQ 32+x, AX, r0; ADOXQ AX, r4; ADCXQ r0, r5; \ + MULXQ 40+x, AX, r0; ADOXQ AX, r5; ADCXQ r0, r6; \ + MULXQ 48+x, AX, r0; ADOXQ AX, r6; ADCXQ R8, r0; \ + ;;;;;;;;;;;;;;;;;;; ADOXQ R8, r0; + +// integerMulAdx multiplies x and y and stores in z +// Uses: AX, DX, R8-R15, FLAGS +// Instr: x86_64, bmi2, adx +#define integerMulAdx(z,x,y) \ + MOVL $0,R15; \ + MOVQ 0+y, DX; XORL AX, AX; MOVQ $0, R8; \ + MULXQ 0+x, AX, R9; MOVQ AX, 0+z; \ + MULXQ 8+x, AX, R10; ADCXQ AX, R9; \ + MULXQ 16+x, AX, R11; ADCXQ AX, R10; \ + MULXQ 24+x, AX, R12; ADCXQ AX, R11; \ + MULXQ 32+x, AX, R13; ADCXQ AX, R12; \ + MULXQ 40+x, AX, R14; ADCXQ AX, R13; \ + MULXQ 48+x, AX, R15; ADCXQ AX, R14; \ + ;;;;;;;;;;;;;;;;;;;; ADCXQ R8, R15; \ + maddBmi2Adx(z,x,y, 8, R9,R10,R11,R12,R13,R14,R15) \ + maddBmi2Adx(z,x,y,16,R10,R11,R12,R13,R14,R15, R9) \ + maddBmi2Adx(z,x,y,24,R11,R12,R13,R14,R15, R9,R10) \ + maddBmi2Adx(z,x,y,32,R12,R13,R14,R15, R9,R10,R11) \ + maddBmi2Adx(z,x,y,40,R13,R14,R15, R9,R10,R11,R12) \ + maddBmi2Adx(z,x,y,48,R14,R15, R9,R10,R11,R12,R13) \ + MOVQ R15, 56+z; \ + MOVQ R9, 64+z; \ + MOVQ R10, 72+z; \ + MOVQ R11, 80+z; \ + MOVQ R12, 88+z; \ + MOVQ R13, 96+z; \ + MOVQ R14, 104+z; + +// maddLegacy multiplies x and y and accumulates in z +// Uses: AX, DX, R15, FLAGS +// Instr: x86_64 +#define maddLegacy(z,x,y,i) \ + MOVQ i+y, R15; \ + MOVQ 0+x, AX; MULQ R15; MOVQ AX, R8; ;;;;;;;;;;;; MOVQ DX, R9; \ + MOVQ 8+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \ + MOVQ 16+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \ + MOVQ 24+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \ + MOVQ 32+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \ + MOVQ 40+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \ + MOVQ 48+x, AX; MULQ R15; ADDQ AX, R14; ADCQ $0, DX; \ + ADDQ 0+i+z, R8; MOVQ R8, 0+i+z; \ + ADCQ 8+i+z, R9; MOVQ R9, 8+i+z; \ + ADCQ 16+i+z, R10; MOVQ R10, 16+i+z; \ + ADCQ 24+i+z, R11; MOVQ R11, 24+i+z; \ + ADCQ 32+i+z, R12; MOVQ R12, 32+i+z; \ + ADCQ 40+i+z, R13; MOVQ R13, 40+i+z; \ + ADCQ 48+i+z, R14; MOVQ R14, 48+i+z; \ + ADCQ $0, DX; MOVQ DX, 56+i+z; + +// integerMulLeg multiplies x and y and stores in z +// Uses: AX, DX, R8-R15, FLAGS +// Instr: x86_64 +#define integerMulLeg(z,x,y) \ + MOVQ 0+y, R15; \ + MOVQ 0+x, AX; MULQ R15; MOVQ AX, 0+z; ;;;;;;;;;;;; MOVQ DX, R8; \ + MOVQ 8+x, AX; MULQ R15; ADDQ AX, R8; ADCQ $0, DX; MOVQ DX, R9; MOVQ R8, 8+z; \ + MOVQ 16+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; MOVQ R9, 16+z; \ + MOVQ 24+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; MOVQ R10, 24+z; \ + MOVQ 32+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; MOVQ R11, 32+z; \ + MOVQ 40+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; MOVQ R12, 40+z; \ + MOVQ 48+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX,56+z; MOVQ R13, 48+z; \ + maddLegacy(z,x,y, 8) \ + maddLegacy(z,x,y,16) \ + maddLegacy(z,x,y,24) \ + maddLegacy(z,x,y,32) \ + maddLegacy(z,x,y,40) \ + maddLegacy(z,x,y,48) + +// integerSqrLeg squares x and stores in z +// Uses: AX, CX, DX, R8-R15, FLAGS +// Instr: x86_64 +#define integerSqrLeg(z,x) \ + XORL R15, R15; \ + MOVQ 0+x, CX; \ + MOVQ CX, AX; MULQ CX; MOVQ AX, 0+z; MOVQ DX, R8; \ + ADDQ CX, CX; ADCQ $0, R15; \ + MOVQ 8+x, AX; MULQ CX; ADDQ AX, R8; ADCQ $0, DX; MOVQ DX, R9; MOVQ R8, 8+z; \ + MOVQ 16+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \ + MOVQ 24+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \ + MOVQ 32+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \ + MOVQ 40+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \ + MOVQ 48+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \ + \ + MOVQ 8+x, CX; \ + MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ + ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ R9,16+z; \ + MOVQ R15, AX; NEGQ AX; ANDQ 8+x, AX; ADDQ AX, DX; ADCQ $0, R11; MOVQ DX, R8; \ + ADDQ 8+x, CX; ADCQ $0, R15; \ + MOVQ 16+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX, R8; MOVQ R10, 24+z; \ + MOVQ 24+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; ADDQ R8, R11; ADCQ $0, DX; MOVQ DX, R8; \ + MOVQ 32+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; \ + MOVQ 40+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; ADDQ R8, R13; ADCQ $0, DX; MOVQ DX, R8; \ + MOVQ 48+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R9; \ + \ + MOVQ 16+x, CX; \ + MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ + ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ R11, 32+z; \ + MOVQ R15, AX; NEGQ AX; ANDQ 16+x,AX; ADDQ AX, DX; ADCQ $0, R13; MOVQ DX, R8; \ + ADDQ 16+x, CX; ADCQ $0, R15; \ + MOVQ 24+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; MOVQ R12, 40+z; \ + MOVQ 32+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; ADDQ R8, R13; ADCQ $0, DX; MOVQ DX, R8; \ + MOVQ 40+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R8; \ + MOVQ 48+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; ADDQ R8, R9; ADCQ $0, DX; MOVQ DX,R10; \ + \ + MOVQ 24+x, CX; \ + MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ + ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ R13, 48+z; \ + MOVQ R15, AX; NEGQ AX; ANDQ 24+x,AX; ADDQ AX, DX; ADCQ $0, R9; MOVQ DX, R8; \ + ADDQ 24+x, CX; ADCQ $0, R15; \ + MOVQ 32+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R8; MOVQ R14, 56+z; \ + MOVQ 40+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; ADDQ R8, R9; ADCQ $0, DX; MOVQ DX, R8; \ + MOVQ 48+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX,R11; \ + \ + MOVQ 32+x, CX; \ + MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ + ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ R9, 64+z; \ + MOVQ R15, AX; NEGQ AX; ANDQ 32+x,AX; ADDQ AX, DX; ADCQ $0, R11; MOVQ DX, R8; \ + ADDQ 32+x, CX; ADCQ $0, R15; \ + MOVQ 40+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX, R8; MOVQ R10, 72+z; \ + MOVQ 48+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; ADDQ R8, R11; ADCQ $0, DX; MOVQ DX,R12; \ + \ + XORL R13, R13; \ + XORL R14, R14; \ + MOVQ 40+x, CX; \ + MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ + ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ R11, 80+z; \ + MOVQ R15, AX; NEGQ AX; ANDQ 40+x,AX; ADDQ AX, DX; ADCQ $0, R13; MOVQ DX, R8; \ + ADDQ 40+x, CX; ADCQ $0, R15; \ + MOVQ 48+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; MOVQ R12, 88+z; \ + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADDQ R8, R13; ADCQ $0,R14; \ + \ + XORL R9, R9; \ + MOVQ 48+x, CX; \ + MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ + ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ R13, 96+z; \ + MOVQ R15, AX; NEGQ AX; ANDQ 48+x,AX; ADDQ AX, DX; ADCQ $0, R9; MOVQ DX, R8; \ + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADDQ R8,R14; ADCQ $0, R9; MOVQ R14, 104+z; + + +// integerSqrAdx squares x and stores in z +// Uses: AX, CX, DX, R8-R15, FLAGS +// Instr: x86_64, bmi2, adx +#define integerSqrAdx(z,x) \ + XORL R15, R15; \ + MOVQ 0+x, DX; \ + ;;;;;;;;;;;;;; MULXQ DX, AX, R8; MOVQ AX, 0+z; \ + ADDQ DX, DX; ADCQ $0, R15; CLC; \ + MULXQ 8+x, AX, R9; ADCXQ AX, R8; MOVQ R8, 8+z; \ + MULXQ 16+x, AX, R10; ADCXQ AX, R9; MOVQ $0, R8;\ + MULXQ 24+x, AX, R11; ADCXQ AX, R10; \ + MULXQ 32+x, AX, R12; ADCXQ AX, R11; \ + MULXQ 40+x, AX, R13; ADCXQ AX, R12; \ + MULXQ 48+x, AX, R14; ADCXQ AX, R13; \ + ;;;;;;;;;;;;;;;;;;;; ADCXQ R8, R14; \ + \ + MOVQ 8+x, DX; \ + MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ + MULXQ AX, AX, CX; \ + MOVQ R15, R8; NEGQ R8; ANDQ 8+x, R8; \ + ADDQ AX, R9; MOVQ R9, 16+z; \ + ADCQ CX, R8; \ + ADCQ $0, R11; \ + ADDQ 8+x, DX; \ + ADCQ $0, R15; \ + XORL R9, R9; ;;;;;;;;;;;;;;;;;;;;; ADOXQ R8, R10; \ + MULXQ 16+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; MOVQ R10, 24+z; \ + MULXQ 24+x, AX, CX; ADCXQ AX, R11; ADOXQ CX, R12; MOVQ $0, R10; \ + MULXQ 32+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; \ + MULXQ 40+x, AX, CX; ADCXQ AX, R13; ADOXQ CX, R14; \ + MULXQ 48+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; \ + ;;;;;;;;;;;;;;;;;;; ADCXQ R10, R9; \ + \ + MOVQ 16+x, DX; \ + MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ + MULXQ AX, AX, CX; \ + MOVQ R15, R8; NEGQ R8; ANDQ 16+x, R8; \ + ADDQ AX, R11; MOVQ R11, 32+z; \ + ADCQ CX, R8; \ + ADCQ $0, R13; \ + ADDQ 16+x, DX; \ + ADCQ $0, R15; \ + XORL R11, R11; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R12; \ + MULXQ 24+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; MOVQ R12, 40+z; \ + MULXQ 32+x, AX, CX; ADCXQ AX, R13; ADOXQ CX, R14; MOVQ $0, R12; \ + MULXQ 40+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; \ + MULXQ 48+x, AX, CX; ADCXQ AX, R9; ADOXQ CX, R10; \ + ;;;;;;;;;;;;;;;;;;; ADCXQ R11,R10; \ + \ + MOVQ 24+x, DX; \ + MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ + MULXQ AX, AX, CX; \ + MOVQ R15, R8; NEGQ R8; ANDQ 24+x, R8; \ + ADDQ AX, R13; MOVQ R13, 48+z; \ + ADCQ CX, R8; \ + ADCQ $0, R9; \ + ADDQ 24+x, DX; \ + ADCQ $0, R15; \ + XORL R13, R13; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R14; \ + MULXQ 32+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; MOVQ R14, 56+z; \ + MULXQ 40+x, AX, CX; ADCXQ AX, R9; ADOXQ CX, R10; MOVQ $0, R14; \ + MULXQ 48+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; \ + ;;;;;;;;;;;;;;;;;;; ADCXQ R12,R11; \ + \ + MOVQ 32+x, DX; \ + MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ + MULXQ AX, AX, CX; \ + MOVQ R15, R8; NEGQ R8; ANDQ 32+x, R8; \ + ADDQ AX, R9; MOVQ R9, 64+z; \ + ADCQ CX, R8; \ + ADCQ $0, R11; \ + ADDQ 32+x, DX; \ + ADCQ $0, R15; \ + XORL R9, R9; ;;;;;;;;;;;;;;;;;;;;; ADOXQ R8, R10; \ + MULXQ 40+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; MOVQ R10, 72+z; \ + MULXQ 48+x, AX, CX; ADCXQ AX, R11; ADOXQ CX, R12; \ + ;;;;;;;;;;;;;;;;;;; ADCXQ R13,R12; \ + \ + MOVQ 40+x, DX; \ + MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ + MULXQ AX, AX, CX; \ + MOVQ R15, R8; NEGQ R8; ANDQ 40+x, R8; \ + ADDQ AX, R11; MOVQ R11, 80+z; \ + ADCQ CX, R8; \ + ADCQ $0, R13; \ + ADDQ 40+x, DX; \ + ADCQ $0, R15; \ + XORL R11, R11; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R12; \ + MULXQ 48+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; MOVQ R12, 88+z; \ + ;;;;;;;;;;;;;;;;;;; ADCXQ R14,R13; \ + \ + MOVQ 48+x, DX; \ + MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ + MULXQ AX, AX, CX; \ + MOVQ R15, R8; NEGQ R8; ANDQ 48+x, R8; \ + XORL R10, R10; ;;;;;;;;;;;;;; ADOXQ CX, R14; \ + ;;;;;;;;;;;;;; ADCXQ AX, R13; ;;;;;;;;;;;;;; MOVQ R13, 96+z; \ + ;;;;;;;;;;;;;; ADCXQ R8, R14; MOVQ R14, 104+z; + +// reduceFromDoubleLeg finds a z=x modulo p such that z<2^448 and stores in z +// Uses: AX, R8-R15, FLAGS +// Instr: x86_64 +#define reduceFromDoubleLeg(z,x) \ + /* ( ,2C13,2C12,2C11,2C10|C10,C9,C8, C7) + (C6,...,C0) */ \ + /* (r14, r13, r12, r11, r10,r9,r8,r15) */ \ + MOVQ 80+x,AX; MOVQ AX,R10; \ + MOVQ $0xFFFFFFFF00000000, R8; \ + ANDQ R8,R10; \ + \ + MOVQ $0,R14; \ + MOVQ 104+x,R13; SHLQ $1,R13,R14; \ + MOVQ 96+x,R12; SHLQ $1,R12,R13; \ + MOVQ 88+x,R11; SHLQ $1,R11,R12; \ + MOVQ 72+x, R9; SHLQ $1,R10,R11; \ + MOVQ 64+x, R8; SHLQ $1,R10; \ + MOVQ $0xFFFFFFFF,R15; ANDQ R15,AX; ORQ AX,R10; \ + MOVQ 56+x,R15; \ + \ + ADDQ 0+x,R15; MOVQ R15, 0+z; MOVQ 56+x,R15; \ + ADCQ 8+x, R8; MOVQ R8, 8+z; MOVQ 64+x, R8; \ + ADCQ 16+x, R9; MOVQ R9,16+z; MOVQ 72+x, R9; \ + ADCQ 24+x,R10; MOVQ R10,24+z; MOVQ 80+x,R10; \ + ADCQ 32+x,R11; MOVQ R11,32+z; MOVQ 88+x,R11; \ + ADCQ 40+x,R12; MOVQ R12,40+z; MOVQ 96+x,R12; \ + ADCQ 48+x,R13; MOVQ R13,48+z; MOVQ 104+x,R13; \ + ADCQ $0,R14; \ + /* (c10c9,c9c8,c8c7,c7c13,c13c12,c12c11,c11c10) + (c6,...,c0) */ \ + /* ( r9, r8, r15, r13, r12, r11, r10) */ \ + MOVQ R10, AX; \ + SHRQ $32,R11,R10; \ + SHRQ $32,R12,R11; \ + SHRQ $32,R13,R12; \ + SHRQ $32,R15,R13; \ + SHRQ $32, R8,R15; \ + SHRQ $32, R9, R8; \ + SHRQ $32, AX, R9; \ + \ + ADDQ 0+z,R10; \ + ADCQ 8+z,R11; \ + ADCQ 16+z,R12; \ + ADCQ 24+z,R13; \ + ADCQ 32+z,R15; \ + ADCQ 40+z, R8; \ + ADCQ 48+z, R9; \ + ADCQ $0,R14; \ + /* ( c7) + (c6,...,c0) */ \ + /* (r14) */ \ + MOVQ R14, AX; SHLQ $32, AX; \ + ADDQ R14,R10; MOVQ $0,R14; \ + ADCQ $0,R11; \ + ADCQ $0,R12; \ + ADCQ AX,R13; \ + ADCQ $0,R15; \ + ADCQ $0, R8; \ + ADCQ $0, R9; \ + ADCQ $0,R14; \ + /* ( c7) + (c6,...,c0) */ \ + /* (r14) */ \ + MOVQ R14, AX; SHLQ $32,AX; \ + ADDQ R14,R10; MOVQ R10, 0+z; \ + ADCQ $0,R11; MOVQ R11, 8+z; \ + ADCQ $0,R12; MOVQ R12,16+z; \ + ADCQ AX,R13; MOVQ R13,24+z; \ + ADCQ $0,R15; MOVQ R15,32+z; \ + ADCQ $0, R8; MOVQ R8,40+z; \ + ADCQ $0, R9; MOVQ R9,48+z; + +// reduceFromDoubleAdx finds a z=x modulo p such that z<2^448 and stores in z +// Uses: AX, R8-R15, FLAGS +// Instr: x86_64, adx +#define reduceFromDoubleAdx(z,x) \ + /* ( ,2C13,2C12,2C11,2C10|C10,C9,C8, C7) + (C6,...,C0) */ \ + /* (r14, r13, r12, r11, r10,r9,r8,r15) */ \ + MOVQ 80+x,AX; MOVQ AX,R10; \ + MOVQ $0xFFFFFFFF00000000, R8; \ + ANDQ R8,R10; \ + \ + MOVQ $0,R14; \ + MOVQ 104+x,R13; SHLQ $1,R13,R14; \ + MOVQ 96+x,R12; SHLQ $1,R12,R13; \ + MOVQ 88+x,R11; SHLQ $1,R11,R12; \ + MOVQ 72+x, R9; SHLQ $1,R10,R11; \ + MOVQ 64+x, R8; SHLQ $1,R10; \ + MOVQ $0xFFFFFFFF,R15; ANDQ R15,AX; ORQ AX,R10; \ + MOVQ 56+x,R15; \ + \ + XORL AX,AX; \ + ADCXQ 0+x,R15; MOVQ R15, 0+z; MOVQ 56+x,R15; \ + ADCXQ 8+x, R8; MOVQ R8, 8+z; MOVQ 64+x, R8; \ + ADCXQ 16+x, R9; MOVQ R9,16+z; MOVQ 72+x, R9; \ + ADCXQ 24+x,R10; MOVQ R10,24+z; MOVQ 80+x,R10; \ + ADCXQ 32+x,R11; MOVQ R11,32+z; MOVQ 88+x,R11; \ + ADCXQ 40+x,R12; MOVQ R12,40+z; MOVQ 96+x,R12; \ + ADCXQ 48+x,R13; MOVQ R13,48+z; MOVQ 104+x,R13; \ + ADCXQ AX,R14; \ + /* (c10c9,c9c8,c8c7,c7c13,c13c12,c12c11,c11c10) + (c6,...,c0) */ \ + /* ( r9, r8, r15, r13, r12, r11, r10) */ \ + MOVQ R10, AX; \ + SHRQ $32,R11,R10; \ + SHRQ $32,R12,R11; \ + SHRQ $32,R13,R12; \ + SHRQ $32,R15,R13; \ + SHRQ $32, R8,R15; \ + SHRQ $32, R9, R8; \ + SHRQ $32, AX, R9; \ + \ + XORL AX,AX; \ + ADCXQ 0+z,R10; \ + ADCXQ 8+z,R11; \ + ADCXQ 16+z,R12; \ + ADCXQ 24+z,R13; \ + ADCXQ 32+z,R15; \ + ADCXQ 40+z, R8; \ + ADCXQ 48+z, R9; \ + ADCXQ AX,R14; \ + /* ( c7) + (c6,...,c0) */ \ + /* (r14) */ \ + MOVQ R14, AX; SHLQ $32, AX; \ + CLC; \ + ADCXQ R14,R10; MOVQ $0,R14; \ + ADCXQ R14,R11; \ + ADCXQ R14,R12; \ + ADCXQ AX,R13; \ + ADCXQ R14,R15; \ + ADCXQ R14, R8; \ + ADCXQ R14, R9; \ + ADCXQ R14,R14; \ + /* ( c7) + (c6,...,c0) */ \ + /* (r14) */ \ + MOVQ R14, AX; SHLQ $32, AX; \ + CLC; \ + ADCXQ R14,R10; MOVQ R10, 0+z; MOVQ $0,R14; \ + ADCXQ R14,R11; MOVQ R11, 8+z; \ + ADCXQ R14,R12; MOVQ R12,16+z; \ + ADCXQ AX,R13; MOVQ R13,24+z; \ + ADCXQ R14,R15; MOVQ R15,32+z; \ + ADCXQ R14, R8; MOVQ R8,40+z; \ + ADCXQ R14, R9; MOVQ R9,48+z; + +// addSub calculates two operations: x,y = x+y,x-y +// Uses: AX, DX, R8-R15, FLAGS +#define addSub(x,y) \ + MOVQ 0+x, R8; ADDQ 0+y, R8; \ + MOVQ 8+x, R9; ADCQ 8+y, R9; \ + MOVQ 16+x, R10; ADCQ 16+y, R10; \ + MOVQ 24+x, R11; ADCQ 24+y, R11; \ + MOVQ 32+x, R12; ADCQ 32+y, R12; \ + MOVQ 40+x, R13; ADCQ 40+y, R13; \ + MOVQ 48+x, R14; ADCQ 48+y, R14; \ + MOVQ $0, AX; ADCQ $0, AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + ADDQ AX, R8; MOVQ $0, AX; \ + ADCQ $0, R9; \ + ADCQ $0, R10; \ + ADCQ DX, R11; \ + ADCQ $0, R12; \ + ADCQ $0, R13; \ + ADCQ $0, R14; \ + ADCQ $0, AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + ADDQ AX, R8; MOVQ 0+x,AX; MOVQ R8, 0+x; MOVQ AX, R8; \ + ADCQ $0, R9; MOVQ 8+x,AX; MOVQ R9, 8+x; MOVQ AX, R9; \ + ADCQ $0, R10; MOVQ 16+x,AX; MOVQ R10, 16+x; MOVQ AX, R10; \ + ADCQ DX, R11; MOVQ 24+x,AX; MOVQ R11, 24+x; MOVQ AX, R11; \ + ADCQ $0, R12; MOVQ 32+x,AX; MOVQ R12, 32+x; MOVQ AX, R12; \ + ADCQ $0, R13; MOVQ 40+x,AX; MOVQ R13, 40+x; MOVQ AX, R13; \ + ADCQ $0, R14; MOVQ 48+x,AX; MOVQ R14, 48+x; MOVQ AX, R14; \ + SUBQ 0+y, R8; \ + SBBQ 8+y, R9; \ + SBBQ 16+y, R10; \ + SBBQ 24+y, R11; \ + SBBQ 32+y, R12; \ + SBBQ 40+y, R13; \ + SBBQ 48+y, R14; \ + MOVQ $0, AX; SETCS AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + SUBQ AX, R8; MOVQ $0, AX; \ + SBBQ $0, R9; \ + SBBQ $0, R10; \ + SBBQ DX, R11; \ + SBBQ $0, R12; \ + SBBQ $0, R13; \ + SBBQ $0, R14; \ + SETCS AX; \ + MOVQ AX, DX; \ + SHLQ $32, DX; \ + SUBQ AX, R8; MOVQ R8, 0+y; \ + SBBQ $0, R9; MOVQ R9, 8+y; \ + SBBQ $0, R10; MOVQ R10, 16+y; \ + SBBQ DX, R11; MOVQ R11, 24+y; \ + SBBQ $0, R12; MOVQ R12, 32+y; \ + SBBQ $0, R13; MOVQ R13, 40+y; \ + SBBQ $0, R14; MOVQ R14, 48+y; diff --git a/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s new file mode 100644 index 00000000000..3f1f07c9862 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s @@ -0,0 +1,75 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +#include "textflag.h" +#include "fp_amd64.h" + +// func cmovAmd64(x, y *Elt, n uint) +TEXT ·cmovAmd64(SB),NOSPLIT,$0-24 + MOVQ x+0(FP), DI + MOVQ y+8(FP), SI + MOVQ n+16(FP), BX + cselect(0(DI),0(SI),BX) + RET + +// func cswapAmd64(x, y *Elt, n uint) +TEXT ·cswapAmd64(SB),NOSPLIT,$0-24 + MOVQ x+0(FP), DI + MOVQ y+8(FP), SI + MOVQ n+16(FP), BX + cswap(0(DI),0(SI),BX) + RET + +// func subAmd64(z, x, y *Elt) +TEXT ·subAmd64(SB),NOSPLIT,$0-24 + MOVQ z+0(FP), DI + MOVQ x+8(FP), SI + MOVQ y+16(FP), BX + subtraction(0(DI),0(SI),0(BX)) + RET + +// func addsubAmd64(x, y *Elt) +TEXT ·addsubAmd64(SB),NOSPLIT,$0-16 + MOVQ x+0(FP), DI + MOVQ y+8(FP), SI + addSub(0(DI),0(SI)) + RET + +#define addLegacy \ + additionLeg(0(DI),0(SI),0(BX)) +#define addBmi2Adx \ + additionAdx(0(DI),0(SI),0(BX)) + +#define mulLegacy \ + integerMulLeg(0(SP),0(SI),0(BX)) \ + reduceFromDoubleLeg(0(DI),0(SP)) +#define mulBmi2Adx \ + integerMulAdx(0(SP),0(SI),0(BX)) \ + reduceFromDoubleAdx(0(DI),0(SP)) + +#define sqrLegacy \ + integerSqrLeg(0(SP),0(SI)) \ + reduceFromDoubleLeg(0(DI),0(SP)) +#define sqrBmi2Adx \ + integerSqrAdx(0(SP),0(SI)) \ + reduceFromDoubleAdx(0(DI),0(SP)) + +// func addAmd64(z, x, y *Elt) +TEXT ·addAmd64(SB),NOSPLIT,$0-24 + MOVQ z+0(FP), DI + MOVQ x+8(FP), SI + MOVQ y+16(FP), BX + CHECK_BMI2ADX(LADD, addLegacy, addBmi2Adx) + +// func mulAmd64(z, x, y *Elt) +TEXT ·mulAmd64(SB),NOSPLIT,$112-24 + MOVQ z+0(FP), DI + MOVQ x+8(FP), SI + MOVQ y+16(FP), BX + CHECK_BMI2ADX(LMUL, mulLegacy, mulBmi2Adx) + +// func sqrAmd64(z, x *Elt) +TEXT ·sqrAmd64(SB),NOSPLIT,$112-16 + MOVQ z+0(FP), DI + MOVQ x+8(FP), SI + CHECK_BMI2ADX(LSQR, sqrLegacy, sqrBmi2Adx) diff --git a/src/vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go new file mode 100644 index 00000000000..47a0b63205f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go @@ -0,0 +1,339 @@ +package fp448 + +import ( + "encoding/binary" + "math/bits" +) + +func cmovGeneric(x, y *Elt, n uint) { + m := -uint64(n & 0x1) + x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) + x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) + x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) + x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) + x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) + x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) + x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) + + y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) + y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) + y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) + y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) + y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) + y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) + y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) + + x0 = (x0 &^ m) | (y0 & m) + x1 = (x1 &^ m) | (y1 & m) + x2 = (x2 &^ m) | (y2 & m) + x3 = (x3 &^ m) | (y3 & m) + x4 = (x4 &^ m) | (y4 & m) + x5 = (x5 &^ m) | (y5 & m) + x6 = (x6 &^ m) | (y6 & m) + + binary.LittleEndian.PutUint64(x[0*8:1*8], x0) + binary.LittleEndian.PutUint64(x[1*8:2*8], x1) + binary.LittleEndian.PutUint64(x[2*8:3*8], x2) + binary.LittleEndian.PutUint64(x[3*8:4*8], x3) + binary.LittleEndian.PutUint64(x[4*8:5*8], x4) + binary.LittleEndian.PutUint64(x[5*8:6*8], x5) + binary.LittleEndian.PutUint64(x[6*8:7*8], x6) +} + +func cswapGeneric(x, y *Elt, n uint) { + m := -uint64(n & 0x1) + x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) + x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) + x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) + x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) + x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) + x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) + x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) + + y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) + y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) + y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) + y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) + y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) + y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) + y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) + + t0 := m & (x0 ^ y0) + t1 := m & (x1 ^ y1) + t2 := m & (x2 ^ y2) + t3 := m & (x3 ^ y3) + t4 := m & (x4 ^ y4) + t5 := m & (x5 ^ y5) + t6 := m & (x6 ^ y6) + x0 ^= t0 + x1 ^= t1 + x2 ^= t2 + x3 ^= t3 + x4 ^= t4 + x5 ^= t5 + x6 ^= t6 + y0 ^= t0 + y1 ^= t1 + y2 ^= t2 + y3 ^= t3 + y4 ^= t4 + y5 ^= t5 + y6 ^= t6 + + binary.LittleEndian.PutUint64(x[0*8:1*8], x0) + binary.LittleEndian.PutUint64(x[1*8:2*8], x1) + binary.LittleEndian.PutUint64(x[2*8:3*8], x2) + binary.LittleEndian.PutUint64(x[3*8:4*8], x3) + binary.LittleEndian.PutUint64(x[4*8:5*8], x4) + binary.LittleEndian.PutUint64(x[5*8:6*8], x5) + binary.LittleEndian.PutUint64(x[6*8:7*8], x6) + + binary.LittleEndian.PutUint64(y[0*8:1*8], y0) + binary.LittleEndian.PutUint64(y[1*8:2*8], y1) + binary.LittleEndian.PutUint64(y[2*8:3*8], y2) + binary.LittleEndian.PutUint64(y[3*8:4*8], y3) + binary.LittleEndian.PutUint64(y[4*8:5*8], y4) + binary.LittleEndian.PutUint64(y[5*8:6*8], y5) + binary.LittleEndian.PutUint64(y[6*8:7*8], y6) +} + +func addGeneric(z, x, y *Elt) { + x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) + x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) + x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) + x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) + x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) + x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) + x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) + + y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) + y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) + y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) + y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) + y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) + y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) + y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) + + z0, c0 := bits.Add64(x0, y0, 0) + z1, c1 := bits.Add64(x1, y1, c0) + z2, c2 := bits.Add64(x2, y2, c1) + z3, c3 := bits.Add64(x3, y3, c2) + z4, c4 := bits.Add64(x4, y4, c3) + z5, c5 := bits.Add64(x5, y5, c4) + z6, z7 := bits.Add64(x6, y6, c5) + + z0, c0 = bits.Add64(z0, z7, 0) + z1, c1 = bits.Add64(z1, 0, c0) + z2, c2 = bits.Add64(z2, 0, c1) + z3, c3 = bits.Add64(z3, z7<<32, c2) + z4, c4 = bits.Add64(z4, 0, c3) + z5, c5 = bits.Add64(z5, 0, c4) + z6, z7 = bits.Add64(z6, 0, c5) + + z0, c0 = bits.Add64(z0, z7, 0) + z1, c1 = bits.Add64(z1, 0, c0) + z2, c2 = bits.Add64(z2, 0, c1) + z3, c3 = bits.Add64(z3, z7<<32, c2) + z4, c4 = bits.Add64(z4, 0, c3) + z5, c5 = bits.Add64(z5, 0, c4) + z6, _ = bits.Add64(z6, 0, c5) + + binary.LittleEndian.PutUint64(z[0*8:1*8], z0) + binary.LittleEndian.PutUint64(z[1*8:2*8], z1) + binary.LittleEndian.PutUint64(z[2*8:3*8], z2) + binary.LittleEndian.PutUint64(z[3*8:4*8], z3) + binary.LittleEndian.PutUint64(z[4*8:5*8], z4) + binary.LittleEndian.PutUint64(z[5*8:6*8], z5) + binary.LittleEndian.PutUint64(z[6*8:7*8], z6) +} + +func subGeneric(z, x, y *Elt) { + x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) + x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) + x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) + x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) + x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) + x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) + x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) + + y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) + y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) + y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) + y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) + y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) + y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) + y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) + + z0, c0 := bits.Sub64(x0, y0, 0) + z1, c1 := bits.Sub64(x1, y1, c0) + z2, c2 := bits.Sub64(x2, y2, c1) + z3, c3 := bits.Sub64(x3, y3, c2) + z4, c4 := bits.Sub64(x4, y4, c3) + z5, c5 := bits.Sub64(x5, y5, c4) + z6, z7 := bits.Sub64(x6, y6, c5) + + z0, c0 = bits.Sub64(z0, z7, 0) + z1, c1 = bits.Sub64(z1, 0, c0) + z2, c2 = bits.Sub64(z2, 0, c1) + z3, c3 = bits.Sub64(z3, z7<<32, c2) + z4, c4 = bits.Sub64(z4, 0, c3) + z5, c5 = bits.Sub64(z5, 0, c4) + z6, z7 = bits.Sub64(z6, 0, c5) + + z0, c0 = bits.Sub64(z0, z7, 0) + z1, c1 = bits.Sub64(z1, 0, c0) + z2, c2 = bits.Sub64(z2, 0, c1) + z3, c3 = bits.Sub64(z3, z7<<32, c2) + z4, c4 = bits.Sub64(z4, 0, c3) + z5, c5 = bits.Sub64(z5, 0, c4) + z6, _ = bits.Sub64(z6, 0, c5) + + binary.LittleEndian.PutUint64(z[0*8:1*8], z0) + binary.LittleEndian.PutUint64(z[1*8:2*8], z1) + binary.LittleEndian.PutUint64(z[2*8:3*8], z2) + binary.LittleEndian.PutUint64(z[3*8:4*8], z3) + binary.LittleEndian.PutUint64(z[4*8:5*8], z4) + binary.LittleEndian.PutUint64(z[5*8:6*8], z5) + binary.LittleEndian.PutUint64(z[6*8:7*8], z6) +} + +func addsubGeneric(x, y *Elt) { + z := &Elt{} + addGeneric(z, x, y) + subGeneric(y, x, y) + *x = *z +} + +func mulGeneric(z, x, y *Elt) { + x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) + x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) + x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) + x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) + x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) + x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) + x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) + + y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) + y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) + y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) + y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) + y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) + y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) + y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) + + yy := [7]uint64{y0, y1, y2, y3, y4, y5, y6} + zz := [7]uint64{} + + yi := yy[0] + h0, l0 := bits.Mul64(x0, yi) + h1, l1 := bits.Mul64(x1, yi) + h2, l2 := bits.Mul64(x2, yi) + h3, l3 := bits.Mul64(x3, yi) + h4, l4 := bits.Mul64(x4, yi) + h5, l5 := bits.Mul64(x5, yi) + h6, l6 := bits.Mul64(x6, yi) + + zz[0] = l0 + a0, c0 := bits.Add64(h0, l1, 0) + a1, c1 := bits.Add64(h1, l2, c0) + a2, c2 := bits.Add64(h2, l3, c1) + a3, c3 := bits.Add64(h3, l4, c2) + a4, c4 := bits.Add64(h4, l5, c3) + a5, c5 := bits.Add64(h5, l6, c4) + a6, _ := bits.Add64(h6, 0, c5) + + for i := 1; i < 7; i++ { + yi = yy[i] + h0, l0 = bits.Mul64(x0, yi) + h1, l1 = bits.Mul64(x1, yi) + h2, l2 = bits.Mul64(x2, yi) + h3, l3 = bits.Mul64(x3, yi) + h4, l4 = bits.Mul64(x4, yi) + h5, l5 = bits.Mul64(x5, yi) + h6, l6 = bits.Mul64(x6, yi) + + zz[i], c0 = bits.Add64(a0, l0, 0) + a0, c1 = bits.Add64(a1, l1, c0) + a1, c2 = bits.Add64(a2, l2, c1) + a2, c3 = bits.Add64(a3, l3, c2) + a3, c4 = bits.Add64(a4, l4, c3) + a4, c5 = bits.Add64(a5, l5, c4) + a5, a6 = bits.Add64(a6, l6, c5) + + a0, c0 = bits.Add64(a0, h0, 0) + a1, c1 = bits.Add64(a1, h1, c0) + a2, c2 = bits.Add64(a2, h2, c1) + a3, c3 = bits.Add64(a3, h3, c2) + a4, c4 = bits.Add64(a4, h4, c3) + a5, c5 = bits.Add64(a5, h5, c4) + a6, _ = bits.Add64(a6, h6, c5) + } + red64(z, &zz, &[7]uint64{a0, a1, a2, a3, a4, a5, a6}) +} + +func sqrGeneric(z, x *Elt) { mulGeneric(z, x, x) } + +func red64(z *Elt, l, h *[7]uint64) { + /* (2C13, 2C12, 2C11, 2C10|C10, C9, C8, C7) + (C6,...,C0) */ + h0 := h[0] + h1 := h[1] + h2 := h[2] + h3 := ((h[3] & (0xFFFFFFFF << 32)) << 1) | (h[3] & 0xFFFFFFFF) + h4 := (h[3] >> 63) | (h[4] << 1) + h5 := (h[4] >> 63) | (h[5] << 1) + h6 := (h[5] >> 63) | (h[6] << 1) + h7 := (h[6] >> 63) + + l0, c0 := bits.Add64(h0, l[0], 0) + l1, c1 := bits.Add64(h1, l[1], c0) + l2, c2 := bits.Add64(h2, l[2], c1) + l3, c3 := bits.Add64(h3, l[3], c2) + l4, c4 := bits.Add64(h4, l[4], c3) + l5, c5 := bits.Add64(h5, l[5], c4) + l6, c6 := bits.Add64(h6, l[6], c5) + l7, _ := bits.Add64(h7, 0, c6) + + /* (C10C9, C9C8,C8C7,C7C13,C13C12,C12C11,C11C10) + (C6,...,C0) */ + h0 = (h[3] >> 32) | (h[4] << 32) + h1 = (h[4] >> 32) | (h[5] << 32) + h2 = (h[5] >> 32) | (h[6] << 32) + h3 = (h[6] >> 32) | (h[0] << 32) + h4 = (h[0] >> 32) | (h[1] << 32) + h5 = (h[1] >> 32) | (h[2] << 32) + h6 = (h[2] >> 32) | (h[3] << 32) + + l0, c0 = bits.Add64(l0, h0, 0) + l1, c1 = bits.Add64(l1, h1, c0) + l2, c2 = bits.Add64(l2, h2, c1) + l3, c3 = bits.Add64(l3, h3, c2) + l4, c4 = bits.Add64(l4, h4, c3) + l5, c5 = bits.Add64(l5, h5, c4) + l6, c6 = bits.Add64(l6, h6, c5) + l7, _ = bits.Add64(l7, 0, c6) + + /* (C7) + (C6,...,C0) */ + l0, c0 = bits.Add64(l0, l7, 0) + l1, c1 = bits.Add64(l1, 0, c0) + l2, c2 = bits.Add64(l2, 0, c1) + l3, c3 = bits.Add64(l3, l7<<32, c2) + l4, c4 = bits.Add64(l4, 0, c3) + l5, c5 = bits.Add64(l5, 0, c4) + l6, l7 = bits.Add64(l6, 0, c5) + + /* (C7) + (C6,...,C0) */ + l0, c0 = bits.Add64(l0, l7, 0) + l1, c1 = bits.Add64(l1, 0, c0) + l2, c2 = bits.Add64(l2, 0, c1) + l3, c3 = bits.Add64(l3, l7<<32, c2) + l4, c4 = bits.Add64(l4, 0, c3) + l5, c5 = bits.Add64(l5, 0, c4) + l6, _ = bits.Add64(l6, 0, c5) + + binary.LittleEndian.PutUint64(z[0*8:1*8], l0) + binary.LittleEndian.PutUint64(z[1*8:2*8], l1) + binary.LittleEndian.PutUint64(z[2*8:3*8], l2) + binary.LittleEndian.PutUint64(z[3*8:4*8], l3) + binary.LittleEndian.PutUint64(z[4*8:5*8], l4) + binary.LittleEndian.PutUint64(z[5*8:6*8], l5) + binary.LittleEndian.PutUint64(z[6*8:7*8], l6) +} diff --git a/src/vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go new file mode 100644 index 00000000000..a62225d2962 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go @@ -0,0 +1,12 @@ +//go:build !amd64 || purego +// +build !amd64 purego + +package fp448 + +func cmov(x, y *Elt, n uint) { cmovGeneric(x, y, n) } +func cswap(x, y *Elt, n uint) { cswapGeneric(x, y, n) } +func add(z, x, y *Elt) { addGeneric(z, x, y) } +func sub(z, x, y *Elt) { subGeneric(z, x, y) } +func addsub(x, y *Elt) { addsubGeneric(x, y) } +func mul(z, x, y *Elt) { mulGeneric(z, x, y) } +func sqr(z, x *Elt) { sqrGeneric(z, x) } diff --git a/src/vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go b/src/vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go new file mode 100644 index 00000000000..2d7afc80598 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go @@ -0,0 +1,75 @@ +//go:build gofuzz +// +build gofuzz + +// How to run the fuzzer: +// +// $ go get -u github.com/dvyukov/go-fuzz/go-fuzz +// $ go get -u github.com/dvyukov/go-fuzz/go-fuzz-build +// $ go-fuzz-build -libfuzzer -func FuzzReduction -o lib.a +// $ clang -fsanitize=fuzzer lib.a -o fu.exe +// $ ./fu.exe +package fp448 + +import ( + "encoding/binary" + "fmt" + "math/big" + + "github.com/cloudflare/circl/internal/conv" +) + +// FuzzReduction is a fuzzer target for red64 function, which reduces t +// (112 bits) to a number t' (56 bits) congruent modulo p448. +func FuzzReduction(data []byte) int { + if len(data) != 2*Size { + return -1 + } + var got, want Elt + var lo, hi [7]uint64 + a := data[:Size] + b := data[Size:] + lo[0] = binary.LittleEndian.Uint64(a[0*8 : 1*8]) + lo[1] = binary.LittleEndian.Uint64(a[1*8 : 2*8]) + lo[2] = binary.LittleEndian.Uint64(a[2*8 : 3*8]) + lo[3] = binary.LittleEndian.Uint64(a[3*8 : 4*8]) + lo[4] = binary.LittleEndian.Uint64(a[4*8 : 5*8]) + lo[5] = binary.LittleEndian.Uint64(a[5*8 : 6*8]) + lo[6] = binary.LittleEndian.Uint64(a[6*8 : 7*8]) + + hi[0] = binary.LittleEndian.Uint64(b[0*8 : 1*8]) + hi[1] = binary.LittleEndian.Uint64(b[1*8 : 2*8]) + hi[2] = binary.LittleEndian.Uint64(b[2*8 : 3*8]) + hi[3] = binary.LittleEndian.Uint64(b[3*8 : 4*8]) + hi[4] = binary.LittleEndian.Uint64(b[4*8 : 5*8]) + hi[5] = binary.LittleEndian.Uint64(b[5*8 : 6*8]) + hi[6] = binary.LittleEndian.Uint64(b[6*8 : 7*8]) + + red64(&got, &lo, &hi) + + t := conv.BytesLe2BigInt(data[:2*Size]) + + two448 := big.NewInt(1) + two448.Lsh(two448, 448) // 2^448 + mask448 := big.NewInt(1) + mask448.Sub(two448, mask448) // 2^448-1 + two224plus1 := big.NewInt(1) + two224plus1.Lsh(two224plus1, 224) + two224plus1.Add(two224plus1, big.NewInt(1)) // 2^224+1 + + var loBig, hiBig big.Int + for t.Cmp(two448) >= 0 { + loBig.And(t, mask448) + hiBig.Rsh(t, 448) + t.Mul(&hiBig, two224plus1) + t.Add(t, &loBig) + } + conv.BigInt2BytesLe(want[:], t) + + if got != want { + fmt.Printf("in: %v\n", conv.BytesLe2BigInt(data[:2*Size])) + fmt.Printf("got: %v\n", got) + fmt.Printf("want: %v\n", want) + panic("error found") + } + return 1 +} diff --git a/src/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go b/src/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go new file mode 100644 index 00000000000..a43851b8bb2 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go @@ -0,0 +1,122 @@ +// Package mlsbset provides a constant-time exponentiation method with precomputation. +// +// References: "Efficient and secure algorithms for GLV-based scalar +// multiplication and their implementation on GLV–GLS curves" by (Faz-Hernandez et al.) +// - https://doi.org/10.1007/s13389-014-0085-7 +// - https://eprint.iacr.org/2013/158 +package mlsbset + +import ( + "errors" + "fmt" + "math/big" + + "github.com/cloudflare/circl/internal/conv" +) + +// EltG is a group element. +type EltG interface{} + +// EltP is a precomputed group element. +type EltP interface{} + +// Group defines the operations required by MLSBSet exponentiation method. +type Group interface { + Identity() EltG // Returns the identity of the group. + Sqr(x EltG) // Calculates x = x^2. + Mul(x EltG, y EltP) // Calculates x = x*y. + NewEltP() EltP // Returns an arbitrary precomputed element. + ExtendedEltP() EltP // Returns the precomputed element x^(2^(w*d)). + Lookup(a EltP, v uint, s, u int32) // Sets a = s*T[v][u]. +} + +// Params contains the parameters of the encoding. +type Params struct { + T uint // T is the maximum size (in bits) of exponents. + V uint // V is the number of tables. + W uint // W is the window size. + E uint // E is the number of digits per table. + D uint // D is the number of digits in total. + L uint // L is the length of the code. +} + +// Encoder allows to convert integers into valid powers. +type Encoder struct{ p Params } + +// New produces an encoder of the MLSBSet algorithm. +func New(t, v, w uint) (Encoder, error) { + if !(t > 1 && v >= 1 && w >= 2) { + return Encoder{}, errors.New("t>1, v>=1, w>=2") + } + e := (t + w*v - 1) / (w * v) + d := e * v + l := d * w + return Encoder{Params{t, v, w, e, d, l}}, nil +} + +// Encode converts an odd integer k into a valid power for exponentiation. +func (m Encoder) Encode(k []byte) (*Power, error) { + if len(k) == 0 { + return nil, errors.New("empty slice") + } + if !(len(k) <= int(m.p.L+7)>>3) { + return nil, errors.New("k too big") + } + if k[0]%2 == 0 { + return nil, errors.New("k must be odd") + } + ap := int((m.p.L+7)/8) - len(k) + k = append(k, make([]byte, ap)...) + s := m.signs(k) + b := make([]int32, m.p.L-m.p.D) + c := conv.BytesLe2BigInt(k) + c.Rsh(c, m.p.D) + var bi big.Int + for i := m.p.D; i < m.p.L; i++ { + c0 := int32(c.Bit(0)) + b[i-m.p.D] = s[i%m.p.D] * c0 + bi.SetInt64(int64(b[i-m.p.D] >> 1)) + c.Rsh(c, 1) + c.Sub(c, &bi) + } + carry := int(c.Int64()) + return &Power{m, s, b, carry}, nil +} + +// signs calculates the set of signs. +func (m Encoder) signs(k []byte) []int32 { + s := make([]int32, m.p.D) + s[m.p.D-1] = 1 + for i := uint(1); i < m.p.D; i++ { + ki := int32((k[i>>3] >> (i & 0x7)) & 0x1) + s[i-1] = 2*ki - 1 + } + return s +} + +// GetParams returns the complementary parameters of the encoding. +func (m Encoder) GetParams() Params { return m.p } + +// tableSize returns the size of each table. +func (m Encoder) tableSize() uint { return 1 << (m.p.W - 1) } + +// Elts returns the total number of elements that must be precomputed. +func (m Encoder) Elts() uint { return m.p.V * m.tableSize() } + +// IsExtended returns true if the element x^(2^(wd)) must be calculated. +func (m Encoder) IsExtended() bool { q := m.p.T / (m.p.V * m.p.W); return m.p.T == q*m.p.V*m.p.W } + +// Ops returns the number of squares and multiplications executed during an exponentiation. +func (m Encoder) Ops() (S uint, M uint) { + S = m.p.E + M = m.p.E * m.p.V + if m.IsExtended() { + M++ + } + return +} + +func (m Encoder) String() string { + return fmt.Sprintf("T: %v W: %v V: %v e: %v d: %v l: %v wv|t: %v", + m.p.T, m.p.W, m.p.V, m.p.E, m.p.D, m.p.L, m.IsExtended()) +} diff --git a/src/vendor/github.com/cloudflare/circl/math/mlsbset/power.go b/src/vendor/github.com/cloudflare/circl/math/mlsbset/power.go new file mode 100644 index 00000000000..3f214c3046a --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/mlsbset/power.go @@ -0,0 +1,64 @@ +package mlsbset + +import "fmt" + +// Power is a valid exponent produced by the MLSBSet encoding algorithm. +type Power struct { + set Encoder // parameters of code. + s []int32 // set of signs. + b []int32 // set of digits. + c int // carry is {0,1}. +} + +// Exp is calculates x^k, where x is a predetermined element of a group G. +func (p *Power) Exp(G Group) EltG { + a, b := G.Identity(), G.NewEltP() + for e := int(p.set.p.E - 1); e >= 0; e-- { + G.Sqr(a) + for v := uint(0); v < p.set.p.V; v++ { + sgnElt, idElt := p.Digit(v, uint(e)) + G.Lookup(b, v, sgnElt, idElt) + G.Mul(a, b) + } + } + if p.set.IsExtended() && p.c == 1 { + G.Mul(a, G.ExtendedEltP()) + } + return a +} + +// Digit returns the (v,e)-th digit and its sign. +func (p *Power) Digit(v, e uint) (sgn, dig int32) { + sgn = p.bit(0, v, e) + dig = 0 + for i := p.set.p.W - 1; i > 0; i-- { + dig = 2*dig + p.bit(i, v, e) + } + mask := dig >> 31 + dig = (dig + mask) ^ mask + return sgn, dig +} + +// bit returns the (w,v,e)-th bit of the code. +func (p *Power) bit(w, v, e uint) int32 { + if !(w < p.set.p.W && + v < p.set.p.V && + e < p.set.p.E) { + panic(fmt.Errorf("indexes outside (%v,%v,%v)", w, v, e)) + } + if w == 0 { + return p.s[p.set.p.E*v+e] + } + return p.b[p.set.p.D*(w-1)+p.set.p.E*v+e] +} + +func (p *Power) String() string { + dig := "" + for j := uint(0); j < p.set.p.V; j++ { + for i := uint(0); i < p.set.p.E; i++ { + s, d := p.Digit(j, i) + dig += fmt.Sprintf("(%2v,%2v) = %+2v %+2v\n", j, i, s, d) + } + } + return fmt.Sprintf("len: %v\ncarry: %v\ndigits:\n%v", len(p.b)+len(p.s), p.c, dig) +} diff --git a/src/vendor/github.com/cloudflare/circl/math/primes.go b/src/vendor/github.com/cloudflare/circl/math/primes.go new file mode 100644 index 00000000000..158fd83a7aa --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/primes.go @@ -0,0 +1,34 @@ +package math + +import ( + "crypto/rand" + "io" + "math/big" +) + +// IsSafePrime reports whether p is (probably) a safe prime. +// The prime p=2*q+1 is safe prime if both p and q are primes. +// Note that ProbablyPrime is not suitable for judging primes +// that an adversary may have crafted to fool the test. +func IsSafePrime(p *big.Int) bool { + pdiv2 := new(big.Int).Rsh(p, 1) + return p.ProbablyPrime(20) && pdiv2.ProbablyPrime(20) +} + +// SafePrime returns a number of the given bit length that is a safe prime with high probability. +// The number returned p=2*q+1 is a safe prime if both p and q are primes. +// SafePrime will return error for any error returned by rand.Read or if bits < 2. +func SafePrime(random io.Reader, bits int) (*big.Int, error) { + one := big.NewInt(1) + p := new(big.Int) + for { + q, err := rand.Prime(random, bits-1) + if err != nil { + return nil, err + } + p.Lsh(q, 1).Add(p, one) + if p.ProbablyPrime(20) { + return p, nil + } + } +} diff --git a/src/vendor/github.com/cloudflare/circl/math/wnaf.go b/src/vendor/github.com/cloudflare/circl/math/wnaf.go new file mode 100644 index 00000000000..94a1ec50429 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/wnaf.go @@ -0,0 +1,84 @@ +// Package math provides some utility functions for big integers. +package math + +import "math/big" + +// SignedDigit obtains the signed-digit recoding of n and returns a list L of +// digits such that n = sum( L[i]*2^(i*(w-1)) ), and each L[i] is an odd number +// in the set {±1, ±3, ..., ±2^(w-1)-1}. The third parameter ensures that the +// output has ceil(l/(w-1)) digits. +// +// Restrictions: +// - n is odd and n > 0. +// - 1 < w < 32. +// - l >= bit length of n. +// +// References: +// - Alg.6 in "Exponent Recoding and Regular Exponentiation Algorithms" +// by Joye-Tunstall. http://doi.org/10.1007/978-3-642-02384-2_21 +// - Alg.6 in "Selecting Elliptic Curves for Cryptography: An Efficiency and +// Security Analysis" by Bos et al. http://doi.org/10.1007/s13389-015-0097-y +func SignedDigit(n *big.Int, w, l uint) []int32 { + if n.Sign() <= 0 || n.Bit(0) == 0 { + panic("n must be non-zero, odd, and positive") + } + if w <= 1 || w >= 32 { + panic("Verify that 1 < w < 32") + } + if uint(n.BitLen()) > l { + panic("n is too big to fit in l digits") + } + lenN := (l + (w - 1) - 1) / (w - 1) // ceil(l/(w-1)) + L := make([]int32, lenN+1) + var k, v big.Int + k.Set(n) + + var i uint + for i = 0; i < lenN; i++ { + words := k.Bits() + value := int32(words[0] & ((1 << w) - 1)) + value -= int32(1) << (w - 1) + L[i] = value + v.SetInt64(int64(value)) + k.Sub(&k, &v) + k.Rsh(&k, w-1) + } + L[i] = int32(k.Int64()) + return L +} + +// OmegaNAF obtains the window-w Non-Adjacent Form of a positive number n and +// 1 < w < 32. The returned slice L holds n = sum( L[i]*2^i ). +// +// Reference: +// - Alg.9 "Efficient arithmetic on Koblitz curves" by Solinas. +// http://doi.org/10.1023/A:1008306223194 +func OmegaNAF(n *big.Int, w uint) (L []int32) { + if n.Sign() < 0 { + panic("n must be positive") + } + if w <= 1 || w >= 32 { + panic("Verify that 1 < w < 32") + } + + L = make([]int32, n.BitLen()+1) + var k, v big.Int + k.Set(n) + + i := 0 + for ; k.Sign() > 0; i++ { + value := int32(0) + if k.Bit(0) == 1 { + words := k.Bits() + value = int32(words[0] & ((1 << w) - 1)) + if value >= (int32(1) << (w - 1)) { + value -= int32(1) << w + } + v.SetInt64(int64(value)) + k.Sub(&k, &v) + } + L[i] = value + k.Rsh(&k, 1) + } + return L[:i] +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.go new file mode 100644 index 00000000000..2c96563c7dc --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.go @@ -0,0 +1,302 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package common + +import ( + "golang.org/x/sys/cpu" +) + +// ZetasAVX2 contains all ζ used in NTT (like the Zetas array), but also +// the values int16(zeta * 62209) for each zeta, which is used in +// Montgomery reduction. There is some duplication and reordering as +// compared to Zetas to make it more convenient for use with AVX2. +var ZetasAVX2 = [...]int16{ + // level 1: int16(Zetas[1]*62209) and Zetas[1] + 31499, 2571, + + // level 2 + // + // int16(Zetas[2]*62209), Zetas[2], int16(Zetas[3]*62209), Zetas[3] + 14746, 2970, 788, 1812, + + // level 3, like level 2. + 13525, 1493, -12402, 1422, 28191, 287, -16694, 202, + + 0, 0, // padding + + // layer 4. offset: 1*16 + // + // The precomputed multiplication and zetas are grouped by 16 at a + // time as used in the set of butterflies, etc. + -20906, -20906, -20906, -20906, -20906, -20906, -20906, -20906, + 27758, 27758, 27758, 27758, 27758, 27758, 27758, 27758, + 3158, 3158, 3158, 3158, 3158, 3158, 3158, 3158, + 622, 622, 622, 622, 622, 622, 622, 622, + -3799, -3799, -3799, -3799, -3799, -3799, -3799, -3799, + -15690, -15690, -15690, -15690, -15690, -15690, -15690, -15690, + 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, + 182, 182, 182, 182, 182, 182, 182, 182, + 10690, 10690, 10690, 10690, 10690, 10690, 10690, 10690, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 962, 962, 962, 962, 962, 962, 962, 962, + 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2127, + -11201, -11201, -11201, -11201, -11201, -11201, -11201, -11201, + 31164, 31164, 31164, 31164, 31164, 31164, 31164, 31164, + 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, + 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, + + // layer 5. offset: 9*16 + -5827, -5827, -5827, -5827, 17364, 17364, 17364, 17364, + -26360, -26360, -26360, -26360, -29057, -29057, -29057, -29057, + 573, 573, 573, 573, 2004, 2004, 2004, 2004, + 264, 264, 264, 264, 383, 383, 383, 383, + 5572, 5572, 5572, 5572, -1102, -1102, -1102, -1102, + 21439, 21439, 21439, 21439, -26241, -26241, -26241, -26241, + 2500, 2500, 2500, 2500, 1458, 1458, 1458, 1458, + 1727, 1727, 1727, 1727, 3199, 3199, 3199, 3199, + -28072, -28072, -28072, -28072, 24313, 24313, 24313, 24313, + -10532, -10532, -10532, -10532, 8800, 8800, 8800, 8800, + 2648, 2648, 2648, 2648, 1017, 1017, 1017, 1017, + 732, 732, 732, 732, 608, 608, 608, 608, + 18427, 18427, 18427, 18427, 8859, 8859, 8859, 8859, + 26676, 26676, 26676, 26676, -16162, -16162, -16162, -16162, + 1787, 1787, 1787, 1787, 411, 411, 411, 411, + 3124, 3124, 3124, 3124, 1758, 1758, 1758, 1758, + + // layer 6. offset: 17*16 + -5689, -5689, -6516, -6516, 1497, 1497, 30967, 30967, + -23564, -23564, 20179, 20179, 20711, 20711, 25081, 25081, + 1223, 1223, 652, 652, 2777, 2777, 1015, 1015, + 2036, 2036, 1491, 1491, 3047, 3047, 1785, 1785, + -12796, -12796, 26617, 26617, 16065, 16065, -12441, -12441, + 9135, 9135, -649, -649, -25986, -25986, 27837, 27837, + 516, 516, 3321, 3321, 3009, 3009, 2663, 2663, + 1711, 1711, 2167, 2167, 126, 126, 1469, 1469, + 19884, 19884, -28249, -28249, -15886, -15886, -8898, -8898, + -28309, -28309, 9076, 9076, -30198, -30198, 18250, 18250, + 2476, 2476, 3239, 3239, 3058, 3058, 830, 830, + 107, 107, 1908, 1908, 3082, 3082, 2378, 2378, + 13427, 13427, 14017, 14017, -29155, -29155, -12756, -12756, + 16832, 16832, 4312, 4312, -24155, -24155, -17914, -17914, + 2931, 2931, 961, 961, 1821, 1821, 2604, 2604, + 448, 448, 2264, 2264, 677, 677, 2054, 2054, + + // layer 7. offset: 25*16 + -334, 11182, -11477, 13387, -32226, -14233, 20494, -21655, + -27738, 13131, 945, -4586, -14882, 23093, 6182, 5493, + 2226, 430, 555, 843, 2078, 871, 1550, 105, + 422, 587, 177, 3094, 3038, 2869, 1574, 1653, + 32011, -32502, 10631, 30318, 29176, -18741, -28761, 12639, + -18485, 20100, 17561, 18525, -14430, 19529, -5275, -12618, + 3083, 778, 1159, 3182, 2552, 1483, 2727, 1119, + 1739, 644, 2457, 349, 418, 329, 3173, 3254, + -31183, 20297, 25435, 2146, -7382, 15356, 24392, -32384, + -20926, -6279, 10946, -14902, 24215, -11044, 16990, 14470, + 817, 1097, 603, 610, 1322, 2044, 1864, 384, + 2114, 3193, 1218, 1994, 2455, 220, 2142, 1670, + 10336, -21497, -7933, -20198, -22501, 23211, 10907, -17442, + 31637, -23859, 28644, -20257, 23998, 7757, -17422, 23132, + 2144, 1799, 2051, 794, 1819, 2475, 2459, 478, + 3221, 3021, 996, 991, 958, 1869, 1522, 1628, + + // layer 1 inverse + 23132, -17422, 7757, 23998, -20257, 28644, -23859, 31637, + -17442, 10907, 23211, -22501, -20198, -7933, -21497, 10336, + 1628, 1522, 1869, 958, 991, 996, 3021, 3221, + 478, 2459, 2475, 1819, 794, 2051, 1799, 2144, + 14470, 16990, -11044, 24215, -14902, 10946, -6279, -20926, + -32384, 24392, 15356, -7382, 2146, 25435, 20297, -31183, + 1670, 2142, 220, 2455, 1994, 1218, 3193, 2114, + 384, 1864, 2044, 1322, 610, 603, 1097, 817, + -12618, -5275, 19529, -14430, 18525, 17561, 20100, -18485, + 12639, -28761, -18741, 29176, 30318, 10631, -32502, 32011, + 3254, 3173, 329, 418, 349, 2457, 644, 1739, + 1119, 2727, 1483, 2552, 3182, 1159, 778, 3083, + 5493, 6182, 23093, -14882, -4586, 945, 13131, -27738, + -21655, 20494, -14233, -32226, 13387, -11477, 11182, -334, + 1653, 1574, 2869, 3038, 3094, 177, 587, 422, + 105, 1550, 871, 2078, 843, 555, 430, 2226, + + // layer 2 inverse + -17914, -17914, -24155, -24155, 4312, 4312, 16832, 16832, + -12756, -12756, -29155, -29155, 14017, 14017, 13427, 13427, + 2054, 2054, 677, 677, 2264, 2264, 448, 448, + 2604, 2604, 1821, 1821, 961, 961, 2931, 2931, + 18250, 18250, -30198, -30198, 9076, 9076, -28309, -28309, + -8898, -8898, -15886, -15886, -28249, -28249, 19884, 19884, + 2378, 2378, 3082, 3082, 1908, 1908, 107, 107, + 830, 830, 3058, 3058, 3239, 3239, 2476, 2476, + 27837, 27837, -25986, -25986, -649, -649, 9135, 9135, + -12441, -12441, 16065, 16065, 26617, 26617, -12796, -12796, + 1469, 1469, 126, 126, 2167, 2167, 1711, 1711, + 2663, 2663, 3009, 3009, 3321, 3321, 516, 516, + 25081, 25081, 20711, 20711, 20179, 20179, -23564, -23564, + 30967, 30967, 1497, 1497, -6516, -6516, -5689, -5689, + 1785, 1785, 3047, 3047, 1491, 1491, 2036, 2036, + 1015, 1015, 2777, 2777, 652, 652, 1223, 1223, + + // layer 3 inverse + -16162, -16162, -16162, -16162, 26676, 26676, 26676, 26676, + 8859, 8859, 8859, 8859, 18427, 18427, 18427, 18427, + 1758, 1758, 1758, 1758, 3124, 3124, 3124, 3124, + 411, 411, 411, 411, 1787, 1787, 1787, 1787, + 8800, 8800, 8800, 8800, -10532, -10532, -10532, -10532, + 24313, 24313, 24313, 24313, -28072, -28072, -28072, -28072, + 608, 608, 608, 608, 732, 732, 732, 732, + 1017, 1017, 1017, 1017, 2648, 2648, 2648, 2648, + -26241, -26241, -26241, -26241, 21439, 21439, 21439, 21439, + -1102, -1102, -1102, -1102, 5572, 5572, 5572, 5572, + 3199, 3199, 3199, 3199, 1727, 1727, 1727, 1727, + 1458, 1458, 1458, 1458, 2500, 2500, 2500, 2500, + -29057, -29057, -29057, -29057, -26360, -26360, -26360, -26360, + 17364, 17364, 17364, 17364, -5827, -5827, -5827, -5827, + 383, 383, 383, 383, 264, 264, 264, 264, + 2004, 2004, 2004, 2004, 573, 573, 573, 573, + + // layer 4 inverse + 31164, 31164, 31164, 31164, 31164, 31164, 31164, 31164, + -11201, -11201, -11201, -11201, -11201, -11201, -11201, -11201, + 1468, 1468, 1468, 1468, 1468, 1468, 1468, 1468, + 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 10690, 10690, 10690, 10690, 10690, 10690, 10690, 10690, + 2127, 2127, 2127, 2127, 2127, 2127, 2127, 2127, + 962, 962, 962, 962, 962, 962, 962, 962, + -15690, -15690, -15690, -15690, -15690, -15690, -15690, -15690, + -3799, -3799, -3799, -3799, -3799, -3799, -3799, -3799, + 182, 182, 182, 182, 182, 182, 182, 182, + 1577, 1577, 1577, 1577, 1577, 1577, 1577, 1577, + 27758, 27758, 27758, 27758, 27758, 27758, 27758, 27758, + -20906, -20906, -20906, -20906, -20906, -20906, -20906, -20906, + 622, 622, 622, 622, 622, 622, 622, 622, + 3158, 3158, 3158, 3158, 3158, 3158, 3158, 3158, + + // layer 5 inverse + -16694, 202, 28191, 287, -12402, 1422, 13525, 1493, + + // layer 6 inverse + 788, 1812, 14746, 2970, + + // layer 7 inverse + 31499, 2571, +} + +// Sets p to a + b. Does not normalize coefficients. +func (p *Poly) Add(a, b *Poly) { + if cpu.X86.HasAVX2 { + addAVX2( + (*[N]int16)(p), + (*[N]int16)(a), + (*[N]int16)(b), + ) + } else { + p.addGeneric(a, b) + } +} + +// Sets p to a - b. Does not normalize coefficients. +func (p *Poly) Sub(a, b *Poly) { + if cpu.X86.HasAVX2 { + subAVX2( + (*[N]int16)(p), + (*[N]int16)(a), + (*[N]int16)(b), + ) + } else { + p.subGeneric(a, b) + } +} + +// Executes an in-place forward "NTT" on p. +// +// Assumes the coefficients are in absolute value ≤q. The resulting +// coefficients are in absolute value ≤7q. If the input is in Montgomery +// form, then the result is in Montgomery form and so (by linearity of the NTT) +// if the input is in regular form, then the result is also in regular form. +// The order of coefficients will be "tangled". These can be put back into +// their proper order by calling Detangle(). +func (p *Poly) NTT() { + if cpu.X86.HasAVX2 { + nttAVX2((*[N]int16)(p)) + } else { + p.nttGeneric() + } +} + +// Executes an in-place inverse "NTT" on p and multiply by the Montgomery +// factor R. +// +// Requires coefficients to be in "tangled" order, see Tangle(). +// Assumes the coefficients are in absolute value ≤q. The resulting +// coefficients are in absolute value ≤q. If the input is in Montgomery +// form, then the result is in Montgomery form and so (by linearity) +// if the input is in regular form, then the result is also in regular form. +func (p *Poly) InvNTT() { + if cpu.X86.HasAVX2 { + invNttAVX2((*[N]int16)(p)) + } else { + p.invNTTGeneric() + } +} + +// Sets p to the "pointwise" multiplication of a and b. +// +// That is: InvNTT(p) = InvNTT(a) * InvNTT(b). Assumes a and b are in +// Montgomery form. Products between coefficients of a and b must be strictly +// bounded in absolute value by 2¹⁵q. p will be in Montgomery form and +// bounded in absolute value by 2q. +// +// Requires a and b to be in "tangled" order, see Tangle(). p will be in +// tangled order as well. +func (p *Poly) MulHat(a, b *Poly) { + if cpu.X86.HasAVX2 { + mulHatAVX2( + (*[N]int16)(p), + (*[N]int16)(a), + (*[N]int16)(b), + ) + } else { + p.mulHatGeneric(a, b) + } +} + +// Puts p into the right form to be used with (among others) InvNTT(). +func (p *Poly) Tangle() { + if cpu.X86.HasAVX2 { + tangleAVX2((*[N]int16)(p)) + } + + // When AVX2 is not available, we use the standard order. +} + +// Puts p back into standard form. +func (p *Poly) Detangle() { + if cpu.X86.HasAVX2 { + detangleAVX2((*[N]int16)(p)) + } + + // When AVX2 is not available, we use the standard order. +} + +// Almost normalizes coefficients. +// +// Ensures each coefficient is in {0, …, q}. +func (p *Poly) BarrettReduce() { + if cpu.X86.HasAVX2 { + barrettReduceAVX2((*[N]int16)(p)) + } else { + p.barrettReduceGeneric() + } +} + +// Normalizes coefficients. +// +// Ensures each coefficient is in {0, …, q-1}. +func (p *Poly) Normalize() { + if cpu.X86.HasAVX2 { + normalizeAVX2((*[N]int16)(p)) + } else { + p.normalizeGeneric() + } +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.s b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.s new file mode 100644 index 00000000000..5c7536b7013 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.s @@ -0,0 +1,2354 @@ +// Code generated by command: go run src.go -out ../amd64.s -stubs ../stubs_amd64.go -pkg common. DO NOT EDIT. + +//go:build amd64 && !purego + +#include "textflag.h" + +// func addAVX2(p *[256]int16, a *[256]int16, b *[256]int16) +// Requires: AVX, AVX2 +TEXT ·addAVX2(SB), NOSPLIT, $0-24 + MOVQ p+0(FP), AX + MOVQ a+8(FP), CX + MOVQ b+16(FP), DX + VMOVDQU (CX), Y0 + VMOVDQU 32(CX), Y2 + VMOVDQU 64(CX), Y4 + VMOVDQU 96(CX), Y6 + VMOVDQU 128(CX), Y8 + VMOVDQU 160(CX), Y10 + VMOVDQU 192(CX), Y12 + VMOVDQU 224(CX), Y14 + VMOVDQU (DX), Y1 + VMOVDQU 32(DX), Y3 + VMOVDQU 64(DX), Y5 + VMOVDQU 96(DX), Y7 + VMOVDQU 128(DX), Y9 + VMOVDQU 160(DX), Y11 + VMOVDQU 192(DX), Y13 + VMOVDQU 224(DX), Y15 + VPADDW Y0, Y1, Y1 + VPADDW Y2, Y3, Y3 + VPADDW Y4, Y5, Y5 + VPADDW Y6, Y7, Y7 + VPADDW Y8, Y9, Y9 + VPADDW Y10, Y11, Y11 + VPADDW Y12, Y13, Y13 + VPADDW Y14, Y15, Y15 + VMOVDQU Y1, (AX) + VMOVDQU Y3, 32(AX) + VMOVDQU Y5, 64(AX) + VMOVDQU Y7, 96(AX) + VMOVDQU Y9, 128(AX) + VMOVDQU Y11, 160(AX) + VMOVDQU Y13, 192(AX) + VMOVDQU Y15, 224(AX) + VMOVDQU 256(CX), Y0 + VMOVDQU 288(CX), Y2 + VMOVDQU 320(CX), Y4 + VMOVDQU 352(CX), Y6 + VMOVDQU 384(CX), Y8 + VMOVDQU 416(CX), Y10 + VMOVDQU 448(CX), Y12 + VMOVDQU 480(CX), Y14 + VMOVDQU 256(DX), Y1 + VMOVDQU 288(DX), Y3 + VMOVDQU 320(DX), Y5 + VMOVDQU 352(DX), Y7 + VMOVDQU 384(DX), Y9 + VMOVDQU 416(DX), Y11 + VMOVDQU 448(DX), Y13 + VMOVDQU 480(DX), Y15 + VPADDW Y0, Y1, Y1 + VPADDW Y2, Y3, Y3 + VPADDW Y4, Y5, Y5 + VPADDW Y6, Y7, Y7 + VPADDW Y8, Y9, Y9 + VPADDW Y10, Y11, Y11 + VPADDW Y12, Y13, Y13 + VPADDW Y14, Y15, Y15 + VMOVDQU Y1, 256(AX) + VMOVDQU Y3, 288(AX) + VMOVDQU Y5, 320(AX) + VMOVDQU Y7, 352(AX) + VMOVDQU Y9, 384(AX) + VMOVDQU Y11, 416(AX) + VMOVDQU Y13, 448(AX) + VMOVDQU Y15, 480(AX) + RET + +// func subAVX2(p *[256]int16, a *[256]int16, b *[256]int16) +// Requires: AVX, AVX2 +TEXT ·subAVX2(SB), NOSPLIT, $0-24 + MOVQ p+0(FP), AX + MOVQ a+8(FP), CX + MOVQ b+16(FP), DX + VMOVDQU (CX), Y0 + VMOVDQU 32(CX), Y2 + VMOVDQU 64(CX), Y4 + VMOVDQU 96(CX), Y6 + VMOVDQU 128(CX), Y8 + VMOVDQU 160(CX), Y10 + VMOVDQU 192(CX), Y12 + VMOVDQU 224(CX), Y14 + VMOVDQU (DX), Y1 + VMOVDQU 32(DX), Y3 + VMOVDQU 64(DX), Y5 + VMOVDQU 96(DX), Y7 + VMOVDQU 128(DX), Y9 + VMOVDQU 160(DX), Y11 + VMOVDQU 192(DX), Y13 + VMOVDQU 224(DX), Y15 + VPSUBW Y1, Y0, Y1 + VPSUBW Y3, Y2, Y3 + VPSUBW Y5, Y4, Y5 + VPSUBW Y7, Y6, Y7 + VPSUBW Y9, Y8, Y9 + VPSUBW Y11, Y10, Y11 + VPSUBW Y13, Y12, Y13 + VPSUBW Y15, Y14, Y15 + VMOVDQU Y1, (AX) + VMOVDQU Y3, 32(AX) + VMOVDQU Y5, 64(AX) + VMOVDQU Y7, 96(AX) + VMOVDQU Y9, 128(AX) + VMOVDQU Y11, 160(AX) + VMOVDQU Y13, 192(AX) + VMOVDQU Y15, 224(AX) + VMOVDQU 256(CX), Y0 + VMOVDQU 288(CX), Y2 + VMOVDQU 320(CX), Y4 + VMOVDQU 352(CX), Y6 + VMOVDQU 384(CX), Y8 + VMOVDQU 416(CX), Y10 + VMOVDQU 448(CX), Y12 + VMOVDQU 480(CX), Y14 + VMOVDQU 256(DX), Y1 + VMOVDQU 288(DX), Y3 + VMOVDQU 320(DX), Y5 + VMOVDQU 352(DX), Y7 + VMOVDQU 384(DX), Y9 + VMOVDQU 416(DX), Y11 + VMOVDQU 448(DX), Y13 + VMOVDQU 480(DX), Y15 + VPSUBW Y1, Y0, Y1 + VPSUBW Y3, Y2, Y3 + VPSUBW Y5, Y4, Y5 + VPSUBW Y7, Y6, Y7 + VPSUBW Y9, Y8, Y9 + VPSUBW Y11, Y10, Y11 + VPSUBW Y13, Y12, Y13 + VPSUBW Y15, Y14, Y15 + VMOVDQU Y1, 256(AX) + VMOVDQU Y3, 288(AX) + VMOVDQU Y5, 320(AX) + VMOVDQU Y7, 352(AX) + VMOVDQU Y9, 384(AX) + VMOVDQU Y11, 416(AX) + VMOVDQU Y13, 448(AX) + VMOVDQU Y15, 480(AX) + RET + +// func nttAVX2(p *[256]int16) +// Requires: AVX, AVX2 +TEXT ·nttAVX2(SB), NOSPLIT, $0-8 + MOVQ p+0(FP), AX + LEAQ ·ZetasAVX2+0(SB), CX + MOVL $0x00000d01, DX + VMOVD DX, X0 + VPBROADCASTW X0, Y15 + VPBROADCASTW (CX), Y0 + VPBROADCASTW 2(CX), Y1 + VMOVDQU (AX), Y7 + VMOVDQU 32(AX), Y8 + VMOVDQU 64(AX), Y9 + VMOVDQU 96(AX), Y10 + VMOVDQU 256(AX), Y11 + VMOVDQU 288(AX), Y12 + VMOVDQU 320(AX), Y13 + VMOVDQU 352(AX), Y14 + VPMULLW Y11, Y0, Y2 + VPMULLW Y12, Y0, Y3 + VPMULLW Y13, Y0, Y4 + VPMULLW Y14, Y0, Y5 + VPMULHW Y11, Y1, Y11 + VPMULHW Y12, Y1, Y12 + VPMULHW Y13, Y1, Y13 + VPMULHW Y14, Y1, Y14 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y11, Y2 + VPSUBW Y3, Y12, Y3 + VPSUBW Y4, Y13, Y4 + VPSUBW Y5, Y14, Y5 + VPSUBW Y2, Y7, Y11 + VPSUBW Y3, Y8, Y12 + VPSUBW Y4, Y9, Y13 + VPSUBW Y5, Y10, Y14 + VPADDW Y2, Y7, Y7 + VPADDW Y3, Y8, Y8 + VPADDW Y4, Y9, Y9 + VPADDW Y5, Y10, Y10 + VMOVDQU Y7, (AX) + VMOVDQU Y8, 32(AX) + VMOVDQU Y9, 64(AX) + VMOVDQU Y10, 96(AX) + VMOVDQU Y11, 256(AX) + VMOVDQU Y12, 288(AX) + VMOVDQU Y13, 320(AX) + VMOVDQU Y14, 352(AX) + VMOVDQU 128(AX), Y7 + VMOVDQU 160(AX), Y8 + VMOVDQU 192(AX), Y9 + VMOVDQU 224(AX), Y10 + VMOVDQU 384(AX), Y11 + VMOVDQU 416(AX), Y12 + VMOVDQU 448(AX), Y13 + VMOVDQU 480(AX), Y14 + VPMULLW Y11, Y0, Y2 + VPMULLW Y12, Y0, Y3 + VPMULLW Y13, Y0, Y4 + VPMULLW Y14, Y0, Y5 + VPMULHW Y11, Y1, Y11 + VPMULHW Y12, Y1, Y12 + VPMULHW Y13, Y1, Y13 + VPMULHW Y14, Y1, Y14 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y11, Y2 + VPSUBW Y3, Y12, Y3 + VPSUBW Y4, Y13, Y4 + VPSUBW Y5, Y14, Y5 + VPSUBW Y2, Y7, Y11 + VPSUBW Y3, Y8, Y12 + VPSUBW Y4, Y9, Y13 + VPSUBW Y5, Y10, Y14 + VPADDW Y2, Y7, Y7 + VPADDW Y3, Y8, Y8 + VPADDW Y4, Y9, Y9 + VPADDW Y5, Y10, Y10 + VMOVDQU Y7, 128(AX) + VMOVDQU Y8, 160(AX) + VMOVDQU Y9, 192(AX) + VMOVDQU Y10, 224(AX) + VMOVDQU Y11, 384(AX) + VMOVDQU Y12, 416(AX) + VMOVDQU Y13, 448(AX) + VMOVDQU Y14, 480(AX) + VPBROADCASTW 4(CX), Y0 + VPBROADCASTW 6(CX), Y1 + VMOVDQU (AX), Y7 + VMOVDQU 32(AX), Y8 + VMOVDQU 64(AX), Y9 + VMOVDQU 96(AX), Y10 + VMOVDQU 128(AX), Y11 + VMOVDQU 160(AX), Y12 + VMOVDQU 192(AX), Y13 + VMOVDQU 224(AX), Y14 + VPMULLW Y11, Y0, Y2 + VPMULLW Y12, Y0, Y3 + VPMULLW Y13, Y0, Y4 + VPMULLW Y14, Y0, Y5 + VPMULHW Y11, Y1, Y11 + VPMULHW Y12, Y1, Y12 + VPMULHW Y13, Y1, Y13 + VPMULHW Y14, Y1, Y14 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y11, Y2 + VPSUBW Y3, Y12, Y3 + VPSUBW Y4, Y13, Y4 + VPSUBW Y5, Y14, Y5 + VPSUBW Y2, Y7, Y11 + VPSUBW Y3, Y8, Y12 + VPSUBW Y4, Y9, Y13 + VPSUBW Y5, Y10, Y14 + VPADDW Y2, Y7, Y7 + VPADDW Y3, Y8, Y8 + VPADDW Y4, Y9, Y9 + VPADDW Y5, Y10, Y10 + VPBROADCASTW 12(CX), Y0 + VPBROADCASTW 14(CX), Y1 + VPBROADCASTW 16(CX), Y2 + VPBROADCASTW 18(CX), Y3 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y13, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y13, Y3, Y13 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y9, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y13, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y9 + VPSUBW Y5, Y8, Y10 + VPSUBW Y6, Y11, Y13 + VPSUBW Y0, Y12, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y8, Y8 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y12, Y12 + VMOVDQU 32(CX), Y0 + VMOVDQU 64(CX), Y1 + VMOVDQU 96(CX), Y2 + VMOVDQU 128(CX), Y3 + VPERM2I128 $0x20, Y9, Y7, Y4 + VPERM2I128 $0x31, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VPERM2I128 $0x20, Y10, Y8, Y4 + VPERM2I128 $0x31, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VPERM2I128 $0x20, Y13, Y11, Y4 + VPERM2I128 $0x31, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VPERM2I128 $0x20, Y14, Y12, Y4 + VPERM2I128 $0x31, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPMULLW Y8, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y12, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y8, Y1, Y8 + VPMULHW Y10, Y1, Y10 + VPMULHW Y12, Y3, Y12 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y8, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y12, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y8 + VPSUBW Y5, Y9, Y10 + VPSUBW Y6, Y11, Y12 + VPSUBW Y0, Y13, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y9, Y9 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y13, Y13 + VMOVDQU 288(CX), Y0 + VMOVDQU 320(CX), Y1 + VMOVDQU 352(CX), Y2 + VMOVDQU 384(CX), Y3 + VPUNPCKLQDQ Y8, Y7, Y4 + VPUNPCKHQDQ Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPUNPCKLQDQ Y10, Y9, Y4 + VPUNPCKHQDQ Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPUNPCKLQDQ Y12, Y11, Y4 + VPUNPCKHQDQ Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPUNPCKLQDQ Y14, Y13, Y4 + VPUNPCKHQDQ Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y13, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y13, Y3, Y13 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y9, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y13, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y9 + VPSUBW Y5, Y8, Y10 + VPSUBW Y6, Y11, Y13 + VPSUBW Y0, Y12, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y8, Y8 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y12, Y12 + VMOVDQU 544(CX), Y0 + VMOVDQU 576(CX), Y1 + VMOVDQU 608(CX), Y2 + VMOVDQU 640(CX), Y3 + VMOVSLDUP Y9, Y4 + VPBLENDD $0xaa, Y4, Y7, Y4 + VPSRLQ $0x20, Y7, Y7 + VPBLENDD $0xaa, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VMOVSLDUP Y10, Y4 + VPBLENDD $0xaa, Y4, Y8, Y4 + VPSRLQ $0x20, Y8, Y8 + VPBLENDD $0xaa, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VMOVSLDUP Y13, Y4 + VPBLENDD $0xaa, Y4, Y11, Y4 + VPSRLQ $0x20, Y11, Y11 + VPBLENDD $0xaa, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VMOVSLDUP Y14, Y4 + VPBLENDD $0xaa, Y4, Y12, Y4 + VPSRLQ $0x20, Y12, Y12 + VPBLENDD $0xaa, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPMULLW Y8, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y12, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y8, Y1, Y8 + VPMULHW Y10, Y1, Y10 + VPMULHW Y12, Y3, Y12 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y8, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y12, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y8 + VPSUBW Y5, Y9, Y10 + VPSUBW Y6, Y11, Y12 + VPSUBW Y0, Y13, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y9, Y9 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y13, Y13 + VMOVDQU 800(CX), Y0 + VMOVDQU 832(CX), Y1 + VMOVDQU 864(CX), Y2 + VMOVDQU 896(CX), Y3 + VPSLLD $0x10, Y8, Y4 + VPBLENDW $0xaa, Y4, Y7, Y4 + VPSRLD $0x10, Y7, Y7 + VPBLENDW $0xaa, Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPSLLD $0x10, Y10, Y4 + VPBLENDW $0xaa, Y4, Y9, Y4 + VPSRLD $0x10, Y9, Y9 + VPBLENDW $0xaa, Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPSLLD $0x10, Y12, Y4 + VPBLENDW $0xaa, Y4, Y11, Y4 + VPSRLD $0x10, Y11, Y11 + VPBLENDW $0xaa, Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPSLLD $0x10, Y14, Y4 + VPBLENDW $0xaa, Y4, Y13, Y4 + VPSRLD $0x10, Y13, Y13 + VPBLENDW $0xaa, Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y13, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y13, Y3, Y13 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y9, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y13, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y9 + VPSUBW Y5, Y8, Y10 + VPSUBW Y6, Y11, Y13 + VPSUBW Y0, Y12, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y8, Y8 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y12, Y12 + VMOVDQU Y7, (AX) + VMOVDQU Y8, 32(AX) + VMOVDQU Y9, 64(AX) + VMOVDQU Y10, 96(AX) + VMOVDQU Y11, 128(AX) + VMOVDQU Y12, 160(AX) + VMOVDQU Y13, 192(AX) + VMOVDQU Y14, 224(AX) + VPBROADCASTW 8(CX), Y0 + VPBROADCASTW 10(CX), Y1 + VMOVDQU 256(AX), Y7 + VMOVDQU 288(AX), Y8 + VMOVDQU 320(AX), Y9 + VMOVDQU 352(AX), Y10 + VMOVDQU 384(AX), Y11 + VMOVDQU 416(AX), Y12 + VMOVDQU 448(AX), Y13 + VMOVDQU 480(AX), Y14 + VPMULLW Y11, Y0, Y2 + VPMULLW Y12, Y0, Y3 + VPMULLW Y13, Y0, Y4 + VPMULLW Y14, Y0, Y5 + VPMULHW Y11, Y1, Y11 + VPMULHW Y12, Y1, Y12 + VPMULHW Y13, Y1, Y13 + VPMULHW Y14, Y1, Y14 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y11, Y2 + VPSUBW Y3, Y12, Y3 + VPSUBW Y4, Y13, Y4 + VPSUBW Y5, Y14, Y5 + VPSUBW Y2, Y7, Y11 + VPSUBW Y3, Y8, Y12 + VPSUBW Y4, Y9, Y13 + VPSUBW Y5, Y10, Y14 + VPADDW Y2, Y7, Y7 + VPADDW Y3, Y8, Y8 + VPADDW Y4, Y9, Y9 + VPADDW Y5, Y10, Y10 + VPBROADCASTW 20(CX), Y0 + VPBROADCASTW 22(CX), Y1 + VPBROADCASTW 24(CX), Y2 + VPBROADCASTW 26(CX), Y3 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y13, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y13, Y3, Y13 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y9, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y13, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y9 + VPSUBW Y5, Y8, Y10 + VPSUBW Y6, Y11, Y13 + VPSUBW Y0, Y12, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y8, Y8 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y12, Y12 + VMOVDQU 160(CX), Y0 + VMOVDQU 192(CX), Y1 + VMOVDQU 224(CX), Y2 + VMOVDQU 256(CX), Y3 + VPERM2I128 $0x20, Y9, Y7, Y4 + VPERM2I128 $0x31, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VPERM2I128 $0x20, Y10, Y8, Y4 + VPERM2I128 $0x31, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VPERM2I128 $0x20, Y13, Y11, Y4 + VPERM2I128 $0x31, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VPERM2I128 $0x20, Y14, Y12, Y4 + VPERM2I128 $0x31, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPMULLW Y8, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y12, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y8, Y1, Y8 + VPMULHW Y10, Y1, Y10 + VPMULHW Y12, Y3, Y12 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y8, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y12, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y8 + VPSUBW Y5, Y9, Y10 + VPSUBW Y6, Y11, Y12 + VPSUBW Y0, Y13, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y9, Y9 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y13, Y13 + VMOVDQU 416(CX), Y0 + VMOVDQU 448(CX), Y1 + VMOVDQU 480(CX), Y2 + VMOVDQU 512(CX), Y3 + VPUNPCKLQDQ Y8, Y7, Y4 + VPUNPCKHQDQ Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPUNPCKLQDQ Y10, Y9, Y4 + VPUNPCKHQDQ Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPUNPCKLQDQ Y12, Y11, Y4 + VPUNPCKHQDQ Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPUNPCKLQDQ Y14, Y13, Y4 + VPUNPCKHQDQ Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y13, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y13, Y3, Y13 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y9, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y13, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y9 + VPSUBW Y5, Y8, Y10 + VPSUBW Y6, Y11, Y13 + VPSUBW Y0, Y12, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y8, Y8 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y12, Y12 + VMOVDQU 672(CX), Y0 + VMOVDQU 704(CX), Y1 + VMOVDQU 736(CX), Y2 + VMOVDQU 768(CX), Y3 + VMOVSLDUP Y9, Y4 + VPBLENDD $0xaa, Y4, Y7, Y4 + VPSRLQ $0x20, Y7, Y7 + VPBLENDD $0xaa, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VMOVSLDUP Y10, Y4 + VPBLENDD $0xaa, Y4, Y8, Y4 + VPSRLQ $0x20, Y8, Y8 + VPBLENDD $0xaa, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VMOVSLDUP Y13, Y4 + VPBLENDD $0xaa, Y4, Y11, Y4 + VPSRLQ $0x20, Y11, Y11 + VPBLENDD $0xaa, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VMOVSLDUP Y14, Y4 + VPBLENDD $0xaa, Y4, Y12, Y4 + VPSRLQ $0x20, Y12, Y12 + VPBLENDD $0xaa, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPMULLW Y8, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y12, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y8, Y1, Y8 + VPMULHW Y10, Y1, Y10 + VPMULHW Y12, Y3, Y12 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y8, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y12, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y8 + VPSUBW Y5, Y9, Y10 + VPSUBW Y6, Y11, Y12 + VPSUBW Y0, Y13, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y9, Y9 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y13, Y13 + VMOVDQU 928(CX), Y0 + VMOVDQU 960(CX), Y1 + VMOVDQU 992(CX), Y2 + VMOVDQU 1024(CX), Y3 + VPSLLD $0x10, Y8, Y4 + VPBLENDW $0xaa, Y4, Y7, Y4 + VPSRLD $0x10, Y7, Y7 + VPBLENDW $0xaa, Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPSLLD $0x10, Y10, Y4 + VPBLENDW $0xaa, Y4, Y9, Y4 + VPSRLD $0x10, Y9, Y9 + VPBLENDW $0xaa, Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPSLLD $0x10, Y12, Y4 + VPBLENDW $0xaa, Y4, Y11, Y4 + VPSRLD $0x10, Y11, Y11 + VPBLENDW $0xaa, Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPSLLD $0x10, Y14, Y4 + VPBLENDW $0xaa, Y4, Y13, Y4 + VPSRLD $0x10, Y13, Y13 + VPBLENDW $0xaa, Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULLW Y13, Y2, Y6 + VPMULLW Y14, Y2, Y0 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y13, Y3, Y13 + VPMULHW Y14, Y3, Y14 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPMULHW Y6, Y15, Y6 + VPMULHW Y0, Y15, Y0 + VPSUBW Y4, Y9, Y4 + VPSUBW Y5, Y10, Y5 + VPSUBW Y6, Y13, Y6 + VPSUBW Y0, Y14, Y0 + VPSUBW Y4, Y7, Y9 + VPSUBW Y5, Y8, Y10 + VPSUBW Y6, Y11, Y13 + VPSUBW Y0, Y12, Y14 + VPADDW Y4, Y7, Y7 + VPADDW Y5, Y8, Y8 + VPADDW Y6, Y11, Y11 + VPADDW Y0, Y12, Y12 + VMOVDQU Y7, 256(AX) + VMOVDQU Y8, 288(AX) + VMOVDQU Y9, 320(AX) + VMOVDQU Y10, 352(AX) + VMOVDQU Y11, 384(AX) + VMOVDQU Y12, 416(AX) + VMOVDQU Y13, 448(AX) + VMOVDQU Y14, 480(AX) + RET + +// func invNttAVX2(p *[256]int16) +// Requires: AVX, AVX2 +TEXT ·invNttAVX2(SB), NOSPLIT, $0-8 + MOVQ p+0(FP), AX + LEAQ ·ZetasAVX2+0(SB), CX + MOVL $0x00000d01, DX + VMOVD DX, X0 + VPBROADCASTW X0, Y15 + VMOVDQU (AX), Y7 + VMOVDQU 32(AX), Y8 + VMOVDQU 64(AX), Y9 + VMOVDQU 96(AX), Y10 + VMOVDQU 128(AX), Y11 + VMOVDQU 160(AX), Y12 + VMOVDQU 192(AX), Y13 + VMOVDQU 224(AX), Y14 + VMOVDQU 1056(CX), Y0 + VMOVDQU 1088(CX), Y1 + VMOVDQU 1120(CX), Y2 + VMOVDQU 1152(CX), Y3 + VPSUBW Y7, Y9, Y4 + VPSUBW Y8, Y10, Y5 + VPSUBW Y11, Y13, Y6 + VPADDW Y7, Y9, Y7 + VPADDW Y8, Y10, Y8 + VPADDW Y11, Y13, Y11 + VPMULLW Y4, Y0, Y9 + VPMULLW Y5, Y0, Y10 + VPSUBW Y12, Y14, Y0 + VPMULLW Y6, Y2, Y13 + VPADDW Y12, Y14, Y12 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y9, Y4, Y9 + VPSUBW Y10, Y5, Y10 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y0, Y14 + VMOVDQU 1312(CX), Y0 + VMOVDQU 1344(CX), Y1 + VMOVDQU 1376(CX), Y2 + VMOVDQU 1408(CX), Y3 + VPSLLD $0x10, Y8, Y4 + VPBLENDW $0xaa, Y4, Y7, Y4 + VPSRLD $0x10, Y7, Y7 + VPBLENDW $0xaa, Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPSLLD $0x10, Y10, Y4 + VPBLENDW $0xaa, Y4, Y9, Y4 + VPSRLD $0x10, Y9, Y9 + VPBLENDW $0xaa, Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPSLLD $0x10, Y12, Y4 + VPBLENDW $0xaa, Y4, Y11, Y4 + VPSRLD $0x10, Y11, Y11 + VPBLENDW $0xaa, Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPSLLD $0x10, Y14, Y4 + VPBLENDW $0xaa, Y4, Y13, Y4 + VPSRLD $0x10, Y13, Y13 + VPBLENDW $0xaa, Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPSUBW Y7, Y8, Y4 + VPSUBW Y9, Y10, Y5 + VPSUBW Y11, Y12, Y6 + VPADDW Y7, Y8, Y7 + VPADDW Y9, Y10, Y9 + VPADDW Y11, Y12, Y11 + VPMULLW Y4, Y0, Y8 + VPMULLW Y5, Y0, Y10 + VPSUBW Y13, Y14, Y0 + VPMULLW Y6, Y2, Y12 + VPADDW Y13, Y14, Y13 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y8, Y15, Y8 + VPMULHW Y10, Y15, Y10 + VPMULHW Y12, Y15, Y12 + VPMULHW Y14, Y15, Y14 + VPSUBW Y8, Y4, Y8 + VPSUBW Y10, Y5, Y10 + VPSUBW Y12, Y6, Y12 + VPSUBW Y14, Y0, Y14 + VMOVDQU 1568(CX), Y0 + VMOVDQU 1600(CX), Y1 + VMOVDQU 1632(CX), Y2 + VMOVDQU 1664(CX), Y3 + VMOVSLDUP Y9, Y4 + VPBLENDD $0xaa, Y4, Y7, Y4 + VPSRLQ $0x20, Y7, Y7 + VPBLENDD $0xaa, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VMOVSLDUP Y10, Y4 + VPBLENDD $0xaa, Y4, Y8, Y4 + VPSRLQ $0x20, Y8, Y8 + VPBLENDD $0xaa, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VMOVSLDUP Y13, Y4 + VPBLENDD $0xaa, Y4, Y11, Y4 + VPSRLQ $0x20, Y11, Y11 + VPBLENDD $0xaa, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VMOVSLDUP Y14, Y4 + VPBLENDD $0xaa, Y4, Y12, Y4 + VPSRLQ $0x20, Y12, Y12 + VPBLENDD $0xaa, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPSUBW Y7, Y9, Y4 + VPSUBW Y8, Y10, Y5 + VPSUBW Y11, Y13, Y6 + VPADDW Y7, Y9, Y7 + VPADDW Y8, Y10, Y8 + VPADDW Y11, Y13, Y11 + VPMULLW Y4, Y0, Y9 + VPMULLW Y5, Y0, Y10 + VPSUBW Y12, Y14, Y0 + VPMULLW Y6, Y2, Y13 + VPADDW Y12, Y14, Y12 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y9, Y4, Y9 + VPSUBW Y10, Y5, Y10 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y0, Y14 + MOVL $0x00004ebf, DX + VMOVD DX, X0 + VPBROADCASTW X0, Y4 + VPMULHW Y4, Y7, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y7, Y7 + VPMULHW Y4, Y11, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y11, Y11 + VMOVDQU 1824(CX), Y0 + VMOVDQU 1856(CX), Y1 + VMOVDQU 1888(CX), Y2 + VMOVDQU 1920(CX), Y3 + VPUNPCKLQDQ Y8, Y7, Y4 + VPUNPCKHQDQ Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPUNPCKLQDQ Y10, Y9, Y4 + VPUNPCKHQDQ Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPUNPCKLQDQ Y12, Y11, Y4 + VPUNPCKHQDQ Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPUNPCKLQDQ Y14, Y13, Y4 + VPUNPCKHQDQ Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPSUBW Y7, Y8, Y4 + VPSUBW Y9, Y10, Y5 + VPSUBW Y11, Y12, Y6 + VPADDW Y7, Y8, Y7 + VPADDW Y9, Y10, Y9 + VPADDW Y11, Y12, Y11 + VPMULLW Y4, Y0, Y8 + VPMULLW Y5, Y0, Y10 + VPSUBW Y13, Y14, Y0 + VPMULLW Y6, Y2, Y12 + VPADDW Y13, Y14, Y13 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y8, Y15, Y8 + VPMULHW Y10, Y15, Y10 + VPMULHW Y12, Y15, Y12 + VPMULHW Y14, Y15, Y14 + VPSUBW Y8, Y4, Y8 + VPSUBW Y10, Y5, Y10 + VPSUBW Y12, Y6, Y12 + VPSUBW Y14, Y0, Y14 + VPBROADCASTW 2080(CX), Y0 + VPBROADCASTW 2082(CX), Y1 + VPBROADCASTW 2084(CX), Y2 + VPBROADCASTW 2086(CX), Y3 + VPERM2I128 $0x20, Y9, Y7, Y4 + VPERM2I128 $0x31, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VPERM2I128 $0x20, Y10, Y8, Y4 + VPERM2I128 $0x31, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VPERM2I128 $0x20, Y13, Y11, Y4 + VPERM2I128 $0x31, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VPERM2I128 $0x20, Y14, Y12, Y4 + VPERM2I128 $0x31, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPSUBW Y7, Y9, Y4 + VPSUBW Y8, Y10, Y5 + VPSUBW Y11, Y13, Y6 + VPADDW Y7, Y9, Y7 + VPADDW Y8, Y10, Y8 + VPADDW Y11, Y13, Y11 + VPMULLW Y4, Y0, Y9 + VPMULLW Y5, Y0, Y10 + VPSUBW Y12, Y14, Y0 + VPMULLW Y6, Y2, Y13 + VPADDW Y12, Y14, Y12 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y9, Y4, Y9 + VPSUBW Y10, Y5, Y10 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y0, Y14 + MOVL $0x00004ebf, DX + VMOVD DX, X0 + VPBROADCASTW X0, Y4 + VPMULHW Y4, Y7, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y7, Y7 + VPMULHW Y4, Y11, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y11, Y11 + VPBROADCASTW 2096(CX), Y0 + VPBROADCASTW 2098(CX), Y1 + VPSUBW Y7, Y11, Y4 + VPSUBW Y8, Y12, Y5 + VPSUBW Y9, Y13, Y6 + VPADDW Y7, Y11, Y7 + VPADDW Y8, Y12, Y8 + VPADDW Y9, Y13, Y9 + VPMULLW Y4, Y0, Y11 + VPMULLW Y5, Y0, Y12 + VPSUBW Y10, Y14, Y2 + VPMULLW Y6, Y0, Y13 + VPADDW Y10, Y14, Y10 + VPMULLW Y2, Y0, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y1, Y6 + VPMULHW Y2, Y1, Y2 + VPMULHW Y11, Y15, Y11 + VPMULHW Y12, Y15, Y12 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y11, Y4, Y11 + VPSUBW Y12, Y5, Y12 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y2, Y14 + VMOVDQU Y7, (AX) + VMOVDQU Y8, 32(AX) + VMOVDQU Y9, 64(AX) + VMOVDQU Y10, 96(AX) + VMOVDQU Y11, 128(AX) + VMOVDQU Y12, 160(AX) + VMOVDQU Y13, 192(AX) + VMOVDQU Y14, 224(AX) + VMOVDQU 256(AX), Y7 + VMOVDQU 288(AX), Y8 + VMOVDQU 320(AX), Y9 + VMOVDQU 352(AX), Y10 + VMOVDQU 384(AX), Y11 + VMOVDQU 416(AX), Y12 + VMOVDQU 448(AX), Y13 + VMOVDQU 480(AX), Y14 + VMOVDQU 1184(CX), Y0 + VMOVDQU 1216(CX), Y1 + VMOVDQU 1248(CX), Y2 + VMOVDQU 1280(CX), Y3 + VPSUBW Y7, Y9, Y4 + VPSUBW Y8, Y10, Y5 + VPSUBW Y11, Y13, Y6 + VPADDW Y7, Y9, Y7 + VPADDW Y8, Y10, Y8 + VPADDW Y11, Y13, Y11 + VPMULLW Y4, Y0, Y9 + VPMULLW Y5, Y0, Y10 + VPSUBW Y12, Y14, Y0 + VPMULLW Y6, Y2, Y13 + VPADDW Y12, Y14, Y12 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y9, Y4, Y9 + VPSUBW Y10, Y5, Y10 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y0, Y14 + VMOVDQU 1440(CX), Y0 + VMOVDQU 1472(CX), Y1 + VMOVDQU 1504(CX), Y2 + VMOVDQU 1536(CX), Y3 + VPSLLD $0x10, Y8, Y4 + VPBLENDW $0xaa, Y4, Y7, Y4 + VPSRLD $0x10, Y7, Y7 + VPBLENDW $0xaa, Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPSLLD $0x10, Y10, Y4 + VPBLENDW $0xaa, Y4, Y9, Y4 + VPSRLD $0x10, Y9, Y9 + VPBLENDW $0xaa, Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPSLLD $0x10, Y12, Y4 + VPBLENDW $0xaa, Y4, Y11, Y4 + VPSRLD $0x10, Y11, Y11 + VPBLENDW $0xaa, Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPSLLD $0x10, Y14, Y4 + VPBLENDW $0xaa, Y4, Y13, Y4 + VPSRLD $0x10, Y13, Y13 + VPBLENDW $0xaa, Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPSUBW Y7, Y8, Y4 + VPSUBW Y9, Y10, Y5 + VPSUBW Y11, Y12, Y6 + VPADDW Y7, Y8, Y7 + VPADDW Y9, Y10, Y9 + VPADDW Y11, Y12, Y11 + VPMULLW Y4, Y0, Y8 + VPMULLW Y5, Y0, Y10 + VPSUBW Y13, Y14, Y0 + VPMULLW Y6, Y2, Y12 + VPADDW Y13, Y14, Y13 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y8, Y15, Y8 + VPMULHW Y10, Y15, Y10 + VPMULHW Y12, Y15, Y12 + VPMULHW Y14, Y15, Y14 + VPSUBW Y8, Y4, Y8 + VPSUBW Y10, Y5, Y10 + VPSUBW Y12, Y6, Y12 + VPSUBW Y14, Y0, Y14 + VMOVDQU 1696(CX), Y0 + VMOVDQU 1728(CX), Y1 + VMOVDQU 1760(CX), Y2 + VMOVDQU 1792(CX), Y3 + VMOVSLDUP Y9, Y4 + VPBLENDD $0xaa, Y4, Y7, Y4 + VPSRLQ $0x20, Y7, Y7 + VPBLENDD $0xaa, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VMOVSLDUP Y10, Y4 + VPBLENDD $0xaa, Y4, Y8, Y4 + VPSRLQ $0x20, Y8, Y8 + VPBLENDD $0xaa, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VMOVSLDUP Y13, Y4 + VPBLENDD $0xaa, Y4, Y11, Y4 + VPSRLQ $0x20, Y11, Y11 + VPBLENDD $0xaa, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VMOVSLDUP Y14, Y4 + VPBLENDD $0xaa, Y4, Y12, Y4 + VPSRLQ $0x20, Y12, Y12 + VPBLENDD $0xaa, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPSUBW Y7, Y9, Y4 + VPSUBW Y8, Y10, Y5 + VPSUBW Y11, Y13, Y6 + VPADDW Y7, Y9, Y7 + VPADDW Y8, Y10, Y8 + VPADDW Y11, Y13, Y11 + VPMULLW Y4, Y0, Y9 + VPMULLW Y5, Y0, Y10 + VPSUBW Y12, Y14, Y0 + VPMULLW Y6, Y2, Y13 + VPADDW Y12, Y14, Y12 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y9, Y4, Y9 + VPSUBW Y10, Y5, Y10 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y0, Y14 + MOVL $0x00004ebf, DX + VMOVD DX, X0 + VPBROADCASTW X0, Y4 + VPMULHW Y4, Y7, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y7, Y7 + VPMULHW Y4, Y11, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y11, Y11 + VMOVDQU 1952(CX), Y0 + VMOVDQU 1984(CX), Y1 + VMOVDQU 2016(CX), Y2 + VMOVDQU 2048(CX), Y3 + VPUNPCKLQDQ Y8, Y7, Y4 + VPUNPCKHQDQ Y8, Y7, Y8 + VMOVDQA Y4, Y7 + VPUNPCKLQDQ Y10, Y9, Y4 + VPUNPCKHQDQ Y10, Y9, Y10 + VMOVDQA Y4, Y9 + VPUNPCKLQDQ Y12, Y11, Y4 + VPUNPCKHQDQ Y12, Y11, Y12 + VMOVDQA Y4, Y11 + VPUNPCKLQDQ Y14, Y13, Y4 + VPUNPCKHQDQ Y14, Y13, Y14 + VMOVDQA Y4, Y13 + VPSUBW Y7, Y8, Y4 + VPSUBW Y9, Y10, Y5 + VPSUBW Y11, Y12, Y6 + VPADDW Y7, Y8, Y7 + VPADDW Y9, Y10, Y9 + VPADDW Y11, Y12, Y11 + VPMULLW Y4, Y0, Y8 + VPMULLW Y5, Y0, Y10 + VPSUBW Y13, Y14, Y0 + VPMULLW Y6, Y2, Y12 + VPADDW Y13, Y14, Y13 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y8, Y15, Y8 + VPMULHW Y10, Y15, Y10 + VPMULHW Y12, Y15, Y12 + VPMULHW Y14, Y15, Y14 + VPSUBW Y8, Y4, Y8 + VPSUBW Y10, Y5, Y10 + VPSUBW Y12, Y6, Y12 + VPSUBW Y14, Y0, Y14 + VPBROADCASTW 2088(CX), Y0 + VPBROADCASTW 2090(CX), Y1 + VPBROADCASTW 2092(CX), Y2 + VPBROADCASTW 2094(CX), Y3 + VPERM2I128 $0x20, Y9, Y7, Y4 + VPERM2I128 $0x31, Y9, Y7, Y9 + VMOVDQA Y4, Y7 + VPERM2I128 $0x20, Y10, Y8, Y4 + VPERM2I128 $0x31, Y10, Y8, Y10 + VMOVDQA Y4, Y8 + VPERM2I128 $0x20, Y13, Y11, Y4 + VPERM2I128 $0x31, Y13, Y11, Y13 + VMOVDQA Y4, Y11 + VPERM2I128 $0x20, Y14, Y12, Y4 + VPERM2I128 $0x31, Y14, Y12, Y14 + VMOVDQA Y4, Y12 + VPSUBW Y7, Y9, Y4 + VPSUBW Y8, Y10, Y5 + VPSUBW Y11, Y13, Y6 + VPADDW Y7, Y9, Y7 + VPADDW Y8, Y10, Y8 + VPADDW Y11, Y13, Y11 + VPMULLW Y4, Y0, Y9 + VPMULLW Y5, Y0, Y10 + VPSUBW Y12, Y14, Y0 + VPMULLW Y6, Y2, Y13 + VPADDW Y12, Y14, Y12 + VPMULLW Y0, Y2, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y3, Y6 + VPMULHW Y0, Y3, Y0 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y9, Y4, Y9 + VPSUBW Y10, Y5, Y10 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y0, Y14 + MOVL $0x00004ebf, DX + VMOVD DX, X0 + VPBROADCASTW X0, Y4 + VPMULHW Y4, Y7, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y7, Y7 + VPMULHW Y4, Y11, Y5 + VPSRAW $0x0a, Y5, Y5 + VPMULLW Y15, Y5, Y5 + VPSUBW Y5, Y11, Y11 + VPBROADCASTW 2100(CX), Y0 + VPBROADCASTW 2102(CX), Y1 + VPSUBW Y7, Y11, Y4 + VPSUBW Y8, Y12, Y5 + VPSUBW Y9, Y13, Y6 + VPADDW Y7, Y11, Y7 + VPADDW Y8, Y12, Y8 + VPADDW Y9, Y13, Y9 + VPMULLW Y4, Y0, Y11 + VPMULLW Y5, Y0, Y12 + VPSUBW Y10, Y14, Y2 + VPMULLW Y6, Y0, Y13 + VPADDW Y10, Y14, Y10 + VPMULLW Y2, Y0, Y14 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y6, Y1, Y6 + VPMULHW Y2, Y1, Y2 + VPMULHW Y11, Y15, Y11 + VPMULHW Y12, Y15, Y12 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y11, Y4, Y11 + VPSUBW Y12, Y5, Y12 + VPSUBW Y13, Y6, Y13 + VPSUBW Y14, Y2, Y14 + VMOVDQU Y7, 256(AX) + VMOVDQU Y8, 288(AX) + VMOVDQU Y9, 320(AX) + VMOVDQU Y10, 352(AX) + VMOVDQU Y11, 384(AX) + VMOVDQU Y12, 416(AX) + VMOVDQU Y13, 448(AX) + VMOVDQU Y14, 480(AX) + VPBROADCASTW 2104(CX), Y0 + VPBROADCASTW 2106(CX), Y1 + VMOVDQU (AX), Y7 + VMOVDQU 32(AX), Y8 + VMOVDQU 64(AX), Y9 + VMOVDQU 96(AX), Y10 + VMOVDQU 256(AX), Y11 + VMOVDQU 288(AX), Y12 + VMOVDQU 320(AX), Y13 + VMOVDQU 352(AX), Y14 + VPSUBW Y7, Y11, Y2 + VPSUBW Y8, Y12, Y3 + VPSUBW Y9, Y13, Y4 + VPADDW Y7, Y11, Y7 + VPADDW Y8, Y12, Y8 + VPADDW Y9, Y13, Y9 + VPMULLW Y2, Y0, Y11 + VPMULLW Y3, Y0, Y12 + VPSUBW Y10, Y14, Y5 + VPMULLW Y4, Y0, Y13 + VPADDW Y10, Y14, Y10 + VPMULLW Y5, Y0, Y14 + VPMULHW Y2, Y1, Y2 + VPMULHW Y3, Y1, Y3 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y11, Y15, Y11 + VPMULHW Y12, Y15, Y12 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y11, Y2, Y11 + VPSUBW Y12, Y3, Y12 + VPSUBW Y13, Y4, Y13 + VPSUBW Y14, Y5, Y14 + MOVL $0xffffd8a1, DX + VMOVD DX, X0 + VPBROADCASTW X0, Y0 + MOVL $0x000005a1, DX + VMOVD DX, X1 + VPBROADCASTW X1, Y1 + VPMULLW Y7, Y0, Y2 + VPMULLW Y8, Y0, Y3 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULHW Y7, Y1, Y7 + VPMULHW Y8, Y1, Y8 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y7, Y7 + VPSUBW Y3, Y8, Y8 + VPSUBW Y4, Y9, Y9 + VPSUBW Y5, Y10, Y10 + VPMULLW Y11, Y0, Y2 + VPMULLW Y12, Y0, Y3 + VPMULLW Y13, Y0, Y4 + VPMULLW Y14, Y0, Y5 + VPMULHW Y11, Y1, Y11 + VPMULHW Y12, Y1, Y12 + VPMULHW Y13, Y1, Y13 + VPMULHW Y14, Y1, Y14 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y11, Y11 + VPSUBW Y3, Y12, Y12 + VPSUBW Y4, Y13, Y13 + VPSUBW Y5, Y14, Y14 + VMOVDQU Y7, (AX) + VMOVDQU Y8, 32(AX) + VMOVDQU Y9, 64(AX) + VMOVDQU Y10, 96(AX) + VMOVDQU Y11, 256(AX) + VMOVDQU Y12, 288(AX) + VMOVDQU Y13, 320(AX) + VMOVDQU Y14, 352(AX) + VPBROADCASTW 2104(CX), Y0 + VPBROADCASTW 2106(CX), Y1 + VMOVDQU 128(AX), Y7 + VMOVDQU 160(AX), Y8 + VMOVDQU 192(AX), Y9 + VMOVDQU 224(AX), Y10 + VMOVDQU 384(AX), Y11 + VMOVDQU 416(AX), Y12 + VMOVDQU 448(AX), Y13 + VMOVDQU 480(AX), Y14 + VPSUBW Y7, Y11, Y2 + VPSUBW Y8, Y12, Y3 + VPSUBW Y9, Y13, Y4 + VPADDW Y7, Y11, Y7 + VPADDW Y8, Y12, Y8 + VPADDW Y9, Y13, Y9 + VPMULLW Y2, Y0, Y11 + VPMULLW Y3, Y0, Y12 + VPSUBW Y10, Y14, Y5 + VPMULLW Y4, Y0, Y13 + VPADDW Y10, Y14, Y10 + VPMULLW Y5, Y0, Y14 + VPMULHW Y2, Y1, Y2 + VPMULHW Y3, Y1, Y3 + VPMULHW Y4, Y1, Y4 + VPMULHW Y5, Y1, Y5 + VPMULHW Y11, Y15, Y11 + VPMULHW Y12, Y15, Y12 + VPMULHW Y13, Y15, Y13 + VPMULHW Y14, Y15, Y14 + VPSUBW Y11, Y2, Y11 + VPSUBW Y12, Y3, Y12 + VPSUBW Y13, Y4, Y13 + VPSUBW Y14, Y5, Y14 + MOVL $0xffffd8a1, CX + VMOVD CX, X0 + VPBROADCASTW X0, Y0 + MOVL $0x000005a1, CX + VMOVD CX, X1 + VPBROADCASTW X1, Y1 + VPMULLW Y7, Y0, Y2 + VPMULLW Y8, Y0, Y3 + VPMULLW Y9, Y0, Y4 + VPMULLW Y10, Y0, Y5 + VPMULHW Y7, Y1, Y7 + VPMULHW Y8, Y1, Y8 + VPMULHW Y9, Y1, Y9 + VPMULHW Y10, Y1, Y10 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y7, Y7 + VPSUBW Y3, Y8, Y8 + VPSUBW Y4, Y9, Y9 + VPSUBW Y5, Y10, Y10 + VPMULLW Y11, Y0, Y2 + VPMULLW Y12, Y0, Y3 + VPMULLW Y13, Y0, Y4 + VPMULLW Y14, Y0, Y5 + VPMULHW Y11, Y1, Y11 + VPMULHW Y12, Y1, Y12 + VPMULHW Y13, Y1, Y13 + VPMULHW Y14, Y1, Y14 + VPMULHW Y2, Y15, Y2 + VPMULHW Y3, Y15, Y3 + VPMULHW Y4, Y15, Y4 + VPMULHW Y5, Y15, Y5 + VPSUBW Y2, Y11, Y11 + VPSUBW Y3, Y12, Y12 + VPSUBW Y4, Y13, Y13 + VPSUBW Y5, Y14, Y14 + VMOVDQU Y7, 128(AX) + VMOVDQU Y8, 160(AX) + VMOVDQU Y9, 192(AX) + VMOVDQU Y10, 224(AX) + VMOVDQU Y11, 384(AX) + VMOVDQU Y12, 416(AX) + VMOVDQU Y13, 448(AX) + VMOVDQU Y14, 480(AX) + RET + +// func mulHatAVX2(p *[256]int16, a *[256]int16, b *[256]int16) +// Requires: AVX, AVX2 +TEXT ·mulHatAVX2(SB), NOSPLIT, $8-24 + MOVQ p+0(FP), AX + MOVQ a+8(FP), CX + MOVQ b+16(FP), DX + LEAQ ·ZetasAVX2+0(SB), BX + MOVL $0xfffff301, SI + VMOVD SI, X0 + VPBROADCASTW X0, Y14 + MOVL $0x00000d01, SI + VMOVD SI, X0 + VPBROADCASTW X0, Y15 + VMOVDQU (CX), Y0 + VMOVDQU 32(CX), Y1 + VMOVDQU 64(CX), Y2 + VMOVDQU 96(CX), Y3 + VMOVDQU (DX), Y4 + VMOVDQU 32(DX), Y5 + VMOVDQU 64(DX), Y6 + VMOVDQU 96(DX), Y7 + VPMULLW Y1, Y5, Y8 + VPMULLW Y0, Y4, Y9 + VPMULLW Y0, Y5, Y10 + VPMULLW Y1, Y4, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y1, Y5, Y12 + VPMULHW Y0, Y4, Y13 + VPMULHW Y0, Y5, Y0 + VPMULHW Y1, Y4, Y1 + VMOVDQA Y12, Y4 + VMOVDQA Y13, Y5 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y4, Y4 + VPSUBW Y9, Y5, Y5 + VPSUBW Y10, Y0, Y0 + VPSUBW Y11, Y1, Y1 + VMOVDQU 800(BX), Y12 + VMOVDQU 832(BX), Y13 + VPMULLW Y4, Y12, Y8 + VPMULHW Y4, Y13, Y4 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y4, Y4 + VPADDW Y4, Y5, Y4 + VPADDW Y0, Y1, Y5 + VPMULLW Y3, Y7, Y8 + VPMULLW Y2, Y6, Y9 + VPMULLW Y2, Y7, Y10 + VPMULLW Y3, Y6, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y3, Y7, Y12 + VPMULHW Y2, Y6, Y13 + VPMULHW Y2, Y7, Y2 + VPMULHW Y3, Y6, Y3 + VMOVDQA Y12, Y6 + VMOVDQA Y13, Y7 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y6, Y6 + VPSUBW Y9, Y7, Y7 + VPSUBW Y10, Y2, Y2 + VPSUBW Y11, Y3, Y3 + VMOVDQU 800(BX), Y12 + VMOVDQU 832(BX), Y13 + VPMULLW Y6, Y12, Y8 + VPMULHW Y6, Y13, Y6 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y6, Y6 + VPSUBW Y6, Y7, Y6 + VPADDW Y2, Y3, Y7 + VMOVDQU Y4, (AX) + VMOVDQU Y5, 32(AX) + VMOVDQU Y6, 64(AX) + VMOVDQU Y7, 96(AX) + VMOVDQU 128(CX), Y0 + VMOVDQU 160(CX), Y1 + VMOVDQU 192(CX), Y2 + VMOVDQU 224(CX), Y3 + VMOVDQU 128(DX), Y4 + VMOVDQU 160(DX), Y5 + VMOVDQU 192(DX), Y6 + VMOVDQU 224(DX), Y7 + VPMULLW Y1, Y5, Y8 + VPMULLW Y0, Y4, Y9 + VPMULLW Y0, Y5, Y10 + VPMULLW Y1, Y4, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y1, Y5, Y12 + VPMULHW Y0, Y4, Y13 + VPMULHW Y0, Y5, Y0 + VPMULHW Y1, Y4, Y1 + VMOVDQA Y12, Y4 + VMOVDQA Y13, Y5 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y4, Y4 + VPSUBW Y9, Y5, Y5 + VPSUBW Y10, Y0, Y0 + VPSUBW Y11, Y1, Y1 + VMOVDQU 864(BX), Y12 + VMOVDQU 896(BX), Y13 + VPMULLW Y4, Y12, Y8 + VPMULHW Y4, Y13, Y4 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y4, Y4 + VPADDW Y4, Y5, Y4 + VPADDW Y0, Y1, Y5 + VPMULLW Y3, Y7, Y8 + VPMULLW Y2, Y6, Y9 + VPMULLW Y2, Y7, Y10 + VPMULLW Y3, Y6, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y3, Y7, Y12 + VPMULHW Y2, Y6, Y13 + VPMULHW Y2, Y7, Y2 + VPMULHW Y3, Y6, Y3 + VMOVDQA Y12, Y6 + VMOVDQA Y13, Y7 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y6, Y6 + VPSUBW Y9, Y7, Y7 + VPSUBW Y10, Y2, Y2 + VPSUBW Y11, Y3, Y3 + VMOVDQU 864(BX), Y12 + VMOVDQU 896(BX), Y13 + VPMULLW Y6, Y12, Y8 + VPMULHW Y6, Y13, Y6 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y6, Y6 + VPSUBW Y6, Y7, Y6 + VPADDW Y2, Y3, Y7 + VMOVDQU Y4, 128(AX) + VMOVDQU Y5, 160(AX) + VMOVDQU Y6, 192(AX) + VMOVDQU Y7, 224(AX) + VMOVDQU 256(CX), Y0 + VMOVDQU 288(CX), Y1 + VMOVDQU 320(CX), Y2 + VMOVDQU 352(CX), Y3 + VMOVDQU 256(DX), Y4 + VMOVDQU 288(DX), Y5 + VMOVDQU 320(DX), Y6 + VMOVDQU 352(DX), Y7 + VPMULLW Y1, Y5, Y8 + VPMULLW Y0, Y4, Y9 + VPMULLW Y0, Y5, Y10 + VPMULLW Y1, Y4, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y1, Y5, Y12 + VPMULHW Y0, Y4, Y13 + VPMULHW Y0, Y5, Y0 + VPMULHW Y1, Y4, Y1 + VMOVDQA Y12, Y4 + VMOVDQA Y13, Y5 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y4, Y4 + VPSUBW Y9, Y5, Y5 + VPSUBW Y10, Y0, Y0 + VPSUBW Y11, Y1, Y1 + VMOVDQU 928(BX), Y12 + VMOVDQU 960(BX), Y13 + VPMULLW Y4, Y12, Y8 + VPMULHW Y4, Y13, Y4 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y4, Y4 + VPADDW Y4, Y5, Y4 + VPADDW Y0, Y1, Y5 + VPMULLW Y3, Y7, Y8 + VPMULLW Y2, Y6, Y9 + VPMULLW Y2, Y7, Y10 + VPMULLW Y3, Y6, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y3, Y7, Y12 + VPMULHW Y2, Y6, Y13 + VPMULHW Y2, Y7, Y2 + VPMULHW Y3, Y6, Y3 + VMOVDQA Y12, Y6 + VMOVDQA Y13, Y7 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y6, Y6 + VPSUBW Y9, Y7, Y7 + VPSUBW Y10, Y2, Y2 + VPSUBW Y11, Y3, Y3 + VMOVDQU 928(BX), Y12 + VMOVDQU 960(BX), Y13 + VPMULLW Y6, Y12, Y8 + VPMULHW Y6, Y13, Y6 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y6, Y6 + VPSUBW Y6, Y7, Y6 + VPADDW Y2, Y3, Y7 + VMOVDQU Y4, 256(AX) + VMOVDQU Y5, 288(AX) + VMOVDQU Y6, 320(AX) + VMOVDQU Y7, 352(AX) + VMOVDQU 384(CX), Y0 + VMOVDQU 416(CX), Y1 + VMOVDQU 448(CX), Y2 + VMOVDQU 480(CX), Y3 + VMOVDQU 384(DX), Y4 + VMOVDQU 416(DX), Y5 + VMOVDQU 448(DX), Y6 + VMOVDQU 480(DX), Y7 + VPMULLW Y1, Y5, Y8 + VPMULLW Y0, Y4, Y9 + VPMULLW Y0, Y5, Y10 + VPMULLW Y1, Y4, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y1, Y5, Y12 + VPMULHW Y0, Y4, Y13 + VPMULHW Y0, Y5, Y0 + VPMULHW Y1, Y4, Y1 + VMOVDQA Y12, Y4 + VMOVDQA Y13, Y5 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y4, Y4 + VPSUBW Y9, Y5, Y5 + VPSUBW Y10, Y0, Y0 + VPSUBW Y11, Y1, Y1 + VMOVDQU 992(BX), Y12 + VMOVDQU 1024(BX), Y13 + VPMULLW Y4, Y12, Y8 + VPMULHW Y4, Y13, Y4 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y4, Y4 + VPADDW Y4, Y5, Y4 + VPADDW Y0, Y1, Y5 + VPMULLW Y3, Y7, Y8 + VPMULLW Y2, Y6, Y9 + VPMULLW Y2, Y7, Y10 + VPMULLW Y3, Y6, Y11 + VPMULLW Y8, Y14, Y8 + VPMULLW Y9, Y14, Y9 + VPMULLW Y10, Y14, Y10 + VPMULLW Y11, Y14, Y11 + VPMULHW Y3, Y7, Y12 + VPMULHW Y2, Y6, Y13 + VPMULHW Y2, Y7, Y2 + VPMULHW Y3, Y6, Y3 + VMOVDQA Y12, Y6 + VMOVDQA Y13, Y7 + VPMULHW Y8, Y15, Y8 + VPMULHW Y9, Y15, Y9 + VPMULHW Y10, Y15, Y10 + VPMULHW Y11, Y15, Y11 + VPSUBW Y8, Y6, Y6 + VPSUBW Y9, Y7, Y7 + VPSUBW Y10, Y2, Y2 + VPSUBW Y11, Y3, Y3 + VMOVDQU 992(BX), Y12 + VMOVDQU 1024(BX), Y13 + VPMULLW Y6, Y12, Y8 + VPMULHW Y6, Y13, Y6 + VPMULHW Y8, Y15, Y8 + VPSUBW Y8, Y6, Y6 + VPSUBW Y6, Y7, Y6 + VPADDW Y2, Y3, Y7 + VMOVDQU Y4, 384(AX) + VMOVDQU Y5, 416(AX) + VMOVDQU Y6, 448(AX) + VMOVDQU Y7, 480(AX) + RET + +// func detangleAVX2(p *[256]int16) +// Requires: AVX, AVX2 +TEXT ·detangleAVX2(SB), NOSPLIT, $0-8 + MOVQ p+0(FP), AX + VMOVDQU (AX), Y0 + VMOVDQU 32(AX), Y1 + VMOVDQU 64(AX), Y2 + VMOVDQU 96(AX), Y3 + VMOVDQU 128(AX), Y4 + VMOVDQU 160(AX), Y5 + VMOVDQU 192(AX), Y6 + VMOVDQU 224(AX), Y7 + VPSLLD $0x10, Y1, Y8 + VPBLENDW $0xaa, Y8, Y0, Y8 + VPSRLD $0x10, Y0, Y0 + VPBLENDW $0xaa, Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPSLLD $0x10, Y3, Y8 + VPBLENDW $0xaa, Y8, Y2, Y8 + VPSRLD $0x10, Y2, Y2 + VPBLENDW $0xaa, Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPSLLD $0x10, Y5, Y8 + VPBLENDW $0xaa, Y8, Y4, Y8 + VPSRLD $0x10, Y4, Y4 + VPBLENDW $0xaa, Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPSLLD $0x10, Y7, Y8 + VPBLENDW $0xaa, Y8, Y6, Y8 + VPSRLD $0x10, Y6, Y6 + VPBLENDW $0xaa, Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VMOVSLDUP Y2, Y8 + VPBLENDD $0xaa, Y8, Y0, Y8 + VPSRLQ $0x20, Y0, Y0 + VPBLENDD $0xaa, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VMOVSLDUP Y3, Y8 + VPBLENDD $0xaa, Y8, Y1, Y8 + VPSRLQ $0x20, Y1, Y1 + VPBLENDD $0xaa, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VMOVSLDUP Y6, Y8 + VPBLENDD $0xaa, Y8, Y4, Y8 + VPSRLQ $0x20, Y4, Y4 + VPBLENDD $0xaa, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VMOVSLDUP Y7, Y8 + VPBLENDD $0xaa, Y8, Y5, Y8 + VPSRLQ $0x20, Y5, Y5 + VPBLENDD $0xaa, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VPUNPCKLQDQ Y1, Y0, Y8 + VPUNPCKHQDQ Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPUNPCKLQDQ Y3, Y2, Y8 + VPUNPCKHQDQ Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPUNPCKLQDQ Y5, Y4, Y8 + VPUNPCKHQDQ Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPUNPCKLQDQ Y7, Y6, Y8 + VPUNPCKHQDQ Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VPERM2I128 $0x20, Y2, Y0, Y8 + VPERM2I128 $0x31, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VPERM2I128 $0x20, Y3, Y1, Y8 + VPERM2I128 $0x31, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VPERM2I128 $0x20, Y6, Y4, Y8 + VPERM2I128 $0x31, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VPERM2I128 $0x20, Y7, Y5, Y8 + VPERM2I128 $0x31, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VMOVDQU Y0, (AX) + VMOVDQU Y1, 32(AX) + VMOVDQU Y2, 64(AX) + VMOVDQU Y3, 96(AX) + VMOVDQU Y4, 128(AX) + VMOVDQU Y5, 160(AX) + VMOVDQU Y6, 192(AX) + VMOVDQU Y7, 224(AX) + VMOVDQU 256(AX), Y0 + VMOVDQU 288(AX), Y1 + VMOVDQU 320(AX), Y2 + VMOVDQU 352(AX), Y3 + VMOVDQU 384(AX), Y4 + VMOVDQU 416(AX), Y5 + VMOVDQU 448(AX), Y6 + VMOVDQU 480(AX), Y7 + VPSLLD $0x10, Y1, Y8 + VPBLENDW $0xaa, Y8, Y0, Y8 + VPSRLD $0x10, Y0, Y0 + VPBLENDW $0xaa, Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPSLLD $0x10, Y3, Y8 + VPBLENDW $0xaa, Y8, Y2, Y8 + VPSRLD $0x10, Y2, Y2 + VPBLENDW $0xaa, Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPSLLD $0x10, Y5, Y8 + VPBLENDW $0xaa, Y8, Y4, Y8 + VPSRLD $0x10, Y4, Y4 + VPBLENDW $0xaa, Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPSLLD $0x10, Y7, Y8 + VPBLENDW $0xaa, Y8, Y6, Y8 + VPSRLD $0x10, Y6, Y6 + VPBLENDW $0xaa, Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VMOVSLDUP Y2, Y8 + VPBLENDD $0xaa, Y8, Y0, Y8 + VPSRLQ $0x20, Y0, Y0 + VPBLENDD $0xaa, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VMOVSLDUP Y3, Y8 + VPBLENDD $0xaa, Y8, Y1, Y8 + VPSRLQ $0x20, Y1, Y1 + VPBLENDD $0xaa, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VMOVSLDUP Y6, Y8 + VPBLENDD $0xaa, Y8, Y4, Y8 + VPSRLQ $0x20, Y4, Y4 + VPBLENDD $0xaa, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VMOVSLDUP Y7, Y8 + VPBLENDD $0xaa, Y8, Y5, Y8 + VPSRLQ $0x20, Y5, Y5 + VPBLENDD $0xaa, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VPUNPCKLQDQ Y1, Y0, Y8 + VPUNPCKHQDQ Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPUNPCKLQDQ Y3, Y2, Y8 + VPUNPCKHQDQ Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPUNPCKLQDQ Y5, Y4, Y8 + VPUNPCKHQDQ Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPUNPCKLQDQ Y7, Y6, Y8 + VPUNPCKHQDQ Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VPERM2I128 $0x20, Y2, Y0, Y8 + VPERM2I128 $0x31, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VPERM2I128 $0x20, Y3, Y1, Y8 + VPERM2I128 $0x31, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VPERM2I128 $0x20, Y6, Y4, Y8 + VPERM2I128 $0x31, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VPERM2I128 $0x20, Y7, Y5, Y8 + VPERM2I128 $0x31, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VMOVDQU Y0, 256(AX) + VMOVDQU Y1, 288(AX) + VMOVDQU Y2, 320(AX) + VMOVDQU Y3, 352(AX) + VMOVDQU Y4, 384(AX) + VMOVDQU Y5, 416(AX) + VMOVDQU Y6, 448(AX) + VMOVDQU Y7, 480(AX) + RET + +// func tangleAVX2(p *[256]int16) +// Requires: AVX, AVX2 +TEXT ·tangleAVX2(SB), NOSPLIT, $0-8 + MOVQ p+0(FP), AX + VMOVDQU (AX), Y0 + VMOVDQU 32(AX), Y1 + VMOVDQU 64(AX), Y2 + VMOVDQU 96(AX), Y3 + VMOVDQU 128(AX), Y4 + VMOVDQU 160(AX), Y5 + VMOVDQU 192(AX), Y6 + VMOVDQU 224(AX), Y7 + VPERM2I128 $0x20, Y2, Y0, Y8 + VPERM2I128 $0x31, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VPERM2I128 $0x20, Y3, Y1, Y8 + VPERM2I128 $0x31, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VPERM2I128 $0x20, Y6, Y4, Y8 + VPERM2I128 $0x31, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VPERM2I128 $0x20, Y7, Y5, Y8 + VPERM2I128 $0x31, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VPUNPCKLQDQ Y1, Y0, Y8 + VPUNPCKHQDQ Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPUNPCKLQDQ Y3, Y2, Y8 + VPUNPCKHQDQ Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPUNPCKLQDQ Y5, Y4, Y8 + VPUNPCKHQDQ Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPUNPCKLQDQ Y7, Y6, Y8 + VPUNPCKHQDQ Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VMOVSLDUP Y2, Y8 + VPBLENDD $0xaa, Y8, Y0, Y8 + VPSRLQ $0x20, Y0, Y0 + VPBLENDD $0xaa, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VMOVSLDUP Y3, Y8 + VPBLENDD $0xaa, Y8, Y1, Y8 + VPSRLQ $0x20, Y1, Y1 + VPBLENDD $0xaa, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VMOVSLDUP Y6, Y8 + VPBLENDD $0xaa, Y8, Y4, Y8 + VPSRLQ $0x20, Y4, Y4 + VPBLENDD $0xaa, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VMOVSLDUP Y7, Y8 + VPBLENDD $0xaa, Y8, Y5, Y8 + VPSRLQ $0x20, Y5, Y5 + VPBLENDD $0xaa, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VPSLLD $0x10, Y1, Y8 + VPBLENDW $0xaa, Y8, Y0, Y8 + VPSRLD $0x10, Y0, Y0 + VPBLENDW $0xaa, Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPSLLD $0x10, Y3, Y8 + VPBLENDW $0xaa, Y8, Y2, Y8 + VPSRLD $0x10, Y2, Y2 + VPBLENDW $0xaa, Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPSLLD $0x10, Y5, Y8 + VPBLENDW $0xaa, Y8, Y4, Y8 + VPSRLD $0x10, Y4, Y4 + VPBLENDW $0xaa, Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPSLLD $0x10, Y7, Y8 + VPBLENDW $0xaa, Y8, Y6, Y8 + VPSRLD $0x10, Y6, Y6 + VPBLENDW $0xaa, Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VMOVDQU Y0, (AX) + VMOVDQU Y1, 32(AX) + VMOVDQU Y2, 64(AX) + VMOVDQU Y3, 96(AX) + VMOVDQU Y4, 128(AX) + VMOVDQU Y5, 160(AX) + VMOVDQU Y6, 192(AX) + VMOVDQU Y7, 224(AX) + VMOVDQU 256(AX), Y0 + VMOVDQU 288(AX), Y1 + VMOVDQU 320(AX), Y2 + VMOVDQU 352(AX), Y3 + VMOVDQU 384(AX), Y4 + VMOVDQU 416(AX), Y5 + VMOVDQU 448(AX), Y6 + VMOVDQU 480(AX), Y7 + VPERM2I128 $0x20, Y2, Y0, Y8 + VPERM2I128 $0x31, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VPERM2I128 $0x20, Y3, Y1, Y8 + VPERM2I128 $0x31, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VPERM2I128 $0x20, Y6, Y4, Y8 + VPERM2I128 $0x31, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VPERM2I128 $0x20, Y7, Y5, Y8 + VPERM2I128 $0x31, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VPUNPCKLQDQ Y1, Y0, Y8 + VPUNPCKHQDQ Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPUNPCKLQDQ Y3, Y2, Y8 + VPUNPCKHQDQ Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPUNPCKLQDQ Y5, Y4, Y8 + VPUNPCKHQDQ Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPUNPCKLQDQ Y7, Y6, Y8 + VPUNPCKHQDQ Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VMOVSLDUP Y2, Y8 + VPBLENDD $0xaa, Y8, Y0, Y8 + VPSRLQ $0x20, Y0, Y0 + VPBLENDD $0xaa, Y2, Y0, Y2 + VMOVDQA Y8, Y0 + VMOVSLDUP Y3, Y8 + VPBLENDD $0xaa, Y8, Y1, Y8 + VPSRLQ $0x20, Y1, Y1 + VPBLENDD $0xaa, Y3, Y1, Y3 + VMOVDQA Y8, Y1 + VMOVSLDUP Y6, Y8 + VPBLENDD $0xaa, Y8, Y4, Y8 + VPSRLQ $0x20, Y4, Y4 + VPBLENDD $0xaa, Y6, Y4, Y6 + VMOVDQA Y8, Y4 + VMOVSLDUP Y7, Y8 + VPBLENDD $0xaa, Y8, Y5, Y8 + VPSRLQ $0x20, Y5, Y5 + VPBLENDD $0xaa, Y7, Y5, Y7 + VMOVDQA Y8, Y5 + VPSLLD $0x10, Y1, Y8 + VPBLENDW $0xaa, Y8, Y0, Y8 + VPSRLD $0x10, Y0, Y0 + VPBLENDW $0xaa, Y1, Y0, Y1 + VMOVDQA Y8, Y0 + VPSLLD $0x10, Y3, Y8 + VPBLENDW $0xaa, Y8, Y2, Y8 + VPSRLD $0x10, Y2, Y2 + VPBLENDW $0xaa, Y3, Y2, Y3 + VMOVDQA Y8, Y2 + VPSLLD $0x10, Y5, Y8 + VPBLENDW $0xaa, Y8, Y4, Y8 + VPSRLD $0x10, Y4, Y4 + VPBLENDW $0xaa, Y5, Y4, Y5 + VMOVDQA Y8, Y4 + VPSLLD $0x10, Y7, Y8 + VPBLENDW $0xaa, Y8, Y6, Y8 + VPSRLD $0x10, Y6, Y6 + VPBLENDW $0xaa, Y7, Y6, Y7 + VMOVDQA Y8, Y6 + VMOVDQU Y0, 256(AX) + VMOVDQU Y1, 288(AX) + VMOVDQU Y2, 320(AX) + VMOVDQU Y3, 352(AX) + VMOVDQU Y4, 384(AX) + VMOVDQU Y5, 416(AX) + VMOVDQU Y6, 448(AX) + VMOVDQU Y7, 480(AX) + RET + +// func barrettReduceAVX2(p *[256]int16) +// Requires: AVX, AVX2 +TEXT ·barrettReduceAVX2(SB), NOSPLIT, $0-8 + MOVQ p+0(FP), AX + MOVL $0x00000d01, CX + VMOVD CX, X0 + VPBROADCASTW X0, Y9 + MOVL $0x00004ebf, CX + VMOVD CX, X0 + VPBROADCASTW X0, Y8 + VMOVDQU (AX), Y0 + VMOVDQU 32(AX), Y1 + VMOVDQU 64(AX), Y2 + VMOVDQU 96(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VMOVDQU Y0, (AX) + VMOVDQU Y1, 32(AX) + VMOVDQU Y2, 64(AX) + VMOVDQU Y3, 96(AX) + VMOVDQU 128(AX), Y0 + VMOVDQU 160(AX), Y1 + VMOVDQU 192(AX), Y2 + VMOVDQU 224(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VMOVDQU Y0, 128(AX) + VMOVDQU Y1, 160(AX) + VMOVDQU Y2, 192(AX) + VMOVDQU Y3, 224(AX) + VMOVDQU 256(AX), Y0 + VMOVDQU 288(AX), Y1 + VMOVDQU 320(AX), Y2 + VMOVDQU 352(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VMOVDQU Y0, 256(AX) + VMOVDQU Y1, 288(AX) + VMOVDQU Y2, 320(AX) + VMOVDQU Y3, 352(AX) + VMOVDQU 384(AX), Y0 + VMOVDQU 416(AX), Y1 + VMOVDQU 448(AX), Y2 + VMOVDQU 480(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VMOVDQU Y0, 384(AX) + VMOVDQU Y1, 416(AX) + VMOVDQU Y2, 448(AX) + VMOVDQU Y3, 480(AX) + RET + +// func normalizeAVX2(p *[256]int16) +// Requires: AVX, AVX2 +TEXT ·normalizeAVX2(SB), NOSPLIT, $0-8 + MOVQ p+0(FP), AX + MOVL $0x00000d01, CX + VMOVD CX, X0 + VPBROADCASTW X0, Y9 + MOVL $0x00004ebf, CX + VMOVD CX, X0 + VPBROADCASTW X0, Y8 + VMOVDQU (AX), Y0 + VMOVDQU 32(AX), Y1 + VMOVDQU 64(AX), Y2 + VMOVDQU 96(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VPSUBW Y9, Y0, Y0 + VPSUBW Y9, Y1, Y1 + VPSUBW Y9, Y2, Y2 + VPSUBW Y9, Y3, Y3 + VPSRAW $0x0f, Y0, Y4 + VPSRAW $0x0f, Y1, Y5 + VPSRAW $0x0f, Y2, Y6 + VPSRAW $0x0f, Y3, Y7 + VPAND Y4, Y9, Y4 + VPAND Y5, Y9, Y5 + VPAND Y6, Y9, Y6 + VPAND Y7, Y9, Y7 + VPADDW Y0, Y4, Y0 + VPADDW Y1, Y5, Y1 + VPADDW Y2, Y6, Y2 + VPADDW Y3, Y7, Y3 + VMOVDQU Y0, (AX) + VMOVDQU Y1, 32(AX) + VMOVDQU Y2, 64(AX) + VMOVDQU Y3, 96(AX) + VMOVDQU 128(AX), Y0 + VMOVDQU 160(AX), Y1 + VMOVDQU 192(AX), Y2 + VMOVDQU 224(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VPSUBW Y9, Y0, Y0 + VPSUBW Y9, Y1, Y1 + VPSUBW Y9, Y2, Y2 + VPSUBW Y9, Y3, Y3 + VPSRAW $0x0f, Y0, Y4 + VPSRAW $0x0f, Y1, Y5 + VPSRAW $0x0f, Y2, Y6 + VPSRAW $0x0f, Y3, Y7 + VPAND Y4, Y9, Y4 + VPAND Y5, Y9, Y5 + VPAND Y6, Y9, Y6 + VPAND Y7, Y9, Y7 + VPADDW Y0, Y4, Y0 + VPADDW Y1, Y5, Y1 + VPADDW Y2, Y6, Y2 + VPADDW Y3, Y7, Y3 + VMOVDQU Y0, 128(AX) + VMOVDQU Y1, 160(AX) + VMOVDQU Y2, 192(AX) + VMOVDQU Y3, 224(AX) + VMOVDQU 256(AX), Y0 + VMOVDQU 288(AX), Y1 + VMOVDQU 320(AX), Y2 + VMOVDQU 352(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VPSUBW Y9, Y0, Y0 + VPSUBW Y9, Y1, Y1 + VPSUBW Y9, Y2, Y2 + VPSUBW Y9, Y3, Y3 + VPSRAW $0x0f, Y0, Y4 + VPSRAW $0x0f, Y1, Y5 + VPSRAW $0x0f, Y2, Y6 + VPSRAW $0x0f, Y3, Y7 + VPAND Y4, Y9, Y4 + VPAND Y5, Y9, Y5 + VPAND Y6, Y9, Y6 + VPAND Y7, Y9, Y7 + VPADDW Y0, Y4, Y0 + VPADDW Y1, Y5, Y1 + VPADDW Y2, Y6, Y2 + VPADDW Y3, Y7, Y3 + VMOVDQU Y0, 256(AX) + VMOVDQU Y1, 288(AX) + VMOVDQU Y2, 320(AX) + VMOVDQU Y3, 352(AX) + VMOVDQU 384(AX), Y0 + VMOVDQU 416(AX), Y1 + VMOVDQU 448(AX), Y2 + VMOVDQU 480(AX), Y3 + VPMULHW Y8, Y0, Y4 + VPMULHW Y8, Y1, Y5 + VPMULHW Y8, Y2, Y6 + VPMULHW Y8, Y3, Y7 + VPSRAW $0x0a, Y4, Y4 + VPSRAW $0x0a, Y5, Y5 + VPSRAW $0x0a, Y6, Y6 + VPSRAW $0x0a, Y7, Y7 + VPMULLW Y9, Y4, Y4 + VPMULLW Y9, Y5, Y5 + VPMULLW Y9, Y6, Y6 + VPMULLW Y9, Y7, Y7 + VPSUBW Y4, Y0, Y0 + VPSUBW Y5, Y1, Y1 + VPSUBW Y6, Y2, Y2 + VPSUBW Y7, Y3, Y3 + VPSUBW Y9, Y0, Y0 + VPSUBW Y9, Y1, Y1 + VPSUBW Y9, Y2, Y2 + VPSUBW Y9, Y3, Y3 + VPSRAW $0x0f, Y0, Y4 + VPSRAW $0x0f, Y1, Y5 + VPSRAW $0x0f, Y2, Y6 + VPSRAW $0x0f, Y3, Y7 + VPAND Y4, Y9, Y4 + VPAND Y5, Y9, Y5 + VPAND Y6, Y9, Y6 + VPAND Y7, Y9, Y7 + VPADDW Y0, Y4, Y0 + VPADDW Y1, Y5, Y1 + VPADDW Y2, Y6, Y2 + VPADDW Y3, Y7, Y3 + VMOVDQU Y0, 384(AX) + VMOVDQU Y1, 416(AX) + VMOVDQU Y2, 448(AX) + VMOVDQU Y3, 480(AX) + RET diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/field.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/field.go new file mode 100644 index 00000000000..31e93ed524f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/field.go @@ -0,0 +1,74 @@ +package common + +// Given -2¹⁵ q ≤ x < 2¹⁵ q, returns -q < y < q with x 2⁻¹⁶ = y (mod q). +func montReduce(x int32) int16 { + // This is Montgomery reduction with R=2¹⁶. + // + // Note gcd(2¹⁶, q) = 1 as q is prime. Write q' := 62209 = q⁻¹ mod R. + // First we compute + // + // m := ((x mod R) q') mod R + // = x q' mod R + // = int16(x q') + // = int16(int32(x) * int32(q')) + // + // Note that x q' might be as big as 2³² and could overflow the int32 + // multiplication in the last line. However for any int32s a and b, + // we have int32(int64(a)*int64(b)) = int32(a*b) and so the result is ok. + m := int16(x * 62209) + + // Note that x - m q is divisible by R; indeed modulo R we have + // + // x - m q ≡ x - x q' q ≡ x - x q⁻¹ q ≡ x - x = 0. + // + // We return y := (x - m q) / R. Note that y is indeed correct as + // modulo q we have + // + // y ≡ x R⁻¹ - m q R⁻¹ = x R⁻¹ + // + // and as both 2¹⁵ q ≤ m q, x < 2¹⁵ q, we have + // 2¹⁶ q ≤ x - m q < 2¹⁶ and so q ≤ (x - m q) / R < q as desired. + return int16(uint32(x-int32(m)*int32(Q)) >> 16) +} + +// Given any x, returns x R mod q where R=2¹⁶. +func toMont(x int16) int16 { + // Note |1353 x| ≤ 1353 2¹⁵ ≤ 13318 q ≤ 2¹⁵ q and so we're within + // the bounds of montReduce. + return montReduce(int32(x) * 1353) // 1353 = R² mod q. +} + +// Given any x, compute 0 ≤ y ≤ q with x = y (mod q). +// +// Beware: we might have barrettReduce(x) = q ≠ 0 for some x. In fact, +// this happens if and only if x = -nq for some positive integer n. +func barrettReduce(x int16) int16 { + // This is standard Barrett reduction. + // + // For any x we have x mod q = x - ⌊x/q⌋ q. We will use 20159/2²⁶ as + // an approximation of 1/q. Note that 0 ≤ 20159/2²⁶ - 1/q ≤ 0.135/2²⁶ + // and so | x 20156/2²⁶ - x/q | ≤ 2⁻¹⁰ for |x| ≤ 2¹⁶. For all x + // not a multiple of q, the number x/q is further than 1/q from any integer + // and so ⌊x 20156/2²⁶⌋ = ⌊x/q⌋. If x is a multiple of q and x is positive, + // then x 20156/2²⁶ is larger than x/q so ⌊x 20156/2²⁶⌋ = ⌊x/q⌋ as well. + // Finally, if x is negative multiple of q, then ⌊x 20156/2²⁶⌋ = ⌊x/q⌋-1. + // Thus + // [ q if x=-nq for pos. integer n + // x - ⌊x 20156/2²⁶⌋ q = [ + // [ x mod q otherwise + // + // To compute actually compute this, note that + // + // ⌊x 20156/2²⁶⌋ = (20159 x) >> 26. + return x - int16((int32(x)*20159)>>26)*Q +} + +// Returns x if x < q and x - q otherwise. Assumes x ≥ -29439. +func csubq(x int16) int16 { + x -= Q // no overflow due to assumption x ≥ -29439. + // If x is positive, then x >> 15 = 0. If x is negative, + // then uint16(x >> 15) = 2¹⁶-1. So this will add back in q + // if x was smaller than q. + x += (x >> 15) & Q + return x +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/generic.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/generic.go new file mode 100644 index 00000000000..66e0e86dc8c --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/generic.go @@ -0,0 +1,77 @@ +//go:build !amd64 || purego +// +build !amd64 purego + +package common + +// Sets p to a + b. Does not normalize coefficients. +func (p *Poly) Add(a, b *Poly) { + p.addGeneric(a, b) +} + +// Sets p to a - b. Does not normalize coefficients. +func (p *Poly) Sub(a, b *Poly) { + p.subGeneric(a, b) +} + +// Executes an in-place forward "NTT" on p. +// +// Assumes the coefficients are in absolute value ≤q. The resulting +// coefficients are in absolute value ≤7q. If the input is in Montgomery +// form, then the result is in Montgomery form and so (by linearity of the NTT) +// if the input is in regular form, then the result is also in regular form. +// The order of coefficients will be "tangled". These can be put back into +// their proper order by calling Detangle(). +func (p *Poly) NTT() { + p.nttGeneric() +} + +// Executes an in-place inverse "NTT" on p and multiply by the Montgomery +// factor R. +// +// Requires coefficients to be in "tangled" order, see Tangle(). +// Assumes the coefficients are in absolute value ≤q. The resulting +// coefficients are in absolute value ≤q. If the input is in Montgomery +// form, then the result is in Montgomery form and so (by linearity) +// if the input is in regular form, then the result is also in regular form. +func (p *Poly) InvNTT() { + p.invNTTGeneric() +} + +// Sets p to the "pointwise" multiplication of a and b. +// +// That is: InvNTT(p) = InvNTT(a) * InvNTT(b). Assumes a and b are in +// Montgomery form. Products between coefficients of a and b must be strictly +// bounded in absolute value by 2¹⁵q. p will be in Montgomery form and +// bounded in absolute value by 2q. +// +// Requires a and b to be in "tangled" order, see Tangle(). p will be in +// tangled order as well. +func (p *Poly) MulHat(a, b *Poly) { + p.mulHatGeneric(a, b) +} + +// Puts p into the right form to be used with (among others) InvNTT(). +func (p *Poly) Tangle() { + // In the generic implementation there is no advantage to using a + // different order, so we use the standard order everywhere. +} + +// Puts p back into standard form. +func (p *Poly) Detangle() { + // In the generic implementation there is no advantage to using a + // different order, so we use the standard order everywhere. +} + +// Almost normalizes coefficients. +// +// Ensures each coefficient is in {0, …, q}. +func (p *Poly) BarrettReduce() { + p.barrettReduceGeneric() +} + +// Normalizes coefficients. +// +// Ensures each coefficient is in {0, …, q-1}. +func (p *Poly) Normalize() { + p.normalizeGeneric() +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/ntt.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/ntt.go new file mode 100644 index 00000000000..5e565b34407 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/ntt.go @@ -0,0 +1,193 @@ +package common + +// Zetas lists precomputed powers of the primitive root of unity in +// Montgomery representation used for the NTT: +// +// Zetas[i] = ζᵇʳᵛ⁽ⁱ⁾ R mod q +// +// where ζ = 17, brv(i) is the bitreversal of a 7-bit number and R=2¹⁶ mod q. +// +// The following Python code generates the Zetas arrays: +// +// q = 13*2**8 + 1; zeta = 17 +// R = 2**16 % q # Montgomery const. +// def brv(x): return int(''.join(reversed(bin(x)[2:].zfill(7))),2) +// print([(pow(zeta, brv(i), q)*R)%q for i in range(128)]) +var Zetas = [128]int16{ + 2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, + 962, 2127, 1855, 1468, 573, 2004, 264, 383, 2500, 1458, 1727, 3199, + 2648, 1017, 732, 608, 1787, 411, 3124, 1758, 1223, 652, 2777, 1015, + 2036, 1491, 3047, 1785, 516, 3321, 3009, 2663, 1711, 2167, 126, + 1469, 2476, 3239, 3058, 830, 107, 1908, 3082, 2378, 2931, 961, 1821, + 2604, 448, 2264, 677, 2054, 2226, 430, 555, 843, 2078, 871, 1550, + 105, 422, 587, 177, 3094, 3038, 2869, 1574, 1653, 3083, 778, 1159, + 3182, 2552, 1483, 2727, 1119, 1739, 644, 2457, 349, 418, 329, 3173, + 3254, 817, 1097, 603, 610, 1322, 2044, 1864, 384, 2114, 3193, 1218, + 1994, 2455, 220, 2142, 1670, 2144, 1799, 2051, 794, 1819, 2475, + 2459, 478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628, +} + +// InvNTTReductions keeps track of which coefficients to apply Barrett +// reduction to in Poly.InvNTT(). +// +// Generated in a lazily: once a butterfly is computed which is about to +// overflow the int16, the largest coefficient is reduced. If that is +// not enough, the other coefficient is reduced as well. +// +// This is actually optimal, as proven in https://eprint.iacr.org/2020/1377.pdf +var InvNTTReductions = [...]int{ + -1, // after layer 1 + -1, // after layer 2 + 16, 17, 48, 49, 80, 81, 112, 113, 144, 145, 176, 177, 208, 209, 240, + 241, -1, // after layer 3 + 0, 1, 32, 33, 34, 35, 64, 65, 96, 97, 98, 99, 128, 129, 160, 161, 162, 163, + 192, 193, 224, 225, 226, 227, -1, // after layer 4 + 2, 3, 66, 67, 68, 69, 70, 71, 130, 131, 194, 195, 196, 197, 198, + 199, -1, // after layer 5 + 4, 5, 6, 7, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, -1, // after layer 6 + -1, // after layer 7 +} + +// Executes an in-place forward "NTT" on p. +// +// Assumes the coefficients are in absolute value ≤q. The resulting +// coefficients are in absolute value ≤7q. If the input is in Montgomery +// form, then the result is in Montgomery form and so (by linearity of the NTT) +// if the input is in regular form, then the result is also in regular form. +// The order of coefficients will be "tangled". These can be put back into +// their proper order by calling Detangle(). +func (p *Poly) nttGeneric() { + // Note that ℤ_q does not have a primitive 512ᵗʰ root of unity (as 512 + // does not divide into q-1) and so we cannot do a regular NTT. ℤ_q + // does have a primitive 256ᵗʰ root of unity, the smallest of which + // is ζ := 17. + // + // Recall that our base ring R := ℤ_q[x] / (x²⁵⁶ + 1). The polynomial + // x²⁵⁶+1 will not split completely (as its roots would be 512ᵗʰ roots + // of unity.) However, it does split almost (using ζ¹²⁸ = -1): + // + // x²⁵⁶ + 1 = (x²)¹²⁸ - ζ¹²⁸ + // = ((x²)⁶⁴ - ζ⁶⁴)((x²)⁶⁴ + ζ⁶⁴) + // = ((x²)³² - ζ³²)((x²)³² + ζ³²)((x²)³² - ζ⁹⁶)((x²)³² + ζ⁹⁶) + // ⋮ + // = (x² - ζ)(x² + ζ)(x² - ζ⁶⁵)(x² + ζ⁶⁵) … (x² + ζ¹²⁷) + // + // Note that the powers of ζ that appear (from the second line down) are + // in binary + // + // 0100000 1100000 + // 0010000 1010000 0110000 1110000 + // 0001000 1001000 0101000 1101000 0011000 1011000 0111000 1111000 + // … + // + // That is: brv(2), brv(3), brv(4), …, where brv(x) denotes the 7-bit + // bitreversal of x. These powers of ζ are given by the Zetas array. + // + // The polynomials x² ± ζⁱ are irreducible and coprime, hence by + // the Chinese Remainder Theorem we know + // + // ℤ_q[x]/(x²⁵⁶+1) → ℤ_q[x]/(x²-ζ) x … x ℤ_q[x]/(x²+ζ¹²⁷) + // + // given by a ↦ ( a mod x²-ζ, …, a mod x²+ζ¹²⁷ ) + // is an isomorphism, which is the "NTT". It can be efficiently computed by + // + // + // a ↦ ( a mod (x²)⁶⁴ - ζ⁶⁴, a mod (x²)⁶⁴ + ζ⁶⁴ ) + // ↦ ( a mod (x²)³² - ζ³², a mod (x²)³² + ζ³², + // a mod (x²)⁹⁶ - ζ⁹⁶, a mod (x²)⁹⁶ + ζ⁹⁶ ) + // + // et cetera + // + // If N was 8 then this can be pictured in the following diagram: + // + // https://cnx.org/resources/17ee4dfe517a6adda05377b25a00bf6e6c93c334/File0026.png + // + // Each cross is a Cooley-Tukey butterfly: it's the map + // + // (a, b) ↦ (a + ζb, a - ζb) + // + // for the appropriate power ζ for that column and row group. + + k := 0 // Index into Zetas + + // l runs effectively over the columns in the diagram above; it is half the + // height of a row group, i.e. the number of butterflies in each row group. + // In the diagram above it would be 4, 2, 1. + for l := N / 2; l > 1; l >>= 1 { + // On the nᵗʰ iteration of the l-loop, the absolute value of the + // coefficients are bounded by nq. + + // offset effectively loops over the row groups in this column; it is + // the first row in the row group. + for offset := 0; offset < N-l; offset += 2 * l { + k++ + zeta := int32(Zetas[k]) + + // j loops over each butterfly in the row group. + for j := offset; j < offset+l; j++ { + t := montReduce(zeta * int32(p[j+l])) + p[j+l] = p[j] - t + p[j] += t + } + } + } +} + +// Executes an in-place inverse "NTT" on p and multiply by the Montgomery +// factor R. +// +// Requires coefficients to be in "tangled" order, see Tangle(). +// Assumes the coefficients are in absolute value ≤q. The resulting +// coefficients are in absolute value ≤q. If the input is in Montgomery +// form, then the result is in Montgomery form and so (by linearity) +// if the input is in regular form, then the result is also in regular form. +func (p *Poly) invNTTGeneric() { + k := 127 // Index into Zetas + r := -1 // Index into InvNTTReductions. + + // We basically do the opposite of NTT, but postpone dividing by 2 in the + // inverse of the Cooley-Tukey butterfly and accumulate that into a big + // division by 2⁷ at the end. See the comments in the NTT() function. + + for l := 2; l < N; l <<= 1 { + for offset := 0; offset < N-l; offset += 2 * l { + // As we're inverting, we need powers of ζ⁻¹ (instead of ζ). + // To be precise, we need ζᵇʳᵛ⁽ᵏ⁾⁻¹²⁸. However, as ζ⁻¹²⁸ = -1, + // we can use the existing Zetas table instead of + // keeping a separate InvZetas table as in Dilithium. + + minZeta := int32(Zetas[k]) + k-- + + for j := offset; j < offset+l; j++ { + // Gentleman-Sande butterfly: (a, b) ↦ (a + b, ζ(a-b)) + t := p[j+l] - p[j] + p[j] += p[j+l] + p[j+l] = montReduce(minZeta * int32(t)) + + // Note that if we had |a| < αq and |b| < βq before the + // butterfly, then now we have |a| < (α+β)q and |b| < q. + } + } + + // We let the InvNTTReductions instruct us which coefficients to + // Barrett reduce. See TestInvNTTReductions, which tests whether + // there is an overflow. + for { + r++ + i := InvNTTReductions[r] + if i < 0 { + break + } + p[i] = barrettReduce(p[i]) + } + } + + for j := 0; j < N; j++ { + // Note 1441 = (128)⁻¹ R². The coefficients are bounded by 9q, so + // as 1441 * 9 ≈ 2¹⁴ < 2¹⁵, we're within the required bounds + // for montReduce(). + p[j] = montReduce(1441 * int32(p[j])) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params.go new file mode 100644 index 00000000000..f04d1aaa32c --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params.go @@ -0,0 +1,22 @@ +package common + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common/params" +) + +const ( + // Q is the parameter q ≡ 3329 = 2¹¹ + 2¹⁰ + 2⁸ + 1. + Q = params.Q + + // N is the parameter N: the length of the polynomials + N = params.N + + // PolySize is the size of a packed polynomial. + PolySize = params.PolySize + + // PlaintextSize is the size of the plaintext + PlaintextSize = params.PlaintextSize + + // Eta2 is the parameter η₂ + Eta2 = params.Eta2 +) diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params/params.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params/params.go new file mode 100644 index 00000000000..dee58ee99e6 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params/params.go @@ -0,0 +1,21 @@ +package params + +// We put these parameters in a separate package so that the Go code, +// such as asm/src.go, that generates assembler can import it. + +const ( + // Q is the parameter q ≡ 3329 = 2¹¹ + 2¹⁰ + 2⁸ + 1. + Q int16 = 3329 + + // N is the parameter N: the length of the polynomials + N = 256 + + // PolySize is the size of a packed polynomial. + PolySize = 384 + + // PlaintextSize is the size of the plaintext + PlaintextSize = 32 + + // Eta2 is the parameter η₂ + Eta2 = 2 +) diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/poly.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/poly.go new file mode 100644 index 00000000000..f580e9150d6 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/poly.go @@ -0,0 +1,332 @@ +package common + +// An element of our base ring R which are polynomials over ℤ_q +// modulo the equation Xᴺ = -1, where q=3329 and N=256. +// +// This type is also used to store NTT-transformed polynomials, +// see Poly.NTT(). +// +// Coefficients aren't always reduced. See Normalize(). +type Poly [N]int16 + +// Sets p to a + b. Does not normalize coefficients. +func (p *Poly) addGeneric(a, b *Poly) { + for i := 0; i < N; i++ { + p[i] = a[i] + b[i] + } +} + +// Sets p to a - b. Does not normalize coefficients. +func (p *Poly) subGeneric(a, b *Poly) { + for i := 0; i < N; i++ { + p[i] = a[i] - b[i] + } +} + +// Almost normalizes coefficients. +// +// Ensures each coefficient is in {0, …, q}. +func (p *Poly) barrettReduceGeneric() { + for i := 0; i < N; i++ { + p[i] = barrettReduce(p[i]) + } +} + +// Normalizes coefficients. +// +// Ensures each coefficient is in {0, …, q-1}. +func (p *Poly) normalizeGeneric() { + for i := 0; i < N; i++ { + p[i] = csubq(barrettReduce(p[i])) + } +} + +// Multiplies p in-place by the Montgomery factor 2¹⁶. +// +// Coefficients of p can be arbitrary. Resulting coefficients are bounded +// in absolute value by q. +func (p *Poly) ToMont() { + for i := 0; i < N; i++ { + p[i] = toMont(p[i]) + } +} + +// Sets p to the "pointwise" multiplication of a and b. +// +// That is: InvNTT(p) = InvNTT(a) * InvNTT(b). Assumes a and b are in +// Montgomery form. Products between coefficients of a and b must be strictly +// bounded in absolute value by 2¹⁵q. p will be in Montgomery form and +// bounded in absolute value by 2q. +// +// Requires a and b to be in "tangled" order, see Tangle(). p will be in +// tangled order as well. +func (p *Poly) mulHatGeneric(a, b *Poly) { + // Recall from the discussion in NTT(), that a transformed polynomial is + // an element of ℤ_q[x]/(x²-ζ) x … x ℤ_q[x]/(x²+ζ¹²⁷); + // that is: 128 degree-one polynomials instead of simply 256 elements + // from ℤ_q as in the regular NTT. So instead of pointwise multiplication, + // we multiply the 128 pairs of degree-one polynomials modulo the + // right equation: + // + // (a₁ + a₂x)(b₁ + b₂x) = a₁b₁ + a₂b₂ζ' + (a₁b₂ + a₂b₁)x, + // + // where ζ' is the appropriate power of ζ. + + k := 64 + for i := 0; i < N; i += 4 { + zeta := int32(Zetas[k]) + k++ + + p0 := montReduce(int32(a[i+1]) * int32(b[i+1])) + p0 = montReduce(int32(p0) * zeta) + p0 += montReduce(int32(a[i]) * int32(b[i])) + + p1 := montReduce(int32(a[i]) * int32(b[i+1])) + p1 += montReduce(int32(a[i+1]) * int32(b[i])) + + p[i] = p0 + p[i+1] = p1 + + p2 := montReduce(int32(a[i+3]) * int32(b[i+3])) + p2 = -montReduce(int32(p2) * zeta) + p2 += montReduce(int32(a[i+2]) * int32(b[i+2])) + + p3 := montReduce(int32(a[i+2]) * int32(b[i+3])) + p3 += montReduce(int32(a[i+3]) * int32(b[i+2])) + + p[i+2] = p2 + p[i+3] = p3 + } +} + +// Packs p into buf. buf should be of length PolySize. +// +// Assumes p is normalized (and not just Barrett reduced) and "tangled", +// see Tangle(). +func (p *Poly) Pack(buf []byte) { + q := *p + q.Detangle() + for i := 0; i < 128; i++ { + t0 := q[2*i] + t1 := q[2*i+1] + buf[3*i] = byte(t0) + buf[3*i+1] = byte(t0>>8) | byte(t1<<4) + buf[3*i+2] = byte(t1 >> 4) + } +} + +// Unpacks p from buf. +// +// buf should be of length PolySize. p will be "tangled", see Detangle(). +// +// p will not be normalized; instead 0 ≤ p[i] < 4096. +func (p *Poly) Unpack(buf []byte) { + for i := 0; i < 128; i++ { + p[2*i] = int16(buf[3*i]) | ((int16(buf[3*i+1]) << 8) & 0xfff) + p[2*i+1] = int16(buf[3*i+1]>>4) | (int16(buf[3*i+2]) << 4) + } + p.Tangle() +} + +// Set p to Decompress_q(m, 1). +// +// p will be normalized. m has to be of PlaintextSize. +func (p *Poly) DecompressMessage(m []byte) { + // Decompress_q(x, 1) = ⌈xq/2⌋ = ⌊xq/2+½⌋ = (xq+1) >> 1 and so + // Decompress_q(0, 1) = 0 and Decompress_q(1, 1) = (q+1)/2. + for i := 0; i < 32; i++ { + for j := 0; j < 8; j++ { + bit := (m[i] >> uint(j)) & 1 + + // Set coefficient to either 0 or (q+1)/2 depending on the bit. + p[8*i+j] = -int16(bit) & ((Q + 1) / 2) + } + } +} + +// Writes Compress_q(p, 1) to m. +// +// Assumes p is normalized. m has to be of length at least PlaintextSize. +func (p *Poly) CompressMessageTo(m []byte) { + // Compress_q(x, 1) is 1 on {833, …, 2496} and zero elsewhere. + for i := 0; i < 32; i++ { + m[i] = 0 + for j := 0; j < 8; j++ { + x := 1664 - p[8*i+j] + // With the previous substitution, we want to return 1 if + // and only if x is in {831, …, -832}. + x = (x >> 15) ^ x + // Note (x >> 15)ˣ if x≥0 and -x-1 otherwise. Thus now we want + // to return 1 iff x ≤ 831, ie. x - 832 < 0. + x -= 832 + m[i] |= ((byte(x >> 15)) & 1) << uint(j) + } + } +} + +// Set p to Decompress_q(m, 1). +// +// Assumes d is in {4, 5, 10, 11}. p will be normalized. +func (p *Poly) Decompress(m []byte, d int) { + // Decompress_q(x, d) = ⌈(q/2ᵈ)x⌋ + // = ⌊(q/2ᵈ)x+½⌋ + // = ⌊(qx + 2ᵈ⁻¹)/2ᵈ⌋ + // = (qx + (1<<(d-1))) >> d + switch d { + case 4: + for i := 0; i < N/2; i++ { + p[2*i] = int16(((1 << 3) + + uint32(m[i]&15)*uint32(Q)) >> 4) + p[2*i+1] = int16(((1 << 3) + + uint32(m[i]>>4)*uint32(Q)) >> 4) + } + case 5: + var t [8]uint16 + idx := 0 + for i := 0; i < N/8; i++ { + t[0] = uint16(m[idx]) + t[1] = (uint16(m[idx]) >> 5) | (uint16(m[idx+1] << 3)) + t[2] = uint16(m[idx+1]) >> 2 + t[3] = (uint16(m[idx+1]) >> 7) | (uint16(m[idx+2] << 1)) + t[4] = (uint16(m[idx+2]) >> 4) | (uint16(m[idx+3] << 4)) + t[5] = uint16(m[idx+3]) >> 1 + t[6] = (uint16(m[idx+3]) >> 6) | (uint16(m[idx+4] << 2)) + t[7] = uint16(m[idx+4]) >> 3 + + for j := 0; j < 8; j++ { + p[8*i+j] = int16(((1 << 4) + + uint32(t[j]&((1<<5)-1))*uint32(Q)) >> 5) + } + + idx += 5 + } + + case 10: + var t [4]uint16 + idx := 0 + for i := 0; i < N/4; i++ { + t[0] = uint16(m[idx]) | (uint16(m[idx+1]) << 8) + t[1] = (uint16(m[idx+1]) >> 2) | (uint16(m[idx+2]) << 6) + t[2] = (uint16(m[idx+2]) >> 4) | (uint16(m[idx+3]) << 4) + t[3] = (uint16(m[idx+3]) >> 6) | (uint16(m[idx+4]) << 2) + + for j := 0; j < 4; j++ { + p[4*i+j] = int16(((1 << 9) + + uint32(t[j]&((1<<10)-1))*uint32(Q)) >> 10) + } + + idx += 5 + } + case 11: + var t [8]uint16 + idx := 0 + for i := 0; i < N/8; i++ { + t[0] = uint16(m[idx]) | (uint16(m[idx+1]) << 8) + t[1] = (uint16(m[idx+1]) >> 3) | (uint16(m[idx+2]) << 5) + t[2] = (uint16(m[idx+2]) >> 6) | (uint16(m[idx+3]) << 2) | (uint16(m[idx+4]) << 10) + t[3] = (uint16(m[idx+4]) >> 1) | (uint16(m[idx+5]) << 7) + t[4] = (uint16(m[idx+5]) >> 4) | (uint16(m[idx+6]) << 4) + t[5] = (uint16(m[idx+6]) >> 7) | (uint16(m[idx+7]) << 1) | (uint16(m[idx+8]) << 9) + t[6] = (uint16(m[idx+8]) >> 2) | (uint16(m[idx+9]) << 6) + t[7] = (uint16(m[idx+9]) >> 5) | (uint16(m[idx+10]) << 3) + + for j := 0; j < 8; j++ { + p[8*i+j] = int16(((1 << 10) + + uint32(t[j]&((1<<11)-1))*uint32(Q)) >> 11) + } + + idx += 11 + } + default: + panic("unsupported d") + } +} + +// Writes Compress_q(p, d) to m. +// +// Assumes p is normalized and d is in {4, 5, 10, 11}. +func (p *Poly) CompressTo(m []byte, d int) { + // Compress_q(x, d) = ⌈(2ᵈ/q)x⌋ mod⁺ 2ᵈ + // = ⌊(2ᵈ/q)x+½⌋ mod⁺ 2ᵈ + // = ⌊((x << d) + q/2) / q⌋ mod⁺ 2ᵈ + // = DIV((x << d) + q/2, q) & ((1<>e, where a/(2^e) ≈ 1/q. + // For d in {10,11} we use 20,642,679/2^36, which computes division by x/q + // correctly for 0 ≤ x < 41,522,616, which fits (q << 11) + q/2 comfortably. + // For d in {4,5} we use 315/2^20, which doesn't compute division by x/q + // correctly for all inputs, but it's close enough that the end result + // of the compression is correct. The advantage is that we do not need + // to use a 64-bit intermediate value. + switch d { + case 4: + var t [8]uint16 + idx := 0 + for i := 0; i < N/8; i++ { + for j := 0; j < 8; j++ { + t[j] = uint16((((uint32(p[8*i+j])<<4)+uint32(Q)/2)*315)>> + 20) & ((1 << 4) - 1) + } + m[idx] = byte(t[0]) | byte(t[1]<<4) + m[idx+1] = byte(t[2]) | byte(t[3]<<4) + m[idx+2] = byte(t[4]) | byte(t[5]<<4) + m[idx+3] = byte(t[6]) | byte(t[7]<<4) + idx += 4 + } + + case 5: + var t [8]uint16 + idx := 0 + for i := 0; i < N/8; i++ { + for j := 0; j < 8; j++ { + t[j] = uint16((((uint32(p[8*i+j])<<5)+uint32(Q)/2)*315)>> + 20) & ((1 << 5) - 1) + } + m[idx] = byte(t[0]) | byte(t[1]<<5) + m[idx+1] = byte(t[1]>>3) | byte(t[2]<<2) | byte(t[3]<<7) + m[idx+2] = byte(t[3]>>1) | byte(t[4]<<4) + m[idx+3] = byte(t[4]>>4) | byte(t[5]<<1) | byte(t[6]<<6) + m[idx+4] = byte(t[6]>>2) | byte(t[7]<<3) + idx += 5 + } + + case 10: + var t [4]uint16 + idx := 0 + for i := 0; i < N/4; i++ { + for j := 0; j < 4; j++ { + t[j] = uint16((uint64((uint32(p[4*i+j])<<10)+uint32(Q)/2)* + 20642679)>>36) & ((1 << 10) - 1) + } + m[idx] = byte(t[0]) + m[idx+1] = byte(t[0]>>8) | byte(t[1]<<2) + m[idx+2] = byte(t[1]>>6) | byte(t[2]<<4) + m[idx+3] = byte(t[2]>>4) | byte(t[3]<<6) + m[idx+4] = byte(t[3] >> 2) + idx += 5 + } + case 11: + var t [8]uint16 + idx := 0 + for i := 0; i < N/8; i++ { + for j := 0; j < 8; j++ { + t[j] = uint16((uint64((uint32(p[8*i+j])<<11)+uint32(Q)/2)* + 20642679)>>36) & ((1 << 11) - 1) + } + m[idx] = byte(t[0]) + m[idx+1] = byte(t[0]>>8) | byte(t[1]<<3) + m[idx+2] = byte(t[1]>>5) | byte(t[2]<<6) + m[idx+3] = byte(t[2] >> 2) + m[idx+4] = byte(t[2]>>10) | byte(t[3]<<1) + m[idx+5] = byte(t[3]>>7) | byte(t[4]<<4) + m[idx+6] = byte(t[4]>>4) | byte(t[5]<<7) + m[idx+7] = byte(t[5] >> 1) + m[idx+8] = byte(t[5]>>9) | byte(t[6]<<2) + m[idx+9] = byte(t[6]>>6) | byte(t[7]<<5) + m[idx+10] = byte(t[7] >> 3) + idx += 11 + } + default: + panic("unsupported d") + } +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/sample.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/sample.go new file mode 100644 index 00000000000..ed5a33dd907 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/sample.go @@ -0,0 +1,236 @@ +package common + +import ( + "encoding/binary" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/simd/keccakf1600" +) + +// DeriveX4Available indicates whether the system supports the quick fourway +// sampling variants like PolyDeriveUniformX4. +var DeriveX4Available = keccakf1600.IsEnabledX4() + +// Samples p from a centered binomial distribution with given η. +// +// Essentially CBD_η(PRF(seed, nonce)) from the specification. +func (p *Poly) DeriveNoise(seed []byte, nonce uint8, eta int) { + switch eta { + case 2: + p.DeriveNoise2(seed, nonce) + case 3: + p.DeriveNoise3(seed, nonce) + default: + panic("unsupported eta") + } +} + +// Sample p from a centered binomial distribution with n=6 and p=½ - that is: +// coefficients are in {-3, -2, -1, 0, 1, 2, 3} with probabilities {1/64, 3/32, +// 15/64, 5/16, 16/64, 3/32, 1/64}. +func (p *Poly) DeriveNoise3(seed []byte, nonce uint8) { + keySuffix := [1]byte{nonce} + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Write(keySuffix[:]) + + // The distribution at hand is exactly the same as that + // of (a₁ + a₂ + a₃) - (b₁ + b₂+b₃) where a_i,b_i~U(1). Thus we need + // 6 bits per coefficients, thus 192 bytes of input entropy. + + // We add two extra zero bytes in the buffer to be able to read 8 bytes + // at the same time (while using only 6.) + var buf [192 + 2]byte + _, _ = h.Read(buf[:192]) + + for i := 0; i < 32; i++ { + // t is interpreted as a₁ + 2a₂ + 4a₃ + 8b₁ + 16b₂ + …. + t := binary.LittleEndian.Uint64(buf[6*i:]) + + d := t & 0x249249249249 // a₁ + 8b₁ + … + d += (t >> 1) & 0x249249249249 // a₁ + a₂ + 8(b₁ + b₂) + … + d += (t >> 2) & 0x249249249249 // a₁ + a₂ + a₃ + 4(b₁ + b₂ + b₃) + … + + for j := 0; j < 8; j++ { + a := int16(d) & 0x7 // a₁ + a₂ + a₃ + d >>= 3 + b := int16(d) & 0x7 // b₁ + b₂ + b₃ + d >>= 3 + p[8*i+j] = a - b + } + } +} + +// Sample p from a centered binomial distribution with n=4 and p=½ - that is: +// coefficients are in {-2, -1, 0, 1, 2} with probabilities {1/16, 1/4, +// 3/8, 1/4, 1/16}. +func (p *Poly) DeriveNoise2(seed []byte, nonce uint8) { + keySuffix := [1]byte{nonce} + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Write(keySuffix[:]) + + // The distribution at hand is exactly the same as that + // of (a + a') - (b + b') where a,a',b,b'~U(1). Thus we need 4 bits per + // coefficients, thus 128 bytes of input entropy. + + var buf [128]byte + _, _ = h.Read(buf[:]) + + for i := 0; i < 16; i++ { + // t is interpreted as a + 2a' + 4b + 8b' + …. + t := binary.LittleEndian.Uint64(buf[8*i:]) + + d := t & 0x5555555555555555 // a + 4b + … + d += (t >> 1) & 0x5555555555555555 // a+a' + 4(b + b') + … + + for j := 0; j < 16; j++ { + a := int16(d) & 0x3 + d >>= 2 + b := int16(d) & 0x3 + d >>= 2 + p[16*i+j] = a - b + } + } +} + +// For each i, sample ps[i] uniformly from the given seed for coordinates +// xs[i] and ys[i]. ps[i] may be nil and is ignored in that case. +// +// Can only be called when DeriveX4Available is true. +func PolyDeriveUniformX4(ps [4]*Poly, seed *[32]byte, xs, ys [4]uint8) { + var perm keccakf1600.StateX4 + state := perm.Initialize(false) + + // Absorb the seed in the four states + for i := 0; i < 4; i++ { + v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)]) + for j := 0; j < 4; j++ { + state[i*4+j] = v + } + } + + // Absorb the coordinates, the SHAKE128 domain separator (0b1111), the + // start of the padding (0b…001) and the end of the padding 0b100…. + // Recall that the rate of SHAKE128 is 168; ie. 21 uint64s. + for j := 0; j < 4; j++ { + state[4*4+j] = uint64(xs[j]) | (uint64(ys[j]) << 8) | (0x1f << 16) + state[20*4+j] = 0x80 << 56 + } + + var idx [4]int // indices into ps + for j := 0; j < 4; j++ { + if ps[j] == nil { + idx[j] = N // mark nil polynomials as completed + } + } + + done := false + for !done { + // Applies KeccaK-f[1600] to state to get the next 21 uint64s of each of + // the four SHAKE128 streams. + perm.Permute() + + done = true + + PolyLoop: + for j := 0; j < 4; j++ { + if idx[j] == N { + continue + } + for i := 0; i < 7; i++ { + var t [16]uint16 + + v1 := state[i*3*4+j] + v2 := state[(i*3+1)*4+j] + v3 := state[(i*3+2)*4+j] + + t[0] = uint16(v1) & 0xfff + t[1] = uint16(v1>>12) & 0xfff + t[2] = uint16(v1>>24) & 0xfff + t[3] = uint16(v1>>36) & 0xfff + t[4] = uint16(v1>>48) & 0xfff + t[5] = uint16((v1>>60)|(v2<<4)) & 0xfff + + t[6] = uint16(v2>>8) & 0xfff + t[7] = uint16(v2>>20) & 0xfff + t[8] = uint16(v2>>32) & 0xfff + t[9] = uint16(v2>>44) & 0xfff + t[10] = uint16((v2>>56)|(v3<<8)) & 0xfff + + t[11] = uint16(v3>>4) & 0xfff + t[12] = uint16(v3>>16) & 0xfff + t[13] = uint16(v3>>28) & 0xfff + t[14] = uint16(v3>>40) & 0xfff + t[15] = uint16(v3>>52) & 0xfff + + for k := 0; k < 16; k++ { + if t[k] < uint16(Q) { + ps[j][idx[j]] = int16(t[k]) + idx[j]++ + if idx[j] == N { + continue PolyLoop + } + } + } + } + + done = false + } + } + + for i := 0; i < 4; i++ { + if ps[i] != nil { + ps[i].Tangle() + } + } +} + +// Sample p uniformly from the given seed and x and y coordinates. +// +// Coefficients are reduced and will be in "tangled" order. See Tangle(). +func (p *Poly) DeriveUniform(seed *[32]byte, x, y uint8) { + var seedSuffix [2]byte + var buf [168]byte // rate of SHAKE-128 + + seedSuffix[0] = x + seedSuffix[1] = y + + h := sha3.NewShake128() + _, _ = h.Write(seed[:]) + _, _ = h.Write(seedSuffix[:]) + + i := 0 + for { + _, _ = h.Read(buf[:]) + + for j := 0; j < 168; j += 3 { + t1 := (uint16(buf[j]) | (uint16(buf[j+1]) << 8)) & 0xfff + t2 := (uint16(buf[j+1]>>4) | (uint16(buf[j+2]) << 4)) & 0xfff + + if t1 < uint16(Q) { + p[i] = int16(t1) + i++ + + if i == N { + break + } + } + + if t2 < uint16(Q) { + p[i] = int16(t2) + i++ + + if i == N { + break + } + } + } + + if i == N { + break + } + } + + p.Tangle() +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/stubs_amd64.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/stubs_amd64.go new file mode 100644 index 00000000000..4b4700dfd9d --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/stubs_amd64.go @@ -0,0 +1,32 @@ +// Code generated by command: go run src.go -out ../amd64.s -stubs ../stubs_amd64.go -pkg common. DO NOT EDIT. + +//go:build amd64 && !purego + +package common + +//go:noescape +func addAVX2(p *[256]int16, a *[256]int16, b *[256]int16) + +//go:noescape +func subAVX2(p *[256]int16, a *[256]int16, b *[256]int16) + +//go:noescape +func nttAVX2(p *[256]int16) + +//go:noescape +func invNttAVX2(p *[256]int16) + +//go:noescape +func mulHatAVX2(p *[256]int16, a *[256]int16, b *[256]int16) + +//go:noescape +func detangleAVX2(p *[256]int16) + +//go:noescape +func tangleAVX2(p *[256]int16) + +//go:noescape +func barrettReduceAVX2(p *[256]int16) + +//go:noescape +func normalizeAVX2(p *[256]int16) diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/cpapke.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/cpapke.go new file mode 100644 index 00000000000..bea07e87438 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/cpapke.go @@ -0,0 +1,192 @@ +// Code generated from kyber512/internal/cpapke.go by gen.go + +package internal + +import ( + "bytes" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A Kyber.CPAPKE private key. +type PrivateKey struct { + sh Vec // NTT(s), normalized +} + +// A Kyber.CPAPKE public key. +type PublicKey struct { + rho [32]byte // ρ, the seed for the matrix A + th Vec // NTT(t), normalized + + // cached values + aT Mat // the matrix Aᵀ +} + +// Packs the private key to buf. +func (sk *PrivateKey) Pack(buf []byte) { + sk.sh.Pack(buf) +} + +// Unpacks the private key from buf. +func (sk *PrivateKey) Unpack(buf []byte) { + sk.sh.Unpack(buf) + sk.sh.Normalize() +} + +// Packs the public key to buf. +func (pk *PublicKey) Pack(buf []byte) { + pk.th.Pack(buf) + copy(buf[K*common.PolySize:], pk.rho[:]) +} + +// Unpacks the public key from buf. Checks if the public key is normalized. +func (pk *PublicKey) UnpackMLKEM(buf []byte) error { + pk.Unpack(buf) + + // FIPS 203 §7.2 "encapsulation key check" (2). + var buf2 [K * common.PolySize]byte + pk.th.Pack(buf2[:]) + if !bytes.Equal(buf[:len(buf2)], buf2[:]) { + return kem.ErrPubKey + } + return nil +} + +// Unpacks the public key from buf. +func (pk *PublicKey) Unpack(buf []byte) { + pk.th.Unpack(buf) + pk.th.Normalize() + copy(pk.rho[:], buf[K*common.PolySize:]) + pk.aT.Derive(&pk.rho, true) +} + +// Derives a new Kyber.CPAPKE keypair from the given seed. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + var pk PublicKey + var sk PrivateKey + + var expandedSeed [64]byte + + h := sha3.New512() + _, _ = h.Write(seed) + + // This writes hash into expandedSeed. Yes, this is idiomatic Go. + _, _ = h.Read(expandedSeed[:]) + + copy(pk.rho[:], expandedSeed[:32]) + sigma := expandedSeed[32:] // σ, the noise seed + + pk.aT.Derive(&pk.rho, false) // Expand ρ to matrix A; we'll transpose later + + var eh Vec + sk.sh.DeriveNoise(sigma, 0, Eta1) // Sample secret vector s + sk.sh.NTT() + sk.sh.Normalize() + + eh.DeriveNoise(sigma, K, Eta1) // Sample blind e + eh.NTT() + + // Next, we compute t = A s + e. + for i := 0; i < K; i++ { + // Note that coefficients of s are bounded by q and those of A + // are bounded by 4.5q and so their product is bounded by 2¹⁵q + // as required for multiplication. + PolyDotHat(&pk.th[i], &pk.aT[i], &sk.sh) + + // A and s were not in Montgomery form, so the Montgomery + // multiplications in the inner product added a factor R⁻¹ which + // we'll cancel out now. This will also ensure the coefficients of + // t are bounded in absolute value by q. + pk.th[i].ToMont() + } + + pk.th.Add(&pk.th, &eh) // bounded by 8q. + pk.th.Normalize() + pk.aT.Transpose() + + return &pk, &sk +} + +// Decrypts ciphertext ct meant for private key sk to plaintext pt. +func (sk *PrivateKey) DecryptTo(pt, ct []byte) { + var u Vec + var v, m common.Poly + + u.Decompress(ct, DU) + v.Decompress(ct[K*compressedPolySize(DU):], DV) + + // Compute m = v - + u.NTT() + PolyDotHat(&m, &sk.sh, &u) + m.BarrettReduce() + m.InvNTT() + m.Sub(&v, &m) + m.Normalize() + + // Compress polynomial m to original message + m.CompressMessageTo(pt) +} + +// Encrypts message pt for the public key to ciphertext ct using randomness +// from seed. +// +// seed has to be of length SeedSize, pt of PlaintextSize and ct of +// CiphertextSize. +func (pk *PublicKey) EncryptTo(ct, pt, seed []byte) { + var rh, e1, u Vec + var e2, v, m common.Poly + + // Sample r, e₁ and e₂ from B_η + rh.DeriveNoise(seed, 0, Eta1) + rh.NTT() + rh.BarrettReduce() + + e1.DeriveNoise(seed, K, common.Eta2) + e2.DeriveNoise(seed, 2*K, common.Eta2) + + // Next we compute u = Aᵀ r + e₁. First Aᵀ. + for i := 0; i < K; i++ { + // Note that coefficients of r are bounded by q and those of Aᵀ + // are bounded by 4.5q and so their product is bounded by 2¹⁵q + // as required for multiplication. + PolyDotHat(&u[i], &pk.aT[i], &rh) + } + + u.BarrettReduce() + + // Aᵀ and r were not in Montgomery form, so the Montgomery + // multiplications in the inner product added a factor R⁻¹ which + // the InvNTT cancels out. + u.InvNTT() + + u.Add(&u, &e1) // u = Aᵀ r + e₁ + + // Next compute v = + e₂ + Decompress_q(m, 1). + PolyDotHat(&v, &pk.th, &rh) + v.BarrettReduce() + v.InvNTT() + + m.DecompressMessage(pt) + v.Add(&v, &m) + v.Add(&v, &e2) // v = + e₂ + Decompress_q(m, 1) + + // Pack ciphertext + u.Normalize() + v.Normalize() + + u.CompressTo(ct, DU) + v.CompressTo(ct[K*compressedPolySize(DU):], DV) +} + +// Returns whether sk equals other. +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + ret := int16(0) + for i := 0; i < K; i++ { + for j := 0; j < common.N; j++ { + ret |= sk.sh[i][j] ^ other.sh[i][j] + } + } + return ret == 0 +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/mat.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/mat.go new file mode 100644 index 00000000000..404aacfb024 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/mat.go @@ -0,0 +1,85 @@ +// Code generated from kyber512/internal/mat.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A k by k matrix of polynomials. +type Mat [K]Vec + +// Expands the given seed to the corresponding matrix A or its transpose Aᵀ. +func (m *Mat) Derive(seed *[32]byte, transpose bool) { + if !common.DeriveX4Available { + if transpose { + for i := 0; i < K; i++ { + for j := 0; j < K; j++ { + m[i][j].DeriveUniform(seed, uint8(i), uint8(j)) + } + } + } else { + for i := 0; i < K; i++ { + for j := 0; j < K; j++ { + m[i][j].DeriveUniform(seed, uint8(j), uint8(i)) + } + } + } + return + } + + var ps [4]*common.Poly + var xs [4]uint8 + var ys [4]uint8 + x := uint8(0) + y := uint8(0) + + for x != K { + idx := 0 + for ; idx < 4; idx++ { + ps[idx] = &m[x][y] + + if transpose { + xs[idx] = x + ys[idx] = y + } else { + xs[idx] = y + ys[idx] = x + } + + y++ + if y == K { + x++ + y = 0 + + if x == K { + if idx == 0 { + // If there is just one left, then a plain DeriveUniform + // is quicker than the X4 variant. + ps[0].DeriveUniform(seed, xs[0], ys[0]) + return + } + + for idx++; idx < 4; idx++ { + ps[idx] = nil + } + + break + } + } + } + + common.PolyDeriveUniformX4(ps, seed, xs, ys) + } +} + +// Transposes A in place. +func (m *Mat) Transpose() { + for i := 0; i < K-1; i++ { + for j := i + 1; j < K; j++ { + t := m[i][j] + m[i][j] = m[j][i] + m[j][i] = t + } + } +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/params.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/params.go new file mode 100644 index 00000000000..669b0edaca2 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/params.go @@ -0,0 +1,21 @@ +// Code generated from params.templ.go. DO NOT EDIT. + +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +const ( + K = 4 + Eta1 = 2 + DU = 11 + DV = 5 + PublicKeySize = 32 + K*common.PolySize + + PrivateKeySize = K * common.PolySize + + PlaintextSize = common.PlaintextSize + SeedSize = 32 + CiphertextSize = 1568 +) diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/vec.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/vec.go new file mode 100644 index 00000000000..6681895a72e --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/vec.go @@ -0,0 +1,125 @@ +// Code generated from kyber512/internal/vec.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A vector of K polynomials +type Vec [K]common.Poly + +// Samples v[i] from a centered binomial distribution with given η, +// seed and nonce+i. +// +// Essentially CBD_η(PRF(seed, nonce+i)) from the specification. +func (v *Vec) DeriveNoise(seed []byte, nonce uint8, eta int) { + for i := 0; i < K; i++ { + v[i].DeriveNoise(seed, nonce+uint8(i), eta) + } +} + +// Sets p to the inner product of a and b using "pointwise" multiplication. +// +// See MulHat() and NTT() for a description of the multiplication. +// Assumes a and b are in Montgomery form. p will be in Montgomery form, +// and its coefficients will be bounded in absolute value by 2kq. +// If a and b are not in Montgomery form, then the action is the same +// as "pointwise" multiplication followed by multiplying by R⁻¹, the inverse +// of the Montgomery factor. +func PolyDotHat(p *common.Poly, a, b *Vec) { + var t common.Poly + *p = common.Poly{} // set p to zero + for i := 0; i < K; i++ { + t.MulHat(&a[i], &b[i]) + p.Add(&t, p) + } +} + +// Almost normalizes coefficients in-place. +// +// Ensures each coefficient is in {0, …, q}. +func (v *Vec) BarrettReduce() { + for i := 0; i < K; i++ { + v[i].BarrettReduce() + } +} + +// Normalizes coefficients in-place. +// +// Ensures each coefficient is in {0, …, q-1}. +func (v *Vec) Normalize() { + for i := 0; i < K; i++ { + v[i].Normalize() + } +} + +// Applies in-place inverse NTT(). See Poly.InvNTT() for assumptions. +func (v *Vec) InvNTT() { + for i := 0; i < K; i++ { + v[i].InvNTT() + } +} + +// Applies in-place forward NTT(). See Poly.NTT() for assumptions. +func (v *Vec) NTT() { + for i := 0; i < K; i++ { + v[i].NTT() + } +} + +// Sets v to a + b. +func (v *Vec) Add(a, b *Vec) { + for i := 0; i < K; i++ { + v[i].Add(&a[i], &b[i]) + } +} + +// Packs v into buf, which must be of length K*PolySize. +func (v *Vec) Pack(buf []byte) { + for i := 0; i < K; i++ { + v[i].Pack(buf[common.PolySize*i:]) + } +} + +// Unpacks v from buf which must be of length K*PolySize. +func (v *Vec) Unpack(buf []byte) { + for i := 0; i < K; i++ { + v[i].Unpack(buf[common.PolySize*i:]) + } +} + +// Writes Compress_q(v, d) to m. +// +// Assumes v is normalized and d is in {3, 4, 5, 10, 11}. +func (v *Vec) CompressTo(m []byte, d int) { + size := compressedPolySize(d) + for i := 0; i < K; i++ { + v[i].CompressTo(m[size*i:], d) + } +} + +// Set v to Decompress_q(m, 1). +// +// Assumes d is in {3, 4, 5, 10, 11}. v will be normalized. +func (v *Vec) Decompress(m []byte, d int) { + size := compressedPolySize(d) + for i := 0; i < K; i++ { + v[i].Decompress(m[size*i:], d) + } +} + +// ⌈(256 d)/8⌉ +func compressedPolySize(d int) int { + switch d { + case 4: + return 128 + case 5: + return 160 + case 10: + return 320 + case 11: + return 352 + } + panic("unsupported d") +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/kyber.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/kyber.go new file mode 100644 index 00000000000..86cc6c6dbcd --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/kyber.go @@ -0,0 +1,175 @@ +// Code generated from pkg.templ.go. DO NOT EDIT. + +// kyber1024 implements the IND-CPA-secure Public Key Encryption +// scheme Kyber1024.CPAPKE as submitted to round 3 of the NIST PQC competition +// and described in +// +// https://pq-crystals.org/kyber/data/kyber-specification-round3.pdf +package kyber1024 + +import ( + cryptoRand "crypto/rand" + "io" + + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/pke/kyber/kyber1024/internal" +) + +const ( + // Size of seed for NewKeyFromSeed + KeySeedSize = internal.SeedSize + + // Size of seed for EncryptTo + EncryptionSeedSize = internal.SeedSize + + // Size of a packed PublicKey + PublicKeySize = internal.PublicKeySize + + // Size of a packed PrivateKey + PrivateKeySize = internal.PrivateKeySize + + // Size of a ciphertext + CiphertextSize = internal.CiphertextSize + + // Size of a plaintext + PlaintextSize = internal.PlaintextSize +) + +// PublicKey is the type of Kyber1024.CPAPKE public key +type PublicKey internal.PublicKey + +// PrivateKey is the type of Kyber1024.CPAPKE private key +type PrivateKey internal.PrivateKey + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [KeySeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := internal.NewKeyFromSeed(seed[:]) + return (*PublicKey)(pk), (*PrivateKey)(sk), nil +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +// +// Note: does not include the domain separation of ML-KEM (line 1, algorithm 13 +// of FIPS 203). For that use NewKeyFromSeedMLKEM(). +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + pk, sk := internal.NewKeyFromSeed(seed) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// NewKeyFromSeedMLKEM derives a public/private key pair using the given seed +// using the domain separation of ML-KEM. +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeedMLKEM(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + var seed2 [33]byte + copy(seed2[:32], seed) + seed2[32] = byte(internal.K) + pk, sk := internal.NewKeyFromSeed(seed2[:]) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// EncryptTo encrypts message pt for the public key and writes the ciphertext +// to ct using randomness from seed. +// +// This function panics if the lengths of pt, seed, and ct are not +// PlaintextSize, EncryptionSeedSize, and CiphertextSize respectively. +func (pk *PublicKey) EncryptTo(ct []byte, pt []byte, seed []byte) { + if len(pt) != PlaintextSize { + panic("pt must be of length PlaintextSize") + } + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + if len(seed) != EncryptionSeedSize { + panic("seed must be of length EncryptionSeedSize") + } + (*internal.PublicKey)(pk).EncryptTo(ct, pt, seed) +} + +// DecryptTo decrypts message ct for the private key and writes the +// plaintext to pt. +// +// This function panics if the lengths of ct and pt are not +// CiphertextSize and PlaintextSize respectively. +func (sk *PrivateKey) DecryptTo(pt []byte, ct []byte) { + if len(pt) != PlaintextSize { + panic("pt must be of length PlaintextSize") + } + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + (*internal.PrivateKey)(sk).DecryptTo(pt, ct) +} + +// Packs pk into the given buffer. +// +// Panics if buf is not of length PublicKeySize. +func (pk *PublicKey) Pack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of size PublicKeySize") + } + (*internal.PublicKey)(pk).Pack(buf) +} + +// Packs sk into the given buffer. +// +// Panics if buf is not of length PrivateKeySize. +func (sk *PrivateKey) Pack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of size PrivateKeySize") + } + (*internal.PrivateKey)(sk).Pack(buf) +} + +// Unpacks pk from the given buffer. +// +// Panics if buf is not of length PublicKeySize. +func (pk *PublicKey) Unpack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of size PublicKeySize") + } + (*internal.PublicKey)(pk).Unpack(buf) +} + +// Unpacks pk from the given buffer. +// +// Returns an error if the buffer is not of the right size, or the public +// key is not normalized. +func (pk *PublicKey) UnpackMLKEM(buf []byte) error { + if len(buf) != PublicKeySize { + return kem.ErrPubKeySize + } + return (*internal.PublicKey)(pk).UnpackMLKEM(buf) +} + +// Unpacks sk from the given buffer. +// +// Panics if buf is not of length PrivateKeySize. +func (sk *PrivateKey) Unpack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of size PrivateKeySize") + } + (*internal.PrivateKey)(sk).Unpack(buf) +} + +// Returns whether the two private keys are equal. +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + return (*internal.PrivateKey)(sk).Equal((*internal.PrivateKey)(other)) +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/cpapke.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/cpapke.go new file mode 100644 index 00000000000..be9bd6eafd5 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/cpapke.go @@ -0,0 +1,190 @@ +package internal + +import ( + "bytes" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A Kyber.CPAPKE private key. +type PrivateKey struct { + sh Vec // NTT(s), normalized +} + +// A Kyber.CPAPKE public key. +type PublicKey struct { + rho [32]byte // ρ, the seed for the matrix A + th Vec // NTT(t), normalized + + // cached values + aT Mat // the matrix Aᵀ +} + +// Packs the private key to buf. +func (sk *PrivateKey) Pack(buf []byte) { + sk.sh.Pack(buf) +} + +// Unpacks the private key from buf. +func (sk *PrivateKey) Unpack(buf []byte) { + sk.sh.Unpack(buf) + sk.sh.Normalize() +} + +// Packs the public key to buf. +func (pk *PublicKey) Pack(buf []byte) { + pk.th.Pack(buf) + copy(buf[K*common.PolySize:], pk.rho[:]) +} + +// Unpacks the public key from buf. Checks if the public key is normalized. +func (pk *PublicKey) UnpackMLKEM(buf []byte) error { + pk.Unpack(buf) + + // FIPS 203 §7.2 "encapsulation key check" (2). + var buf2 [K * common.PolySize]byte + pk.th.Pack(buf2[:]) + if !bytes.Equal(buf[:len(buf2)], buf2[:]) { + return kem.ErrPubKey + } + return nil +} + +// Unpacks the public key from buf. +func (pk *PublicKey) Unpack(buf []byte) { + pk.th.Unpack(buf) + pk.th.Normalize() + copy(pk.rho[:], buf[K*common.PolySize:]) + pk.aT.Derive(&pk.rho, true) +} + +// Derives a new Kyber.CPAPKE keypair from the given seed. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + var pk PublicKey + var sk PrivateKey + + var expandedSeed [64]byte + + h := sha3.New512() + _, _ = h.Write(seed) + + // This writes hash into expandedSeed. Yes, this is idiomatic Go. + _, _ = h.Read(expandedSeed[:]) + + copy(pk.rho[:], expandedSeed[:32]) + sigma := expandedSeed[32:] // σ, the noise seed + + pk.aT.Derive(&pk.rho, false) // Expand ρ to matrix A; we'll transpose later + + var eh Vec + sk.sh.DeriveNoise(sigma, 0, Eta1) // Sample secret vector s + sk.sh.NTT() + sk.sh.Normalize() + + eh.DeriveNoise(sigma, K, Eta1) // Sample blind e + eh.NTT() + + // Next, we compute t = A s + e. + for i := 0; i < K; i++ { + // Note that coefficients of s are bounded by q and those of A + // are bounded by 4.5q and so their product is bounded by 2¹⁵q + // as required for multiplication. + PolyDotHat(&pk.th[i], &pk.aT[i], &sk.sh) + + // A and s were not in Montgomery form, so the Montgomery + // multiplications in the inner product added a factor R⁻¹ which + // we'll cancel out now. This will also ensure the coefficients of + // t are bounded in absolute value by q. + pk.th[i].ToMont() + } + + pk.th.Add(&pk.th, &eh) // bounded by 8q. + pk.th.Normalize() + pk.aT.Transpose() + + return &pk, &sk +} + +// Decrypts ciphertext ct meant for private key sk to plaintext pt. +func (sk *PrivateKey) DecryptTo(pt, ct []byte) { + var u Vec + var v, m common.Poly + + u.Decompress(ct, DU) + v.Decompress(ct[K*compressedPolySize(DU):], DV) + + // Compute m = v - + u.NTT() + PolyDotHat(&m, &sk.sh, &u) + m.BarrettReduce() + m.InvNTT() + m.Sub(&v, &m) + m.Normalize() + + // Compress polynomial m to original message + m.CompressMessageTo(pt) +} + +// Encrypts message pt for the public key to ciphertext ct using randomness +// from seed. +// +// seed has to be of length SeedSize, pt of PlaintextSize and ct of +// CiphertextSize. +func (pk *PublicKey) EncryptTo(ct, pt, seed []byte) { + var rh, e1, u Vec + var e2, v, m common.Poly + + // Sample r, e₁ and e₂ from B_η + rh.DeriveNoise(seed, 0, Eta1) + rh.NTT() + rh.BarrettReduce() + + e1.DeriveNoise(seed, K, common.Eta2) + e2.DeriveNoise(seed, 2*K, common.Eta2) + + // Next we compute u = Aᵀ r + e₁. First Aᵀ. + for i := 0; i < K; i++ { + // Note that coefficients of r are bounded by q and those of Aᵀ + // are bounded by 4.5q and so their product is bounded by 2¹⁵q + // as required for multiplication. + PolyDotHat(&u[i], &pk.aT[i], &rh) + } + + u.BarrettReduce() + + // Aᵀ and r were not in Montgomery form, so the Montgomery + // multiplications in the inner product added a factor R⁻¹ which + // the InvNTT cancels out. + u.InvNTT() + + u.Add(&u, &e1) // u = Aᵀ r + e₁ + + // Next compute v = + e₂ + Decompress_q(m, 1). + PolyDotHat(&v, &pk.th, &rh) + v.BarrettReduce() + v.InvNTT() + + m.DecompressMessage(pt) + v.Add(&v, &m) + v.Add(&v, &e2) // v = + e₂ + Decompress_q(m, 1) + + // Pack ciphertext + u.Normalize() + v.Normalize() + + u.CompressTo(ct, DU) + v.CompressTo(ct[K*compressedPolySize(DU):], DV) +} + +// Returns whether sk equals other. +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + ret := int16(0) + for i := 0; i < K; i++ { + for j := 0; j < common.N; j++ { + ret |= sk.sh[i][j] ^ other.sh[i][j] + } + } + return ret == 0 +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/mat.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/mat.go new file mode 100644 index 00000000000..735ecf556c2 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/mat.go @@ -0,0 +1,83 @@ +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A k by k matrix of polynomials. +type Mat [K]Vec + +// Expands the given seed to the corresponding matrix A or its transpose Aᵀ. +func (m *Mat) Derive(seed *[32]byte, transpose bool) { + if !common.DeriveX4Available { + if transpose { + for i := 0; i < K; i++ { + for j := 0; j < K; j++ { + m[i][j].DeriveUniform(seed, uint8(i), uint8(j)) + } + } + } else { + for i := 0; i < K; i++ { + for j := 0; j < K; j++ { + m[i][j].DeriveUniform(seed, uint8(j), uint8(i)) + } + } + } + return + } + + var ps [4]*common.Poly + var xs [4]uint8 + var ys [4]uint8 + x := uint8(0) + y := uint8(0) + + for x != K { + idx := 0 + for ; idx < 4; idx++ { + ps[idx] = &m[x][y] + + if transpose { + xs[idx] = x + ys[idx] = y + } else { + xs[idx] = y + ys[idx] = x + } + + y++ + if y == K { + x++ + y = 0 + + if x == K { + if idx == 0 { + // If there is just one left, then a plain DeriveUniform + // is quicker than the X4 variant. + ps[0].DeriveUniform(seed, xs[0], ys[0]) + return + } + + for idx++; idx < 4; idx++ { + ps[idx] = nil + } + + break + } + } + } + + common.PolyDeriveUniformX4(ps, seed, xs, ys) + } +} + +// Transposes A in place. +func (m *Mat) Transpose() { + for i := 0; i < K-1; i++ { + for j := i + 1; j < K; j++ { + t := m[i][j] + m[i][j] = m[j][i] + m[j][i] = t + } + } +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/params.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/params.go new file mode 100644 index 00000000000..0e6df77b981 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/params.go @@ -0,0 +1,21 @@ +// Code generated from params.templ.go. DO NOT EDIT. + +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +const ( + K = 2 + Eta1 = 3 + DU = 10 + DV = 4 + PublicKeySize = 32 + K*common.PolySize + + PrivateKeySize = K * common.PolySize + + PlaintextSize = common.PlaintextSize + SeedSize = 32 + CiphertextSize = 768 +) diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/vec.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/vec.go new file mode 100644 index 00000000000..222f1ca931f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/vec.go @@ -0,0 +1,123 @@ +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A vector of K polynomials +type Vec [K]common.Poly + +// Samples v[i] from a centered binomial distribution with given η, +// seed and nonce+i. +// +// Essentially CBD_η(PRF(seed, nonce+i)) from the specification. +func (v *Vec) DeriveNoise(seed []byte, nonce uint8, eta int) { + for i := 0; i < K; i++ { + v[i].DeriveNoise(seed, nonce+uint8(i), eta) + } +} + +// Sets p to the inner product of a and b using "pointwise" multiplication. +// +// See MulHat() and NTT() for a description of the multiplication. +// Assumes a and b are in Montgomery form. p will be in Montgomery form, +// and its coefficients will be bounded in absolute value by 2kq. +// If a and b are not in Montgomery form, then the action is the same +// as "pointwise" multiplication followed by multiplying by R⁻¹, the inverse +// of the Montgomery factor. +func PolyDotHat(p *common.Poly, a, b *Vec) { + var t common.Poly + *p = common.Poly{} // set p to zero + for i := 0; i < K; i++ { + t.MulHat(&a[i], &b[i]) + p.Add(&t, p) + } +} + +// Almost normalizes coefficients in-place. +// +// Ensures each coefficient is in {0, …, q}. +func (v *Vec) BarrettReduce() { + for i := 0; i < K; i++ { + v[i].BarrettReduce() + } +} + +// Normalizes coefficients in-place. +// +// Ensures each coefficient is in {0, …, q-1}. +func (v *Vec) Normalize() { + for i := 0; i < K; i++ { + v[i].Normalize() + } +} + +// Applies in-place inverse NTT(). See Poly.InvNTT() for assumptions. +func (v *Vec) InvNTT() { + for i := 0; i < K; i++ { + v[i].InvNTT() + } +} + +// Applies in-place forward NTT(). See Poly.NTT() for assumptions. +func (v *Vec) NTT() { + for i := 0; i < K; i++ { + v[i].NTT() + } +} + +// Sets v to a + b. +func (v *Vec) Add(a, b *Vec) { + for i := 0; i < K; i++ { + v[i].Add(&a[i], &b[i]) + } +} + +// Packs v into buf, which must be of length K*PolySize. +func (v *Vec) Pack(buf []byte) { + for i := 0; i < K; i++ { + v[i].Pack(buf[common.PolySize*i:]) + } +} + +// Unpacks v from buf which must be of length K*PolySize. +func (v *Vec) Unpack(buf []byte) { + for i := 0; i < K; i++ { + v[i].Unpack(buf[common.PolySize*i:]) + } +} + +// Writes Compress_q(v, d) to m. +// +// Assumes v is normalized and d is in {3, 4, 5, 10, 11}. +func (v *Vec) CompressTo(m []byte, d int) { + size := compressedPolySize(d) + for i := 0; i < K; i++ { + v[i].CompressTo(m[size*i:], d) + } +} + +// Set v to Decompress_q(m, 1). +// +// Assumes d is in {3, 4, 5, 10, 11}. v will be normalized. +func (v *Vec) Decompress(m []byte, d int) { + size := compressedPolySize(d) + for i := 0; i < K; i++ { + v[i].Decompress(m[size*i:], d) + } +} + +// ⌈(256 d)/8⌉ +func compressedPolySize(d int) int { + switch d { + case 4: + return 128 + case 5: + return 160 + case 10: + return 320 + case 11: + return 352 + } + panic("unsupported d") +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/kyber.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/kyber.go new file mode 100644 index 00000000000..d4b166a5244 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/kyber.go @@ -0,0 +1,175 @@ +// Code generated from pkg.templ.go. DO NOT EDIT. + +// kyber512 implements the IND-CPA-secure Public Key Encryption +// scheme Kyber512.CPAPKE as submitted to round 3 of the NIST PQC competition +// and described in +// +// https://pq-crystals.org/kyber/data/kyber-specification-round3.pdf +package kyber512 + +import ( + cryptoRand "crypto/rand" + "io" + + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/pke/kyber/kyber512/internal" +) + +const ( + // Size of seed for NewKeyFromSeed + KeySeedSize = internal.SeedSize + + // Size of seed for EncryptTo + EncryptionSeedSize = internal.SeedSize + + // Size of a packed PublicKey + PublicKeySize = internal.PublicKeySize + + // Size of a packed PrivateKey + PrivateKeySize = internal.PrivateKeySize + + // Size of a ciphertext + CiphertextSize = internal.CiphertextSize + + // Size of a plaintext + PlaintextSize = internal.PlaintextSize +) + +// PublicKey is the type of Kyber512.CPAPKE public key +type PublicKey internal.PublicKey + +// PrivateKey is the type of Kyber512.CPAPKE private key +type PrivateKey internal.PrivateKey + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [KeySeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := internal.NewKeyFromSeed(seed[:]) + return (*PublicKey)(pk), (*PrivateKey)(sk), nil +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +// +// Note: does not include the domain separation of ML-KEM (line 1, algorithm 13 +// of FIPS 203). For that use NewKeyFromSeedMLKEM(). +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + pk, sk := internal.NewKeyFromSeed(seed) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// NewKeyFromSeedMLKEM derives a public/private key pair using the given seed +// using the domain separation of ML-KEM. +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeedMLKEM(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + var seed2 [33]byte + copy(seed2[:32], seed) + seed2[32] = byte(internal.K) + pk, sk := internal.NewKeyFromSeed(seed2[:]) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// EncryptTo encrypts message pt for the public key and writes the ciphertext +// to ct using randomness from seed. +// +// This function panics if the lengths of pt, seed, and ct are not +// PlaintextSize, EncryptionSeedSize, and CiphertextSize respectively. +func (pk *PublicKey) EncryptTo(ct []byte, pt []byte, seed []byte) { + if len(pt) != PlaintextSize { + panic("pt must be of length PlaintextSize") + } + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + if len(seed) != EncryptionSeedSize { + panic("seed must be of length EncryptionSeedSize") + } + (*internal.PublicKey)(pk).EncryptTo(ct, pt, seed) +} + +// DecryptTo decrypts message ct for the private key and writes the +// plaintext to pt. +// +// This function panics if the lengths of ct and pt are not +// CiphertextSize and PlaintextSize respectively. +func (sk *PrivateKey) DecryptTo(pt []byte, ct []byte) { + if len(pt) != PlaintextSize { + panic("pt must be of length PlaintextSize") + } + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + (*internal.PrivateKey)(sk).DecryptTo(pt, ct) +} + +// Packs pk into the given buffer. +// +// Panics if buf is not of length PublicKeySize. +func (pk *PublicKey) Pack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of size PublicKeySize") + } + (*internal.PublicKey)(pk).Pack(buf) +} + +// Packs sk into the given buffer. +// +// Panics if buf is not of length PrivateKeySize. +func (sk *PrivateKey) Pack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of size PrivateKeySize") + } + (*internal.PrivateKey)(sk).Pack(buf) +} + +// Unpacks pk from the given buffer. +// +// Panics if buf is not of length PublicKeySize. +func (pk *PublicKey) Unpack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of size PublicKeySize") + } + (*internal.PublicKey)(pk).Unpack(buf) +} + +// Unpacks pk from the given buffer. +// +// Returns an error if the buffer is not of the right size, or the public +// key is not normalized. +func (pk *PublicKey) UnpackMLKEM(buf []byte) error { + if len(buf) != PublicKeySize { + return kem.ErrPubKeySize + } + return (*internal.PublicKey)(pk).UnpackMLKEM(buf) +} + +// Unpacks sk from the given buffer. +// +// Panics if buf is not of length PrivateKeySize. +func (sk *PrivateKey) Unpack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of size PrivateKeySize") + } + (*internal.PrivateKey)(sk).Unpack(buf) +} + +// Returns whether the two private keys are equal. +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + return (*internal.PrivateKey)(sk).Equal((*internal.PrivateKey)(other)) +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/cpapke.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/cpapke.go new file mode 100644 index 00000000000..bea07e87438 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/cpapke.go @@ -0,0 +1,192 @@ +// Code generated from kyber512/internal/cpapke.go by gen.go + +package internal + +import ( + "bytes" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A Kyber.CPAPKE private key. +type PrivateKey struct { + sh Vec // NTT(s), normalized +} + +// A Kyber.CPAPKE public key. +type PublicKey struct { + rho [32]byte // ρ, the seed for the matrix A + th Vec // NTT(t), normalized + + // cached values + aT Mat // the matrix Aᵀ +} + +// Packs the private key to buf. +func (sk *PrivateKey) Pack(buf []byte) { + sk.sh.Pack(buf) +} + +// Unpacks the private key from buf. +func (sk *PrivateKey) Unpack(buf []byte) { + sk.sh.Unpack(buf) + sk.sh.Normalize() +} + +// Packs the public key to buf. +func (pk *PublicKey) Pack(buf []byte) { + pk.th.Pack(buf) + copy(buf[K*common.PolySize:], pk.rho[:]) +} + +// Unpacks the public key from buf. Checks if the public key is normalized. +func (pk *PublicKey) UnpackMLKEM(buf []byte) error { + pk.Unpack(buf) + + // FIPS 203 §7.2 "encapsulation key check" (2). + var buf2 [K * common.PolySize]byte + pk.th.Pack(buf2[:]) + if !bytes.Equal(buf[:len(buf2)], buf2[:]) { + return kem.ErrPubKey + } + return nil +} + +// Unpacks the public key from buf. +func (pk *PublicKey) Unpack(buf []byte) { + pk.th.Unpack(buf) + pk.th.Normalize() + copy(pk.rho[:], buf[K*common.PolySize:]) + pk.aT.Derive(&pk.rho, true) +} + +// Derives a new Kyber.CPAPKE keypair from the given seed. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + var pk PublicKey + var sk PrivateKey + + var expandedSeed [64]byte + + h := sha3.New512() + _, _ = h.Write(seed) + + // This writes hash into expandedSeed. Yes, this is idiomatic Go. + _, _ = h.Read(expandedSeed[:]) + + copy(pk.rho[:], expandedSeed[:32]) + sigma := expandedSeed[32:] // σ, the noise seed + + pk.aT.Derive(&pk.rho, false) // Expand ρ to matrix A; we'll transpose later + + var eh Vec + sk.sh.DeriveNoise(sigma, 0, Eta1) // Sample secret vector s + sk.sh.NTT() + sk.sh.Normalize() + + eh.DeriveNoise(sigma, K, Eta1) // Sample blind e + eh.NTT() + + // Next, we compute t = A s + e. + for i := 0; i < K; i++ { + // Note that coefficients of s are bounded by q and those of A + // are bounded by 4.5q and so their product is bounded by 2¹⁵q + // as required for multiplication. + PolyDotHat(&pk.th[i], &pk.aT[i], &sk.sh) + + // A and s were not in Montgomery form, so the Montgomery + // multiplications in the inner product added a factor R⁻¹ which + // we'll cancel out now. This will also ensure the coefficients of + // t are bounded in absolute value by q. + pk.th[i].ToMont() + } + + pk.th.Add(&pk.th, &eh) // bounded by 8q. + pk.th.Normalize() + pk.aT.Transpose() + + return &pk, &sk +} + +// Decrypts ciphertext ct meant for private key sk to plaintext pt. +func (sk *PrivateKey) DecryptTo(pt, ct []byte) { + var u Vec + var v, m common.Poly + + u.Decompress(ct, DU) + v.Decompress(ct[K*compressedPolySize(DU):], DV) + + // Compute m = v - + u.NTT() + PolyDotHat(&m, &sk.sh, &u) + m.BarrettReduce() + m.InvNTT() + m.Sub(&v, &m) + m.Normalize() + + // Compress polynomial m to original message + m.CompressMessageTo(pt) +} + +// Encrypts message pt for the public key to ciphertext ct using randomness +// from seed. +// +// seed has to be of length SeedSize, pt of PlaintextSize and ct of +// CiphertextSize. +func (pk *PublicKey) EncryptTo(ct, pt, seed []byte) { + var rh, e1, u Vec + var e2, v, m common.Poly + + // Sample r, e₁ and e₂ from B_η + rh.DeriveNoise(seed, 0, Eta1) + rh.NTT() + rh.BarrettReduce() + + e1.DeriveNoise(seed, K, common.Eta2) + e2.DeriveNoise(seed, 2*K, common.Eta2) + + // Next we compute u = Aᵀ r + e₁. First Aᵀ. + for i := 0; i < K; i++ { + // Note that coefficients of r are bounded by q and those of Aᵀ + // are bounded by 4.5q and so their product is bounded by 2¹⁵q + // as required for multiplication. + PolyDotHat(&u[i], &pk.aT[i], &rh) + } + + u.BarrettReduce() + + // Aᵀ and r were not in Montgomery form, so the Montgomery + // multiplications in the inner product added a factor R⁻¹ which + // the InvNTT cancels out. + u.InvNTT() + + u.Add(&u, &e1) // u = Aᵀ r + e₁ + + // Next compute v = + e₂ + Decompress_q(m, 1). + PolyDotHat(&v, &pk.th, &rh) + v.BarrettReduce() + v.InvNTT() + + m.DecompressMessage(pt) + v.Add(&v, &m) + v.Add(&v, &e2) // v = + e₂ + Decompress_q(m, 1) + + // Pack ciphertext + u.Normalize() + v.Normalize() + + u.CompressTo(ct, DU) + v.CompressTo(ct[K*compressedPolySize(DU):], DV) +} + +// Returns whether sk equals other. +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + ret := int16(0) + for i := 0; i < K; i++ { + for j := 0; j < common.N; j++ { + ret |= sk.sh[i][j] ^ other.sh[i][j] + } + } + return ret == 0 +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/mat.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/mat.go new file mode 100644 index 00000000000..404aacfb024 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/mat.go @@ -0,0 +1,85 @@ +// Code generated from kyber512/internal/mat.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A k by k matrix of polynomials. +type Mat [K]Vec + +// Expands the given seed to the corresponding matrix A or its transpose Aᵀ. +func (m *Mat) Derive(seed *[32]byte, transpose bool) { + if !common.DeriveX4Available { + if transpose { + for i := 0; i < K; i++ { + for j := 0; j < K; j++ { + m[i][j].DeriveUniform(seed, uint8(i), uint8(j)) + } + } + } else { + for i := 0; i < K; i++ { + for j := 0; j < K; j++ { + m[i][j].DeriveUniform(seed, uint8(j), uint8(i)) + } + } + } + return + } + + var ps [4]*common.Poly + var xs [4]uint8 + var ys [4]uint8 + x := uint8(0) + y := uint8(0) + + for x != K { + idx := 0 + for ; idx < 4; idx++ { + ps[idx] = &m[x][y] + + if transpose { + xs[idx] = x + ys[idx] = y + } else { + xs[idx] = y + ys[idx] = x + } + + y++ + if y == K { + x++ + y = 0 + + if x == K { + if idx == 0 { + // If there is just one left, then a plain DeriveUniform + // is quicker than the X4 variant. + ps[0].DeriveUniform(seed, xs[0], ys[0]) + return + } + + for idx++; idx < 4; idx++ { + ps[idx] = nil + } + + break + } + } + } + + common.PolyDeriveUniformX4(ps, seed, xs, ys) + } +} + +// Transposes A in place. +func (m *Mat) Transpose() { + for i := 0; i < K-1; i++ { + for j := i + 1; j < K; j++ { + t := m[i][j] + m[i][j] = m[j][i] + m[j][i] = t + } + } +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/params.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/params.go new file mode 100644 index 00000000000..27cdb1abfd8 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/params.go @@ -0,0 +1,21 @@ +// Code generated from params.templ.go. DO NOT EDIT. + +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +const ( + K = 3 + Eta1 = 2 + DU = 10 + DV = 4 + PublicKeySize = 32 + K*common.PolySize + + PrivateKeySize = K * common.PolySize + + PlaintextSize = common.PlaintextSize + SeedSize = 32 + CiphertextSize = 1088 +) diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/vec.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/vec.go new file mode 100644 index 00000000000..6681895a72e --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/vec.go @@ -0,0 +1,125 @@ +// Code generated from kyber512/internal/vec.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/pke/kyber/internal/common" +) + +// A vector of K polynomials +type Vec [K]common.Poly + +// Samples v[i] from a centered binomial distribution with given η, +// seed and nonce+i. +// +// Essentially CBD_η(PRF(seed, nonce+i)) from the specification. +func (v *Vec) DeriveNoise(seed []byte, nonce uint8, eta int) { + for i := 0; i < K; i++ { + v[i].DeriveNoise(seed, nonce+uint8(i), eta) + } +} + +// Sets p to the inner product of a and b using "pointwise" multiplication. +// +// See MulHat() and NTT() for a description of the multiplication. +// Assumes a and b are in Montgomery form. p will be in Montgomery form, +// and its coefficients will be bounded in absolute value by 2kq. +// If a and b are not in Montgomery form, then the action is the same +// as "pointwise" multiplication followed by multiplying by R⁻¹, the inverse +// of the Montgomery factor. +func PolyDotHat(p *common.Poly, a, b *Vec) { + var t common.Poly + *p = common.Poly{} // set p to zero + for i := 0; i < K; i++ { + t.MulHat(&a[i], &b[i]) + p.Add(&t, p) + } +} + +// Almost normalizes coefficients in-place. +// +// Ensures each coefficient is in {0, …, q}. +func (v *Vec) BarrettReduce() { + for i := 0; i < K; i++ { + v[i].BarrettReduce() + } +} + +// Normalizes coefficients in-place. +// +// Ensures each coefficient is in {0, …, q-1}. +func (v *Vec) Normalize() { + for i := 0; i < K; i++ { + v[i].Normalize() + } +} + +// Applies in-place inverse NTT(). See Poly.InvNTT() for assumptions. +func (v *Vec) InvNTT() { + for i := 0; i < K; i++ { + v[i].InvNTT() + } +} + +// Applies in-place forward NTT(). See Poly.NTT() for assumptions. +func (v *Vec) NTT() { + for i := 0; i < K; i++ { + v[i].NTT() + } +} + +// Sets v to a + b. +func (v *Vec) Add(a, b *Vec) { + for i := 0; i < K; i++ { + v[i].Add(&a[i], &b[i]) + } +} + +// Packs v into buf, which must be of length K*PolySize. +func (v *Vec) Pack(buf []byte) { + for i := 0; i < K; i++ { + v[i].Pack(buf[common.PolySize*i:]) + } +} + +// Unpacks v from buf which must be of length K*PolySize. +func (v *Vec) Unpack(buf []byte) { + for i := 0; i < K; i++ { + v[i].Unpack(buf[common.PolySize*i:]) + } +} + +// Writes Compress_q(v, d) to m. +// +// Assumes v is normalized and d is in {3, 4, 5, 10, 11}. +func (v *Vec) CompressTo(m []byte, d int) { + size := compressedPolySize(d) + for i := 0; i < K; i++ { + v[i].CompressTo(m[size*i:], d) + } +} + +// Set v to Decompress_q(m, 1). +// +// Assumes d is in {3, 4, 5, 10, 11}. v will be normalized. +func (v *Vec) Decompress(m []byte, d int) { + size := compressedPolySize(d) + for i := 0; i < K; i++ { + v[i].Decompress(m[size*i:], d) + } +} + +// ⌈(256 d)/8⌉ +func compressedPolySize(d int) int { + switch d { + case 4: + return 128 + case 5: + return 160 + case 10: + return 320 + case 11: + return 352 + } + panic("unsupported d") +} diff --git a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/kyber.go b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/kyber.go new file mode 100644 index 00000000000..75bb7bd34db --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/kyber.go @@ -0,0 +1,175 @@ +// Code generated from pkg.templ.go. DO NOT EDIT. + +// kyber768 implements the IND-CPA-secure Public Key Encryption +// scheme Kyber768.CPAPKE as submitted to round 3 of the NIST PQC competition +// and described in +// +// https://pq-crystals.org/kyber/data/kyber-specification-round3.pdf +package kyber768 + +import ( + cryptoRand "crypto/rand" + "io" + + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/pke/kyber/kyber768/internal" +) + +const ( + // Size of seed for NewKeyFromSeed + KeySeedSize = internal.SeedSize + + // Size of seed for EncryptTo + EncryptionSeedSize = internal.SeedSize + + // Size of a packed PublicKey + PublicKeySize = internal.PublicKeySize + + // Size of a packed PrivateKey + PrivateKeySize = internal.PrivateKeySize + + // Size of a ciphertext + CiphertextSize = internal.CiphertextSize + + // Size of a plaintext + PlaintextSize = internal.PlaintextSize +) + +// PublicKey is the type of Kyber768.CPAPKE public key +type PublicKey internal.PublicKey + +// PrivateKey is the type of Kyber768.CPAPKE private key +type PrivateKey internal.PrivateKey + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [KeySeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := internal.NewKeyFromSeed(seed[:]) + return (*PublicKey)(pk), (*PrivateKey)(sk), nil +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +// +// Note: does not include the domain separation of ML-KEM (line 1, algorithm 13 +// of FIPS 203). For that use NewKeyFromSeedMLKEM(). +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + pk, sk := internal.NewKeyFromSeed(seed) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// NewKeyFromSeedMLKEM derives a public/private key pair using the given seed +// using the domain separation of ML-KEM. +// +// Panics if seed is not of length KeySeedSize. +func NewKeyFromSeedMLKEM(seed []byte) (*PublicKey, *PrivateKey) { + if len(seed) != KeySeedSize { + panic("seed must be of length KeySeedSize") + } + var seed2 [33]byte + copy(seed2[:32], seed) + seed2[32] = byte(internal.K) + pk, sk := internal.NewKeyFromSeed(seed2[:]) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// EncryptTo encrypts message pt for the public key and writes the ciphertext +// to ct using randomness from seed. +// +// This function panics if the lengths of pt, seed, and ct are not +// PlaintextSize, EncryptionSeedSize, and CiphertextSize respectively. +func (pk *PublicKey) EncryptTo(ct []byte, pt []byte, seed []byte) { + if len(pt) != PlaintextSize { + panic("pt must be of length PlaintextSize") + } + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + if len(seed) != EncryptionSeedSize { + panic("seed must be of length EncryptionSeedSize") + } + (*internal.PublicKey)(pk).EncryptTo(ct, pt, seed) +} + +// DecryptTo decrypts message ct for the private key and writes the +// plaintext to pt. +// +// This function panics if the lengths of ct and pt are not +// CiphertextSize and PlaintextSize respectively. +func (sk *PrivateKey) DecryptTo(pt []byte, ct []byte) { + if len(pt) != PlaintextSize { + panic("pt must be of length PlaintextSize") + } + if len(ct) != CiphertextSize { + panic("ct must be of length CiphertextSize") + } + (*internal.PrivateKey)(sk).DecryptTo(pt, ct) +} + +// Packs pk into the given buffer. +// +// Panics if buf is not of length PublicKeySize. +func (pk *PublicKey) Pack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of size PublicKeySize") + } + (*internal.PublicKey)(pk).Pack(buf) +} + +// Packs sk into the given buffer. +// +// Panics if buf is not of length PrivateKeySize. +func (sk *PrivateKey) Pack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of size PrivateKeySize") + } + (*internal.PrivateKey)(sk).Pack(buf) +} + +// Unpacks pk from the given buffer. +// +// Panics if buf is not of length PublicKeySize. +func (pk *PublicKey) Unpack(buf []byte) { + if len(buf) != PublicKeySize { + panic("buf must be of size PublicKeySize") + } + (*internal.PublicKey)(pk).Unpack(buf) +} + +// Unpacks pk from the given buffer. +// +// Returns an error if the buffer is not of the right size, or the public +// key is not normalized. +func (pk *PublicKey) UnpackMLKEM(buf []byte) error { + if len(buf) != PublicKeySize { + return kem.ErrPubKeySize + } + return (*internal.PublicKey)(pk).UnpackMLKEM(buf) +} + +// Unpacks sk from the given buffer. +// +// Panics if buf is not of length PrivateKeySize. +func (sk *PrivateKey) Unpack(buf []byte) { + if len(buf) != PrivateKeySize { + panic("buf must be of size PrivateKeySize") + } + (*internal.PrivateKey)(sk).Unpack(buf) +} + +// Returns whether the two private keys are equal. +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + return (*internal.PrivateKey)(sk).Equal((*internal.PrivateKey)(other)) +} diff --git a/src/vendor/github.com/cloudflare/circl/pki/pki.go b/src/vendor/github.com/cloudflare/circl/pki/pki.go new file mode 100644 index 00000000000..a2edebdb7f7 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pki/pki.go @@ -0,0 +1,182 @@ +package pki + +import ( + "crypto/x509/pkix" + "encoding/asn1" + "encoding/pem" + "errors" + "strings" + + "github.com/cloudflare/circl/sign" + "github.com/cloudflare/circl/sign/schemes" +) + +var ( + allSchemesByOID map[string]sign.Scheme + allSchemesByTLS map[uint]sign.Scheme +) + +type pkixPrivKey struct { + Version int + Algorithm pkix.AlgorithmIdentifier + PrivateKey []byte +} + +func init() { + allSchemesByOID = make(map[string]sign.Scheme) + allSchemesByTLS = make(map[uint]sign.Scheme) + for _, scheme := range schemes.All() { + if cert, ok := scheme.(CertificateScheme); ok { + allSchemesByOID[cert.Oid().String()] = scheme + } + if tlsScheme, ok := scheme.(TLSScheme); ok { + allSchemesByTLS[tlsScheme.TLSIdentifier()] = scheme + } + } +} + +func SchemeByOid(oid asn1.ObjectIdentifier) sign.Scheme { return allSchemesByOID[oid.String()] } + +func SchemeByTLSID(id uint) sign.Scheme { return allSchemesByTLS[id] } + +// Additional methods when the signature scheme is supported in X509. +type CertificateScheme interface { + // Return the appropriate OIDs for this instance. It is implicitly + // assumed that the encoding is simple: e.g. uses the same OID for + // signature and public key like Ed25519. + Oid() asn1.ObjectIdentifier +} + +// Additional methods when the signature scheme is supported in TLS. +type TLSScheme interface { + TLSIdentifier() uint +} + +func UnmarshalPEMPublicKey(data []byte) (sign.PublicKey, error) { + block, rest := pem.Decode(data) + if len(rest) != 0 { + return nil, errors.New("trailing data") + } + if !strings.HasSuffix(block.Type, "PUBLIC KEY") { + return nil, errors.New("pem block type is not public key") + } + + return UnmarshalPKIXPublicKey(block.Bytes) +} + +func UnmarshalPKIXPublicKey(data []byte) (sign.PublicKey, error) { + var pkix struct { + Raw asn1.RawContent + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString + } + if rest, err := asn1.Unmarshal(data, &pkix); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("trailing data") + } + scheme := SchemeByOid(pkix.Algorithm.Algorithm) + if scheme == nil { + return nil, errors.New("unsupported public key algorithm") + } + return scheme.UnmarshalBinaryPublicKey(pkix.PublicKey.RightAlign()) +} + +func UnmarshalPEMPrivateKey(data []byte) (sign.PrivateKey, error) { + block, rest := pem.Decode(data) + if len(rest) != 0 { + return nil, errors.New("trailing") + } + if !strings.HasSuffix(block.Type, "PRIVATE KEY") { + return nil, errors.New("pem block type is not private key") + } + + return UnmarshalPKIXPrivateKey(block.Bytes) +} + +func UnmarshalPKIXPrivateKey(data []byte) (sign.PrivateKey, error) { + var pkix pkixPrivKey + if rest, err := asn1.Unmarshal(data, &pkix); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("trailing data") + } + scheme := SchemeByOid(pkix.Algorithm.Algorithm) + if scheme == nil { + return nil, errors.New("unsupported public key algorithm") + } + var sk []byte + if rest, err := asn1.Unmarshal(pkix.PrivateKey, &sk); err != nil { + return nil, err + } else if len(rest) > 0 { + return nil, errors.New("trailing data") + } + return scheme.UnmarshalBinaryPrivateKey(sk) +} + +func MarshalPEMPublicKey(pk sign.PublicKey) ([]byte, error) { + data, err := MarshalPKIXPublicKey(pk) + if err != nil { + return nil, err + } + str := pem.EncodeToMemory(&pem.Block{ + Type: "PUBLIC KEY", + Bytes: data, + }) + return str, nil +} + +func MarshalPKIXPublicKey(pk sign.PublicKey) ([]byte, error) { + data, err := pk.MarshalBinary() + if err != nil { + return nil, err + } + + scheme := pk.Scheme() + return asn1.Marshal(struct { + pkix.AlgorithmIdentifier + asn1.BitString + }{ + pkix.AlgorithmIdentifier{ + Algorithm: scheme.(CertificateScheme).Oid(), + }, + asn1.BitString{ + Bytes: data, + BitLength: len(data) * 8, + }, + }) +} + +func MarshalPEMPrivateKey(sk sign.PrivateKey) ([]byte, error) { + data, err := MarshalPKIXPrivateKey(sk) + if err != nil { + return nil, err + } + str := pem.EncodeToMemory(&pem.Block{ + Type: sk.Scheme().Name() + " PRIVATE KEY", + Bytes: data, + }, + ) + return str, nil +} + +func MarshalPKIXPrivateKey(sk sign.PrivateKey) ([]byte, error) { + data, err := sk.MarshalBinary() + if err != nil { + return nil, err + } + + data, err = asn1.Marshal(data) + if err != nil { + return nil, err + } + + scheme := sk.Scheme() + return asn1.Marshal(pkixPrivKey{ + 0, + pkix.AlgorithmIdentifier{ + Algorithm: scheme.(CertificateScheme).Oid(), + }, + data, + }) +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/aes.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/aes.go new file mode 100644 index 00000000000..f5de2542507 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/aes.go @@ -0,0 +1,46 @@ +package common + +import ( + "crypto/aes" + "crypto/cipher" + "encoding/binary" +) + +// AES CTR stream used as a replacement for SHAKE in Dilithium[1234]-AES. +type AesStream struct { + c cipher.Block + counter uint64 + nonce uint16 +} + +// Create a new AesStream as a replacement of SHAKE128. (Note that +// not all occurrences of SHAKE are replaced by AES in the AES-variants). +func NewAesStream128(key *[32]byte, nonce uint16) AesStream { + c, _ := aes.NewCipher(key[:]) + return AesStream{c: c, nonce: nonce} +} + +// Create a new AesStream as a replacement of SHAKE256. (Note that +// not all occurrences of SHAKE are replaced by AES in the AES-variants.) +// +// Yes, in an AES mode, Dilithium throws away the last 32 bytes of a seed ... +// See the remark at the end of the caption of Figure 4 in the Round 2 spec. +func NewAesStream256(key *[64]byte, nonce uint16) AesStream { + c, _ := aes.NewCipher(key[:32]) + return AesStream{c: c, nonce: nonce} +} + +// Squeeze some more blocks from the AES CTR stream into buf. +// +// Assumes length of buf is a multiple of 16. +func (s *AesStream) SqueezeInto(buf []byte) { + var tmp [16]byte + binary.LittleEndian.PutUint16(tmp[:], s.nonce) + + for len(buf) != 0 { + binary.BigEndian.PutUint64(tmp[8:], s.counter) + s.counter++ + s.c.Encrypt(buf, tmp[:]) + buf = buf[16:] + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.go new file mode 100644 index 00000000000..11f0e3dcf6b --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.go @@ -0,0 +1,154 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package common + +import ( + "golang.org/x/sys/cpu" +) + +// Execute an in-place forward NTT on as. +// +// Assumes the coefficients are in Montgomery representation and bounded +// by 2*Q. The resulting coefficients are again in Montgomery representation, +// but are only bounded bt 18*Q. +func (p *Poly) NTT() { + if cpu.X86.HasAVX2 { + nttAVX2( + (*[N]uint32)(p), + ) + } else { + p.nttGeneric() + } +} + +// Execute an in-place inverse NTT and multiply by Montgomery factor R +// +// Assumes the coefficients are in Montgomery representation and bounded +// by 2*Q. The resulting coefficients are again in Montgomery representation +// and bounded by 2*Q. +func (p *Poly) InvNTT() { + if cpu.X86.HasAVX2 { + invNttAVX2( + (*[N]uint32)(p), + ) + } else { + p.invNttGeneric() + } +} + +// Sets p to the polynomial whose coefficients are the pointwise multiplication +// of those of a and b. The coefficients of p are bounded by 2q. +// +// Assumes a and b are in Montgomery form and that the pointwise product +// of each coefficient is below 2³² q. +func (p *Poly) MulHat(a, b *Poly) { + if cpu.X86.HasAVX2 { + mulHatAVX2( + (*[N]uint32)(p), + (*[N]uint32)(a), + (*[N]uint32)(b), + ) + } else { + p.mulHatGeneric(a, b) + } +} + +// Sets p to a + b. Does not normalize polynomials. +func (p *Poly) Add(a, b *Poly) { + if cpu.X86.HasAVX2 { + addAVX2( + (*[N]uint32)(p), + (*[N]uint32)(a), + (*[N]uint32)(b), + ) + } else { + p.addGeneric(a, b) + } +} + +// Sets p to a - b. +// +// Warning: assumes coefficients of b are less than 2q. +// Sets p to a + b. Does not normalize polynomials. +func (p *Poly) Sub(a, b *Poly) { + if cpu.X86.HasAVX2 { + subAVX2( + (*[N]uint32)(p), + (*[N]uint32)(a), + (*[N]uint32)(b), + ) + } else { + p.subGeneric(a, b) + } +} + +// Writes p whose coefficients are in [0, 16) to buf, which must be of +// length N/2. +func (p *Poly) PackLe16(buf []byte) { + if cpu.X86.HasAVX2 { + if len(buf) < PolyLe16Size { + panic("buf too small") + } + packLe16AVX2( + (*[N]uint32)(p), + &buf[0], + ) + } else { + p.packLe16Generic(buf) + } +} + +// Reduces each of the coefficients to <2q. +func (p *Poly) ReduceLe2Q() { + if cpu.X86.HasAVX2 { + reduceLe2QAVX2((*[N]uint32)(p)) + } else { + p.reduceLe2QGeneric() + } +} + +// Reduce each of the coefficients to > 23 + x2 := x & 0x7FFFFF // 2²³-1 + return x2 + (x1 << 13) - x1 +} + +// Returns x mod q. +func modQ(x uint32) uint32 { + return le2qModQ(ReduceLe2Q(x)) +} + +// For x R ≤ q 2³², find y ≤ 2q with y = x mod q. +func montReduceLe2Q(x uint64) uint32 { + // Qinv = 4236238847 = -(q⁻¹) mod 2³² + m := (x * Qinv) & 0xffffffff + return uint32((x + m*uint64(Q)) >> 32) +} + +// Returns x mod q for 0 ≤ x < 2q. +func le2qModQ(x uint32) uint32 { + x -= Q + mask := uint32(int32(x) >> 31) // mask is 2³²-1 if x was neg.; 0 otherwise + return x + (mask & Q) +} + +// Splits 0 ≤ a < Q into a0 and a1 with a = a1*2ᴰ + a0 +// and -2ᴰ⁻¹ < a0 < 2ᴰ⁻¹. Returns a0 + Q and a1. +func power2round(a uint32) (a0plusQ, a1 uint32) { + // We effectively compute a0 = a mod± 2ᵈ + // and a1 = (a - a0) / 2ᵈ. + a0 := a & ((1 << D) - 1) // a mod 2ᵈ + + // a0 is one of 0, 1, ..., 2ᵈ⁻¹-1, 2ᵈ⁻¹, 2ᵈ⁻¹+1, ..., 2ᵈ-1 + a0 -= (1 << (D - 1)) + 1 + // now a0 is -2ᵈ⁻¹-1, -2ᵈ⁻¹, ..., -2, -1, 0, ..., 2ᵈ⁻¹-2 + // Next, we add 2ᴰ to those a0 that are negative (seen as int32). + a0 += uint32(int32(a0)>>31) & (1 << D) + // now a0 is 2ᵈ⁻¹-1, 2ᵈ⁻¹, ..., 2ᵈ-2, 2ᵈ-1, 0, ..., 2ᵈ⁻¹-2 + a0 -= (1 << (D - 1)) - 1 + // now a0 id 0, 1, 2, ..., 2ᵈ⁻¹-1, 2ᵈ⁻¹-1, -2ᵈ⁻¹-1, ... + // which is what we want. + a0plusQ = Q + a0 + a1 = (a - a0) >> D + return +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/generic.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/generic.go new file mode 100644 index 00000000000..2736e1617f4 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/generic.go @@ -0,0 +1,81 @@ +//go:build !amd64 || purego +// +build !amd64 purego + +package common + +// Execute an in-place forward NTT on as. +// +// Assumes the coefficients are in Montgomery representation and bounded +// by 2*Q. The resulting coefficients are again in Montgomery representation, +// but are only bounded bt 18*Q. +func (p *Poly) NTT() { + p.nttGeneric() +} + +// Execute an in-place inverse NTT and multiply by Montgomery factor R +// +// Assumes the coefficients are in Montgomery representation and bounded +// by 2*Q. The resulting coefficients are again in Montgomery representation +// and bounded by 2*Q. +func (p *Poly) InvNTT() { + p.invNttGeneric() +} + +// Sets p to the polynomial whose coefficients are the pointwise multiplication +// of those of a and b. The coefficients of p are bounded by 2q. +// +// Assumes a and b are in Montgomery form and that the pointwise product +// of each coefficient is below 2³² q. +func (p *Poly) MulHat(a, b *Poly) { + p.mulHatGeneric(a, b) +} + +// Sets p to a + b. Does not normalize polynomials. +func (p *Poly) Add(a, b *Poly) { + p.addGeneric(a, b) +} + +// Sets p to a - b. +// +// Warning: assumes coefficients of b are less than 2q. +// Sets p to a + b. Does not normalize polynomials. +func (p *Poly) Sub(a, b *Poly) { + p.subGeneric(a, b) +} + +// Writes p whose coefficients are in [0, 16) to buf, which must be of +// length N/2. +func (p *Poly) PackLe16(buf []byte) { + p.packLe16Generic(buf) +} + +// Reduces each of the coefficients to <2q. +func (p *Poly) ReduceLe2Q() { + p.reduceLe2QGeneric() +} + +// Reduce each of the coefficients to 0; l >>= 1 { + // On the n-th iteration of the l-loop, the coefficients start off + // bounded by n*2*Q. + // + // offset effectively loops over the row groups in this column; it + // is the first row in the row group. + for offset := uint(0); offset < N-l; offset += 2 * l { + k++ + zeta := uint64(Zetas[k]) + + // j loops over each butterfly in the row group. + for j := offset; j < offset+l; j++ { + t := montReduceLe2Q(zeta * uint64(p[j+l])) + p[j+l] = p[j] + (2*Q - t) // Cooley--Tukey butterfly + p[j] += t + } + } + } +} + +// Execute an in-place inverse NTT and multiply by Montgomery factor R +// +// Assumes the coefficients are in Montgomery representation and bounded +// by 2*Q. The resulting coefficients are again in Montgomery representation +// and bounded by 2*Q. +func (p *Poly) invNttGeneric() { + k := 0 // Index into InvZetas + + // We basically do the opposite of NTT, but postpone dividing by 2 in the + // inverse of the Cooley--Tukey butterfly and accumulate that to a big + // division by 2⁸ at the end. See comments in the NTT() function. + + for l := uint(1); l < N; l <<= 1 { + // On the n-th iteration of the l-loop, the coefficients start off + // bounded by 2ⁿ⁻¹*2*Q, so by 256*Q on the last. + for offset := uint(0); offset < N-l; offset += 2 * l { + zeta := uint64(InvZetas[k]) + k++ + for j := offset; j < offset+l; j++ { + t := p[j] // Gentleman--Sande butterfly + p[j] = t + p[j+l] + t += 256*Q - p[j+l] + p[j+l] = montReduceLe2Q(zeta * uint64(t)) + } + } + } + + for j := uint(0); j < N; j++ { + // ROver256 = 41978 = (256)⁻¹ R² + p[j] = montReduceLe2Q(ROver256 * uint64(p[j])) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/pack.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/pack.go new file mode 100644 index 00000000000..6c366089c06 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/pack.go @@ -0,0 +1,160 @@ +package common + +// Sets p to the polynomial whose coefficients are less than 1024 encoded +// into buf (which must be of size PolyT1Size). +// +// p will be normalized. +func (p *Poly) UnpackT1(buf []byte) { + j := 0 + for i := 0; i < PolyT1Size; i += 5 { + p[j] = (uint32(buf[i]) | (uint32(buf[i+1]) << 8)) & 0x3ff + p[j+1] = (uint32(buf[i+1]>>2) | (uint32(buf[i+2]) << 6)) & 0x3ff + p[j+2] = (uint32(buf[i+2]>>4) | (uint32(buf[i+3]) << 4)) & 0x3ff + p[j+3] = (uint32(buf[i+3]>>6) | (uint32(buf[i+4]) << 2)) & 0x3ff + j += 4 + } +} + +// Writes p whose coefficients are in (-2ᵈ⁻¹, 2ᵈ⁻¹] into buf which +// has to be of length at least PolyT0Size. +// +// Assumes that the coefficients are not normalized, but lie in the +// range (q-2ᵈ⁻¹, q+2ᵈ⁻¹]. +func (p *Poly) PackT0(buf []byte) { + j := 0 + for i := 0; i < PolyT0Size; i += 13 { + p0 := Q + (1 << (D - 1)) - p[j] + p1 := Q + (1 << (D - 1)) - p[j+1] + p2 := Q + (1 << (D - 1)) - p[j+2] + p3 := Q + (1 << (D - 1)) - p[j+3] + p4 := Q + (1 << (D - 1)) - p[j+4] + p5 := Q + (1 << (D - 1)) - p[j+5] + p6 := Q + (1 << (D - 1)) - p[j+6] + p7 := Q + (1 << (D - 1)) - p[j+7] + + buf[i] = byte(p0 >> 0) + buf[i+1] = byte(p0>>8) | byte(p1<<5) + buf[i+2] = byte(p1 >> 3) + buf[i+3] = byte(p1>>11) | byte(p2<<2) + buf[i+4] = byte(p2>>6) | byte(p3<<7) + buf[i+5] = byte(p3 >> 1) + buf[i+6] = byte(p3>>9) | byte(p4<<4) + buf[i+7] = byte(p4 >> 4) + buf[i+8] = byte(p4>>12) | byte(p5<<1) + buf[i+9] = byte(p5>>7) | byte(p6<<6) + buf[i+10] = byte(p6 >> 2) + buf[i+11] = byte(p6>>10) | byte(p7<<3) + buf[i+12] = byte(p7 >> 5) + j += 8 + } +} + +// Sets p to the polynomial packed into buf by PackT0. +// +// The coefficients of p will not be normalized, but will lie +// in (-2ᵈ⁻¹, 2ᵈ⁻¹]. +func (p *Poly) UnpackT0(buf []byte) { + j := 0 + for i := 0; i < PolyT0Size; i += 13 { + p[j] = Q + (1 << (D - 1)) - ((uint32(buf[i]) | + (uint32(buf[i+1]) << 8)) & 0x1fff) + p[j+1] = Q + (1 << (D - 1)) - (((uint32(buf[i+1]) >> 5) | + (uint32(buf[i+2]) << 3) | + (uint32(buf[i+3]) << 11)) & 0x1fff) + p[j+2] = Q + (1 << (D - 1)) - (((uint32(buf[i+3]) >> 2) | + (uint32(buf[i+4]) << 6)) & 0x1fff) + p[j+3] = Q + (1 << (D - 1)) - (((uint32(buf[i+4]) >> 7) | + (uint32(buf[i+5]) << 1) | + (uint32(buf[i+6]) << 9)) & 0x1fff) + p[j+4] = Q + (1 << (D - 1)) - (((uint32(buf[i+6]) >> 4) | + (uint32(buf[i+7]) << 4) | + (uint32(buf[i+8]) << 12)) & 0x1fff) + p[j+5] = Q + (1 << (D - 1)) - (((uint32(buf[i+8]) >> 1) | + (uint32(buf[i+9]) << 7)) & 0x1fff) + p[j+6] = Q + (1 << (D - 1)) - (((uint32(buf[i+9]) >> 6) | + (uint32(buf[i+10]) << 2) | + (uint32(buf[i+11]) << 10)) & 0x1fff) + p[j+7] = Q + (1 << (D - 1)) - ((uint32(buf[i+11]) >> 3) | + (uint32(buf[i+12]) << 5)) + + j += 8 + } +} + +// Writes p whose coefficients are less than 1024 into buf, which must be +// of size at least PolyT1Size . +// +// Assumes coefficients of p are normalized. +func (p *Poly) PackT1(buf []byte) { + j := 0 + for i := 0; i < PolyT1Size; i += 5 { + buf[i] = byte(p[j]) + buf[i+1] = byte(p[j]>>8) | byte(p[j+1]<<2) + buf[i+2] = byte(p[j+1]>>6) | byte(p[j+2]<<4) + buf[i+3] = byte(p[j+2]>>4) | byte(p[j+3]<<6) + buf[i+4] = byte(p[j+3] >> 2) + j += 4 + } +} + +// Writes p whose coefficients are in [0, 16) to buf, which must be of +// length N/2. +func (p *Poly) packLe16Generic(buf []byte) { + j := 0 + for i := 0; i < PolyLe16Size; i++ { + buf[i] = byte(p[j]) | byte(p[j+1]<<4) + j += 2 + } +} + +// Writes p with 60 non-zero coefficients {-1,1} to buf, which must have +// length 40. +func (p *Poly) PackB60(buf []byte) { + // We start with a mask of the non-zero positions of p (which is 32 bytes) + // and then append 60 packed bits, where a one indicates a negative + // coefficients. + var signs uint64 + mask := uint64(1) + for i := 0; i < 32; i++ { + buf[i] = 0 + for j := 0; j < 8; j++ { + if p[8*i+j] != 0 { + buf[i] |= 1 << uint(j) + if p[8*i+j] == Q-1 { + signs |= mask + } + mask <<= 1 + } + } + } + for i := uint64(0); i < 8; i++ { + buf[i+32] = uint8(signs >> (8 * i)) + } +} + +// UnpackB60 sets p to the polynomial packed into buf with Poly.PackB60(). +// +// Returns whether unpacking was successful. +func (p *Poly) UnpackB60(buf []byte) bool { + *p = Poly{} // zero p + signs := (uint64(buf[32]) | (uint64(buf[33]) << 8) | + (uint64(buf[34]) << 16) | (uint64(buf[35]) << 24) | + (uint64(buf[36]) << 32) | (uint64(buf[37]) << 40) | + (uint64(buf[38]) << 48) | (uint64(buf[39]) << 56)) + if signs>>60 != 0 { + return false // ensure unused bits are zero for strong unforgeability + } + + for i := 0; i < 32; i++ { + for j := 0; j < 8; j++ { + if (buf[i]>>uint(j))&1 == 1 { + p[8*i+j] = 1 + // Note 1 ^ (1 | (Q-1)) = Q-1 and (-1)&x = x + p[8*i+j] ^= uint32(-(signs & 1)) & (1 | (Q - 1)) + signs >>= 1 + } + } + } + + return true +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params.go new file mode 100644 index 00000000000..7713c6da975 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params.go @@ -0,0 +1,18 @@ +package common + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common/params" +) + +const ( + SeedSize = params.SeedSize + N = params.N + Q = params.Q + QBits = params.QBits + Qinv = params.Qinv + ROver256 = params.ROver256 + D = params.D + PolyT1Size = params.PolyT1Size + PolyT0Size = params.PolyT0Size + PolyLe16Size = params.PolyLe16Size +) diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params/params.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params/params.go new file mode 100644 index 00000000000..2df20e3a408 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params/params.go @@ -0,0 +1,25 @@ +package params + +// We put these parameters in a separate package so that the Go code, +// such as ntt_amd64_src.go, that generates assembler can import it. + +const ( + SeedSize = 32 + N = 256 + Q = 8380417 // 2²³ - 2¹³ + 1 + QBits = 23 + Qinv = 4236238847 // = -(q^-1) mod 2³² + ROver256 = 41978 // = (256)⁻¹ R² mod q, where R=2³² + D = 13 + + // Size of T1 packed. (Note that the formula is not valid in general, + // but it is for the parameters used in the modes of Dilithium.) + PolyT1Size = (N * (QBits - D)) / 8 + + // Size of T0 packed. (Note that the formula is not valid in general, + // but it is for the parameters used in the modes of Dilithium.) + PolyT0Size = (N * D) / 8 + + // Size of a packed polynomial whose coefficients are in [0,16). + PolyLe16Size = N / 2 +) diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/poly.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/poly.go new file mode 100644 index 00000000000..7ac8e57da8d --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/poly.go @@ -0,0 +1,101 @@ +package common + +// An element of our base ring R which are polynomials over Z_q modulo +// the equation Xᴺ = -1, where q=2²³ - 2¹³ + 1 and N=256. +// +// Coefficients aren't always reduced. See Normalize(). +type Poly [N]uint32 + +// Reduces each of the coefficients to <2q. +func (p *Poly) reduceLe2QGeneric() { + for i := uint(0); i < N; i++ { + p[i] = ReduceLe2Q(p[i]) + } +} + +// Reduce each of the coefficients to > 31) + // Sets x to {0, 1, ..., (Q-1)/2, (Q-1)/2, ..., 1} + x = int32((Q-1)/2) - x + if uint32(x) >= bound { + return true + } + } + return false +} + +// Splits p into p1 and p0 such that [i]p1 * 2ᴰ + [i]p0 = [i]p +// with -2ᴰ⁻¹ < [i]p0 ≤ 2ᴰ⁻¹. Returns p0 + Q and p1. +// +// Requires the coefficients of p to be normalized. +func (p *Poly) Power2Round(p0PlusQ, p1 *Poly) { + for i := 0; i < N; i++ { + p0PlusQ[i], p1[i] = power2round(p[i]) + } +} + +// Sets p to the polynomial whose coefficients are the pointwise multiplication +// of those of a and b. The coefficients of p are bounded by 2q. +// +// Assumes a and b are in Montgomery form and that the pointwise product +// of each coefficient is below 2³² q. +func (p *Poly) mulHatGeneric(a, b *Poly) { + for i := 0; i < N; i++ { + p[i] = montReduceLe2Q(uint64(a[i]) * uint64(b[i])) + } +} + +// Sets p to 2ᵈ q without reducing. +// +// So it requires the coefficients of p to be less than 2³²⁻ᴰ. +func (p *Poly) mulBy2toDGeneric(q *Poly) { + for i := 0; i < N; i++ { + p[i] = q[i] << D + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/stubs_amd64.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/stubs_amd64.go new file mode 100644 index 00000000000..3afeda4ddbb --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/stubs_amd64.go @@ -0,0 +1,35 @@ +// Code generated by command: go run src.go -out ../amd64.s -stubs ../stubs_amd64.go -pkg common. DO NOT EDIT. + +//go:build amd64 && !purego + +package common + +//go:noescape +func nttAVX2(p *[256]uint32) + +//go:noescape +func invNttAVX2(p *[256]uint32) + +//go:noescape +func mulHatAVX2(p *[256]uint32, a *[256]uint32, b *[256]uint32) + +//go:noescape +func addAVX2(p *[256]uint32, a *[256]uint32, b *[256]uint32) + +//go:noescape +func subAVX2(p *[256]uint32, a *[256]uint32, b *[256]uint32) + +//go:noescape +func packLe16AVX2(p *[256]uint32, buf *byte) + +//go:noescape +func reduceLe2QAVX2(p *[256]uint32) + +//go:noescape +func le2qModQAVX2(p *[256]uint32) + +//go:noescape +func exceedsAVX2(p *[256]uint32, bound uint32) uint8 + +//go:noescape +func mulBy2toDAVX2(p *[256]uint32, q *[256]uint32) diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/dilithium.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/dilithium.go new file mode 100644 index 00000000000..13ac869a5af --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/dilithium.go @@ -0,0 +1,181 @@ +// Code generated from modePkg.templ.go. DO NOT EDIT. + +// mode2 implements the CRYSTALS-Dilithium signature scheme Dilithium2 +// as submitted to round3 of the NIST PQC competition and described in +// +// https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf +package mode2 + +import ( + "crypto" + "errors" + "io" + + "github.com/cloudflare/circl/sign/dilithium/internal/common" + "github.com/cloudflare/circl/sign/dilithium/mode2/internal" +) + +const ( + // Size of seed for NewKeyFromSeed + SeedSize = common.SeedSize + + // Size of a packed PublicKey + PublicKeySize = internal.PublicKeySize + + // Size of a packed PrivateKey + PrivateKeySize = internal.PrivateKeySize + + // Size of a signature + SignatureSize = internal.SignatureSize +) + +// PublicKey is the type of Dilithium2 public key +type PublicKey internal.PublicKey + +// PrivateKey is the type of Dilithium2 private key +type PrivateKey internal.PrivateKey + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + pk, sk, err := internal.GenerateKey(rand) + return (*PublicKey)(pk), (*PrivateKey)(sk), err +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { + pk, sk := internal.NewKeyFromSeed(seed) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// SignTo signs the given message and writes the signature into signature. +// It will panic if signature is not of length at least SignatureSize. +func SignTo(sk *PrivateKey, msg []byte, signature []byte) { + internal.SignTo( + (*internal.PrivateKey)(sk), + msg, + signature, + ) +} + +// Verify checks whether the given signature by pk on msg is valid. +func Verify(pk *PublicKey, msg []byte, signature []byte) bool { + return internal.Verify( + (*internal.PublicKey)(pk), + msg, + signature, + ) +} + +// Sets pk to the public key encoded in buf. +func (pk *PublicKey) Unpack(buf *[PublicKeySize]byte) { + (*internal.PublicKey)(pk).Unpack(buf) +} + +// Sets sk to the private key encoded in buf. +func (sk *PrivateKey) Unpack(buf *[PrivateKeySize]byte) { + (*internal.PrivateKey)(sk).Unpack(buf) +} + +// Packs the public key into buf. +func (pk *PublicKey) Pack(buf *[PublicKeySize]byte) { + (*internal.PublicKey)(pk).Pack(buf) +} + +// Packs the private key into buf. +func (sk *PrivateKey) Pack(buf *[PrivateKeySize]byte) { + (*internal.PrivateKey)(sk).Pack(buf) +} + +// Packs the public key. +func (pk *PublicKey) Bytes() []byte { + var buf [PublicKeySize]byte + pk.Pack(&buf) + return buf[:] +} + +// Packs the private key. +func (sk *PrivateKey) Bytes() []byte { + var buf [PrivateKeySize]byte + sk.Pack(&buf) + return buf[:] +} + +// Packs the public key. +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + return pk.Bytes(), nil +} + +// Packs the private key. +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + return sk.Bytes(), nil +} + +// Unpacks the public key from data. +func (pk *PublicKey) UnmarshalBinary(data []byte) error { + if len(data) != PublicKeySize { + return errors.New("packed public key must be of mode2.PublicKeySize bytes") + } + var buf [PublicKeySize]byte + copy(buf[:], data) + pk.Unpack(&buf) + return nil +} + +// Unpacks the private key from data. +func (sk *PrivateKey) UnmarshalBinary(data []byte) error { + if len(data) != PrivateKeySize { + return errors.New("packed private key must be of mode2.PrivateKeySize bytes") + } + var buf [PrivateKeySize]byte + copy(buf[:], data) + sk.Unpack(&buf) + return nil +} + +// Sign signs the given message. +// +// opts.HashFunc() must return zero, which can be achieved by passing +// crypto.Hash(0) for opts. rand is ignored. Will only return an error +// if opts.HashFunc() is non-zero. +// +// This function is used to make PrivateKey implement the crypto.Signer +// interface. The package-level SignTo function might be more convenient +// to use. +func (sk *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ( + signature []byte, err error) { + var sig [SignatureSize]byte + + if opts.HashFunc() != crypto.Hash(0) { + return nil, errors.New("dilithium: cannot sign hashed message") + } + + SignTo(sk, msg, sig[:]) + return sig[:], nil +} + +// Computes the public key corresponding to this private key. +// +// Returns a *PublicKey. The type crypto.PublicKey is used to make +// PrivateKey implement the crypto.Signer interface. +func (sk *PrivateKey) Public() crypto.PublicKey { + return (*PublicKey)((*internal.PrivateKey)(sk).Public()) +} + +// Equal returns whether the two private keys equal. +func (sk *PrivateKey) Equal(other crypto.PrivateKey) bool { + castOther, ok := other.(*PrivateKey) + if !ok { + return false + } + return (*internal.PrivateKey)(sk).Equal((*internal.PrivateKey)(castOther)) +} + +// Equal returns whether the two public keys equal. +func (pk *PublicKey) Equal(other crypto.PublicKey) bool { + castOther, ok := other.(*PublicKey) + if !ok { + return false + } + return (*internal.PublicKey)(pk).Equal((*internal.PublicKey)(castOther)) +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/dilithium.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/dilithium.go new file mode 100644 index 00000000000..79a17d5047d --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/dilithium.go @@ -0,0 +1,477 @@ +// Code generated from mode3/internal/dilithium.go by gen.go + +package internal + +import ( + cryptoRand "crypto/rand" + "crypto/subtle" + "io" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +const ( + // Size of a packed polynomial of norm ≤η. + // (Note that the formula is not valid in general.) + PolyLeqEtaSize = (common.N * DoubleEtaBits) / 8 + + // β = τη, the maximum size of c s₂. + Beta = Tau * Eta + + // γ₁ range of y + Gamma1 = 1 << Gamma1Bits + + // Size of packed polynomial of norm <γ₁ such as z + PolyLeGamma1Size = (Gamma1Bits + 1) * common.N / 8 + + // α = 2γ₂ parameter for decompose + Alpha = 2 * Gamma2 + + // Size of a packed private key + PrivateKeySize = 32 + 32 + 32 + PolyLeqEtaSize*(L+K) + common.PolyT0Size*K + + // Size of a packed public key + PublicKeySize = 32 + common.PolyT1Size*K + + // Size of a packed signature + SignatureSize = L*PolyLeGamma1Size + Omega + K + 32 + + // Size of packed w₁ + PolyW1Size = (common.N * (common.QBits - Gamma1Bits)) / 8 +) + +// PublicKey is the type of Dilithium public keys. +type PublicKey struct { + rho [32]byte + t1 VecK + + // Cached values + t1p [common.PolyT1Size * K]byte + A *Mat + tr *[32]byte +} + +// PrivateKey is the type of Dilithium private keys. +type PrivateKey struct { + rho [32]byte + key [32]byte + s1 VecL + s2 VecK + t0 VecK + tr [32]byte + + // Cached values + A Mat // ExpandA(ρ) + s1h VecL // NTT(s₁) + s2h VecK // NTT(s₂) + t0h VecK // NTT(t₀) +} + +type unpackedSignature struct { + z VecL + hint VecK + c [32]byte +} + +// Packs the signature into buf. +func (sig *unpackedSignature) Pack(buf []byte) { + copy(buf[:], sig.c[:]) + sig.z.PackLeGamma1(buf[32:]) + sig.hint.PackHint(buf[32+L*PolyLeGamma1Size:]) +} + +// Sets sig to the signature encoded in the buffer. +// +// Returns whether buf contains a properly packed signature. +func (sig *unpackedSignature) Unpack(buf []byte) bool { + if len(buf) < SignatureSize { + return false + } + copy(sig.c[:], buf[:]) + sig.z.UnpackLeGamma1(buf[32:]) + if sig.z.Exceeds(Gamma1 - Beta) { + return false + } + if !sig.hint.UnpackHint(buf[32+L*PolyLeGamma1Size:]) { + return false + } + return true +} + +// Packs the public key into buf. +func (pk *PublicKey) Pack(buf *[PublicKeySize]byte) { + copy(buf[:32], pk.rho[:]) + copy(buf[32:], pk.t1p[:]) +} + +// Sets pk to the public key encoded in buf. +func (pk *PublicKey) Unpack(buf *[PublicKeySize]byte) { + copy(pk.rho[:], buf[:32]) + copy(pk.t1p[:], buf[32:]) + + pk.t1.UnpackT1(pk.t1p[:]) + pk.A = new(Mat) + pk.A.Derive(&pk.rho) + + // tr = CRH(ρ ‖ t1) = CRH(pk) + pk.tr = new([32]byte) + h := sha3.NewShake256() + _, _ = h.Write(buf[:]) + _, _ = h.Read(pk.tr[:]) +} + +// Packs the private key into buf. +func (sk *PrivateKey) Pack(buf *[PrivateKeySize]byte) { + copy(buf[:32], sk.rho[:]) + copy(buf[32:64], sk.key[:]) + copy(buf[64:96], sk.tr[:]) + offset := 96 + sk.s1.PackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * L + sk.s2.PackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * K + sk.t0.PackT0(buf[offset:]) +} + +// Sets sk to the private key encoded in buf. +func (sk *PrivateKey) Unpack(buf *[PrivateKeySize]byte) { + copy(sk.rho[:], buf[:32]) + copy(sk.key[:], buf[32:64]) + copy(sk.tr[:], buf[64:96]) + offset := 96 + sk.s1.UnpackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * L + sk.s2.UnpackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * K + sk.t0.UnpackT0(buf[offset:]) + + // Cached values + sk.A.Derive(&sk.rho) + sk.t0h = sk.t0 + sk.t0h.NTT() + sk.s1h = sk.s1 + sk.s1h.NTT() + sk.s2h = sk.s2 + sk.s2h.NTT() +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [32]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := NewKeyFromSeed(&seed) + return pk, sk, nil +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +func NewKeyFromSeed(seed *[common.SeedSize]byte) (*PublicKey, *PrivateKey) { + var eSeed [128]byte // expanded seed + var pk PublicKey + var sk PrivateKey + var sSeed [64]byte + + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Read(eSeed[:]) + + copy(pk.rho[:], eSeed[:32]) + copy(sSeed[:], eSeed[32:96]) + copy(sk.key[:], eSeed[96:]) + copy(sk.rho[:], pk.rho[:]) + + sk.A.Derive(&pk.rho) + + for i := uint16(0); i < L; i++ { + PolyDeriveUniformLeqEta(&sk.s1[i], &sSeed, i) + } + + for i := uint16(0); i < K; i++ { + PolyDeriveUniformLeqEta(&sk.s2[i], &sSeed, i+L) + } + + sk.s1h = sk.s1 + sk.s1h.NTT() + sk.s2h = sk.s2 + sk.s2h.NTT() + + sk.computeT0andT1(&sk.t0, &pk.t1) + + sk.t0h = sk.t0 + sk.t0h.NTT() + + // Complete public key far enough to be packed + pk.t1.PackT1(pk.t1p[:]) + pk.A = &sk.A + + // Finish private key + var packedPk [PublicKeySize]byte + pk.Pack(&packedPk) + + // tr = CRH(ρ ‖ t1) = CRH(pk) + h.Reset() + _, _ = h.Write(packedPk[:]) + _, _ = h.Read(sk.tr[:]) + + // Finish cache of public key + pk.tr = &sk.tr + + return &pk, &sk +} + +// Computes t0 and t1 from sk.s1h, sk.s2 and sk.A. +func (sk *PrivateKey) computeT0andT1(t0, t1 *VecK) { + var t VecK + + // Set t to A s₁ + s₂ + for i := 0; i < K; i++ { + PolyDotHat(&t[i], &sk.A[i], &sk.s1h) + t[i].ReduceLe2Q() + t[i].InvNTT() + } + t.Add(&t, &sk.s2) + t.Normalize() + + // Compute t₀, t₁ = Power2Round(t) + t.Power2Round(t0, t1) +} + +// Verify checks whether the given signature by pk on msg is valid. +func Verify(pk *PublicKey, msg []byte, signature []byte) bool { + var sig unpackedSignature + var mu [64]byte + var zh VecL + var Az, Az2dct1, w1 VecK + var ch common.Poly + var cp [32]byte + var w1Packed [PolyW1Size * K]byte + + // Note that Unpack() checked whether ‖z‖_∞ < γ₁ - β + // and ensured that there at most ω ones in pk.hint. + if !sig.Unpack(signature) { + return false + } + + // μ = CRH(tr ‖ msg) + h := sha3.NewShake256() + _, _ = h.Write(pk.tr[:]) + _, _ = h.Write(msg) + _, _ = h.Read(mu[:]) + + // Compute Az + zh = sig.z + zh.NTT() + + for i := 0; i < K; i++ { + PolyDotHat(&Az[i], &pk.A[i], &zh) + } + + // Next, we compute Az - 2ᵈ·c·t₁. + // Note that the coefficients of t₁ are bounded by 256 = 2⁹, + // so the coefficients of Az2dct1 will bounded by 2⁹⁺ᵈ = 2²³ < 2q, + // which is small enough for NTT(). + Az2dct1.MulBy2toD(&pk.t1) + Az2dct1.NTT() + PolyDeriveUniformBall(&ch, &sig.c) + ch.NTT() + for i := 0; i < K; i++ { + Az2dct1[i].MulHat(&Az2dct1[i], &ch) + } + Az2dct1.Sub(&Az, &Az2dct1) + Az2dct1.ReduceLe2Q() + Az2dct1.InvNTT() + Az2dct1.NormalizeAssumingLe2Q() + + // UseHint(pk.hint, Az - 2ᵈ·c·t₁) + // = UseHint(pk.hint, w - c·s₂ + c·t₀) + // = UseHint(pk.hint, r + c·t₀) + // = r₁ = w₁. + w1.UseHint(&Az2dct1, &sig.hint) + w1.PackW1(w1Packed[:]) + + // c' = H(μ, w₁) + h.Reset() + _, _ = h.Write(mu[:]) + _, _ = h.Write(w1Packed[:]) + _, _ = h.Read(cp[:]) + + return sig.c == cp +} + +// SignTo signs the given message and writes the signature into signature. +// +//nolint:funlen +func SignTo(sk *PrivateKey, msg []byte, signature []byte) { + var mu, rhop [64]byte + var w1Packed [PolyW1Size * K]byte + var y, yh VecL + var w, w0, w1, w0mcs2, ct0, w0mcs2pct0 VecK + var ch common.Poly + var yNonce uint16 + var sig unpackedSignature + + if len(signature) < SignatureSize { + panic("Signature does not fit in that byteslice") + } + + // μ = CRH(tr ‖ msg) + h := sha3.NewShake256() + _, _ = h.Write(sk.tr[:]) + _, _ = h.Write(msg) + _, _ = h.Read(mu[:]) + + // ρ' = CRH(key ‖ μ) + h.Reset() + _, _ = h.Write(sk.key[:]) + _, _ = h.Write(mu[:]) + _, _ = h.Read(rhop[:]) + + // Main rejection loop + attempt := 0 + for { + attempt++ + if attempt >= 576 { + // Depending on the mode, one try has a chance between 1/7 and 1/4 + // of succeeding. Thus it is safe to say that 576 iterations + // are enough as (6/7)⁵⁷⁶ < 2⁻¹²⁸. + panic("This should only happen 1 in 2^{128}: something is wrong.") + } + + // y = ExpandMask(ρ', key) + VecLDeriveUniformLeGamma1(&y, &rhop, yNonce) + yNonce += uint16(L) + + // Set w to A y + yh = y + yh.NTT() + for i := 0; i < K; i++ { + PolyDotHat(&w[i], &sk.A[i], &yh) + w[i].ReduceLe2Q() + w[i].InvNTT() + } + + // Decompose w into w₀ and w₁ + w.NormalizeAssumingLe2Q() + w.Decompose(&w0, &w1) + + // c~ = H(μ ‖ w₁) + w1.PackW1(w1Packed[:]) + h.Reset() + _, _ = h.Write(mu[:]) + _, _ = h.Write(w1Packed[:]) + _, _ = h.Read(sig.c[:]) + + PolyDeriveUniformBall(&ch, &sig.c) + ch.NTT() + + // Ensure ‖ w₀ - c·s2 ‖_∞ < γ₂ - β. + // + // By Lemma 3 of the specification this is equivalent to checking that + // both ‖ r₀ ‖_∞ < γ₂ - β and r₁ = w₁, for the decomposition + // w - c·s₂ = r₁ α + r₀ as computed by decompose(). + // See also §4.1 of the specification. + for i := 0; i < K; i++ { + w0mcs2[i].MulHat(&ch, &sk.s2h[i]) + w0mcs2[i].InvNTT() + } + w0mcs2.Sub(&w0, &w0mcs2) + w0mcs2.Normalize() + + if w0mcs2.Exceeds(Gamma2 - Beta) { + continue + } + + // z = y + c·s₁ + for i := 0; i < L; i++ { + sig.z[i].MulHat(&ch, &sk.s1h[i]) + sig.z[i].InvNTT() + } + sig.z.Add(&sig.z, &y) + sig.z.Normalize() + + // Ensure ‖z‖_∞ < γ₁ - β + if sig.z.Exceeds(Gamma1 - Beta) { + continue + } + + // Compute c·t₀ + for i := 0; i < K; i++ { + ct0[i].MulHat(&ch, &sk.t0h[i]) + ct0[i].InvNTT() + } + ct0.NormalizeAssumingLe2Q() + + // Ensure ‖c·t₀‖_∞ < γ₂. + if ct0.Exceeds(Gamma2) { + continue + } + + // Create the hint to be able to reconstruct w₁ from w - c·s₂ + c·t0. + // Note that we're not using makeHint() in the obvious way as we + // do not know whether ‖ sc·s₂ - c·t₀ ‖_∞ < γ₂. Instead we note + // that our makeHint() is actually the same as a makeHint for a + // different decomposition: + // + // Earlier we ensured indirectly with a check that r₁ = w₁ where + // r = w - c·s₂. Hence r₀ = r - r₁ α = w - c·s₂ - w₁ α = w₀ - c·s₂. + // Thus MakeHint(w₀ - c·s₂ + c·t₀, w₁) = MakeHint(r0 + c·t₀, r₁) + // and UseHint(w - c·s₂ + c·t₀, w₁) = UseHint(r + c·t₀, r₁). + // As we just ensured that ‖ c·t₀ ‖_∞ < γ₂ our usage is correct. + w0mcs2pct0.Add(&w0mcs2, &ct0) + w0mcs2pct0.NormalizeAssumingLe2Q() + hintPop := sig.hint.MakeHint(&w0mcs2pct0, &w1) + if hintPop > Omega { + continue + } + + break + } + + sig.Pack(signature[:]) +} + +// Computes the public key corresponding to this private key. +func (sk *PrivateKey) Public() *PublicKey { + var t0 VecK + pk := &PublicKey{ + rho: sk.rho, + A: &sk.A, + tr: &sk.tr, + } + sk.computeT0andT1(&t0, &pk.t1) + pk.t1.PackT1(pk.t1p[:]) + return pk +} + +// Equal returns whether the two public keys are equal +func (pk *PublicKey) Equal(other *PublicKey) bool { + return pk.rho == other.rho && pk.t1 == other.t1 +} + +// Equal returns whether the two private keys are equal +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + ret := (subtle.ConstantTimeCompare(sk.rho[:], other.rho[:]) & + subtle.ConstantTimeCompare(sk.key[:], other.key[:]) & + subtle.ConstantTimeCompare(sk.tr[:], other.tr[:])) + + acc := uint32(0) + for i := 0; i < L; i++ { + for j := 0; j < common.N; j++ { + acc |= sk.s1[i][j] ^ other.s1[i][j] + } + } + for i := 0; i < K; i++ { + for j := 0; j < common.N; j++ { + acc |= sk.s2[i][j] ^ other.s2[i][j] + acc |= sk.t0[i][j] ^ other.t0[i][j] + } + } + return (ret & subtle.ConstantTimeEq(int32(acc), 0)) == 1 +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/mat.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/mat.go new file mode 100644 index 00000000000..cb473c14924 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/mat.go @@ -0,0 +1,59 @@ +// Code generated from mode3/internal/mat.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// A k by l matrix of polynomials. +type Mat [K]VecL + +// Expands the given seed to a complete matrix. +// +// This function is called ExpandA in the specification. +func (m *Mat) Derive(seed *[32]byte) { + if !DeriveX4Available { + for i := uint16(0); i < K; i++ { + for j := uint16(0); j < L; j++ { + PolyDeriveUniform(&m[i][j], seed, (i<<8)+j) + } + } + return + } + + idx := 0 + var nonces [4]uint16 + var ps [4]*common.Poly + for i := uint16(0); i < K; i++ { + for j := uint16(0); j < L; j++ { + nonces[idx] = (i << 8) + j + ps[idx] = &m[i][j] + idx++ + if idx == 4 { + idx = 0 + PolyDeriveUniformX4(ps, seed, nonces) + } + } + } + if idx != 0 { + for i := idx; i < 4; i++ { + ps[i] = nil + } + PolyDeriveUniformX4(ps, seed, nonces) + } +} + +// Set p to the inner product of a and b using pointwise multiplication. +// +// Assumes a and b are in Montgomery form and their coefficients are +// pairwise sufficiently small to multiply, see Poly.MulHat(). Resulting +// coefficients are bounded by 2Lq. +func PolyDotHat(p *common.Poly, a, b *VecL) { + var t common.Poly + *p = common.Poly{} // zero p + for i := 0; i < L; i++ { + t.MulHat(&a[i], &b[i]) + p.Add(&t, p) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/pack.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/pack.go new file mode 100644 index 00000000000..0285dfd8e5f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/pack.go @@ -0,0 +1,270 @@ +// Code generated from mode3/internal/pack.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// Writes p with norm less than or equal η into buf, which must be of +// size PolyLeqEtaSize. +// +// Assumes coefficients of p are not normalized, but in [q-η,q+η]. +func PolyPackLeqEta(p *common.Poly, buf []byte) { + if DoubleEtaBits == 4 { // compiler eliminates branch + j := 0 + for i := 0; i < PolyLeqEtaSize; i++ { + buf[i] = (byte(common.Q+Eta-p[j]) | + byte(common.Q+Eta-p[j+1])<<4) + j += 2 + } + } else if DoubleEtaBits == 3 { + j := 0 + for i := 0; i < PolyLeqEtaSize; i += 3 { + buf[i] = (byte(common.Q+Eta-p[j]) | + (byte(common.Q+Eta-p[j+1]) << 3) | + (byte(common.Q+Eta-p[j+2]) << 6)) + buf[i+1] = ((byte(common.Q+Eta-p[j+2]) >> 2) | + (byte(common.Q+Eta-p[j+3]) << 1) | + (byte(common.Q+Eta-p[j+4]) << 4) | + (byte(common.Q+Eta-p[j+5]) << 7)) + buf[i+2] = ((byte(common.Q+Eta-p[j+5]) >> 1) | + (byte(common.Q+Eta-p[j+6]) << 2) | + (byte(common.Q+Eta-p[j+7]) << 5)) + j += 8 + } + } else { + panic("eta not supported") + } +} + +// Sets p to the polynomial of norm less than or equal η encoded in the +// given buffer of size PolyLeqEtaSize. +// +// Output coefficients of p are not normalized, but in [q-η,q+η] provided +// buf was created using PackLeqEta. +// +// Beware, for arbitrary buf the coefficients of p might end up in +// the interval [q-2^b,q+2^b] where b is the least b with η≤2^b. +func PolyUnpackLeqEta(p *common.Poly, buf []byte) { + if DoubleEtaBits == 4 { // compiler eliminates branch + j := 0 + for i := 0; i < PolyLeqEtaSize; i++ { + p[j] = common.Q + Eta - uint32(buf[i]&15) + p[j+1] = common.Q + Eta - uint32(buf[i]>>4) + j += 2 + } + } else if DoubleEtaBits == 3 { + j := 0 + for i := 0; i < PolyLeqEtaSize; i += 3 { + p[j] = common.Q + Eta - uint32(buf[i]&7) + p[j+1] = common.Q + Eta - uint32((buf[i]>>3)&7) + p[j+2] = common.Q + Eta - uint32((buf[i]>>6)|((buf[i+1]<<2)&7)) + p[j+3] = common.Q + Eta - uint32((buf[i+1]>>1)&7) + p[j+4] = common.Q + Eta - uint32((buf[i+1]>>4)&7) + p[j+5] = common.Q + Eta - uint32((buf[i+1]>>7)|((buf[i+2]<<1)&7)) + p[j+6] = common.Q + Eta - uint32((buf[i+2]>>2)&7) + p[j+7] = common.Q + Eta - uint32((buf[i+2]>>5)&7) + j += 8 + } + } else { + panic("eta not supported") + } +} + +// Writes v with coefficients in {0, 1} of which at most ω non-zero +// to buf, which must have length ω+k. +func (v *VecK) PackHint(buf []byte) { + // The packed hint starts with the indices of the non-zero coefficients + // For instance: + // + // (x⁵⁶ + x¹⁰⁰, x²⁵⁵, 0, x² + x²³, x¹) + // + // Yields + // + // 56, 100, 255, 2, 23, 1 + // + // Then we pad with zeroes until we have a list of ω items: + // // 56, 100, 255, 2, 23, 1, 0, 0, ..., 0 + // + // Then we finish with a list of the switch-over-indices in this + // list between polynomials, so: + // + // 56, 100, 255, 2, 23, 1, 0, 0, ..., 0, 2, 3, 3, 5, 6 + + off := uint8(0) + for i := 0; i < K; i++ { + for j := uint16(0); j < common.N; j++ { + if v[i][j] != 0 { + buf[off] = uint8(j) + off++ + } + } + buf[Omega+i] = off + } + for ; off < Omega; off++ { + buf[off] = 0 + } +} + +// Sets v to the vector encoded using VecK.PackHint() +// +// Returns whether unpacking was successful. +func (v *VecK) UnpackHint(buf []byte) bool { + // A priori, there would be several reasonable ways to encode the same + // hint vector. We take care to only allow only one encoding, to ensure + // "strong unforgeability". + // + // See PackHint() source for description of the encoding. + *v = VecK{} // zero v + prevSOP := uint8(0) // previous switch-over-point + for i := 0; i < K; i++ { + SOP := buf[Omega+i] + if SOP < prevSOP || SOP > Omega { + return false // ensures switch-over-points are increasing + } + for j := prevSOP; j < SOP; j++ { + if j > prevSOP && buf[j] <= buf[j-1] { + return false // ensures indices are increasing (within a poly) + } + v[i][buf[j]] = 1 + } + prevSOP = SOP + } + for j := prevSOP; j < Omega; j++ { + if buf[j] != 0 { + return false // ensures padding indices are zero + } + } + + return true +} + +// Sets p to the polynomial packed into buf by PolyPackLeGamma1. +// +// p will be normalized. +func PolyUnpackLeGamma1(p *common.Poly, buf []byte) { + if Gamma1Bits == 17 { + j := 0 + for i := 0; i < PolyLeGamma1Size; i += 9 { + p0 := uint32(buf[i]) | (uint32(buf[i+1]) << 8) | + (uint32(buf[i+2]&0x3) << 16) + p1 := uint32(buf[i+2]>>2) | (uint32(buf[i+3]) << 6) | + (uint32(buf[i+4]&0xf) << 14) + p2 := uint32(buf[i+4]>>4) | (uint32(buf[i+5]) << 4) | + (uint32(buf[i+6]&0x3f) << 12) + p3 := uint32(buf[i+6]>>6) | (uint32(buf[i+7]) << 2) | + (uint32(buf[i+8]) << 10) + + // coefficients in [0,…,2γ₁) + p0 = Gamma1 - p0 // (-γ₁,…,γ₁] + p1 = Gamma1 - p1 + p2 = Gamma1 - p2 + p3 = Gamma1 - p3 + + p0 += uint32(int32(p0)>>31) & common.Q // normalize + p1 += uint32(int32(p1)>>31) & common.Q + p2 += uint32(int32(p2)>>31) & common.Q + p3 += uint32(int32(p3)>>31) & common.Q + + p[j] = p0 + p[j+1] = p1 + p[j+2] = p2 + p[j+3] = p3 + + j += 4 + } + } else if Gamma1Bits == 19 { + j := 0 + for i := 0; i < PolyLeGamma1Size; i += 5 { + p0 := uint32(buf[i]) | (uint32(buf[i+1]) << 8) | + (uint32(buf[i+2]&0xf) << 16) + p1 := uint32(buf[i+2]>>4) | (uint32(buf[i+3]) << 4) | + (uint32(buf[i+4]) << 12) + + p0 = Gamma1 - p0 + p1 = Gamma1 - p1 + + p0 += uint32(int32(p0)>>31) & common.Q + p1 += uint32(int32(p1)>>31) & common.Q + + p[j] = p0 + p[j+1] = p1 + + j += 2 + } + } else { + panic("γ₁ not supported") + } +} + +// Writes p whose coefficients are in (-γ₁,γ₁] into buf +// which has to be of length PolyLeGamma1Size. +// +// Assumes p is normalized. +func PolyPackLeGamma1(p *common.Poly, buf []byte) { + if Gamma1Bits == 17 { + j := 0 + // coefficients in [0,…,γ₁] ∪ (q-γ₁,…,q) + for i := 0; i < PolyLeGamma1Size; i += 9 { + p0 := Gamma1 - p[j] // [0,…,γ₁] ∪ (γ₁-q,…,2γ₁-q) + p0 += uint32(int32(p0)>>31) & common.Q // [0,…,2γ₁) + p1 := Gamma1 - p[j+1] + p1 += uint32(int32(p1)>>31) & common.Q + p2 := Gamma1 - p[j+2] + p2 += uint32(int32(p2)>>31) & common.Q + p3 := Gamma1 - p[j+3] + p3 += uint32(int32(p3)>>31) & common.Q + + buf[i+0] = byte(p0) + buf[i+1] = byte(p0 >> 8) + buf[i+2] = byte(p0>>16) | byte(p1<<2) + buf[i+3] = byte(p1 >> 6) + buf[i+4] = byte(p1>>14) | byte(p2<<4) + buf[i+5] = byte(p2 >> 4) + buf[i+6] = byte(p2>>12) | byte(p3<<6) + buf[i+7] = byte(p3 >> 2) + buf[i+8] = byte(p3 >> 10) + + j += 4 + } + } else if Gamma1Bits == 19 { + j := 0 + for i := 0; i < PolyLeGamma1Size; i += 5 { + // Coefficients are in [0, γ₁] ∪ (Q-γ₁, Q) + p0 := Gamma1 - p[j] + p0 += uint32(int32(p0)>>31) & common.Q + p1 := Gamma1 - p[j+1] + p1 += uint32(int32(p1)>>31) & common.Q + + buf[i+0] = byte(p0) + buf[i+1] = byte(p0 >> 8) + buf[i+2] = byte(p0>>16) | byte(p1<<4) + buf[i+3] = byte(p1 >> 4) + buf[i+4] = byte(p1 >> 12) + + j += 2 + } + } else { + panic("γ₁ not supported") + } +} + +// Pack w₁ into buf, which must be of length PolyW1Size. +// +// Assumes w₁ is normalized. +func PolyPackW1(p *common.Poly, buf []byte) { + if Gamma1Bits == 19 { + p.PackLe16(buf) + } else if Gamma1Bits == 17 { + j := 0 + for i := 0; i < PolyW1Size; i += 3 { + buf[i] = byte(p[j]) | byte(p[j+1]<<6) + buf[i+1] = byte(p[j+1]>>2) | byte(p[j+2]<<4) + buf[i+2] = byte(p[j+2]>>4) | byte(p[j+3]<<2) + j += 4 + } + } else { + panic("unsupported γ₁") + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/params.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/params.go new file mode 100644 index 00000000000..b49db55b38a --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/params.go @@ -0,0 +1,16 @@ +// Code generated from params.templ.go. DO NOT EDIT. + +package internal + +const ( + Name = "Dilithium2" + UseAES = false + K = 4 + L = 4 + Eta = 2 + DoubleEtaBits = 3 + Omega = 80 + Tau = 39 + Gamma1Bits = 17 + Gamma2 = 95232 +) diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/rounding.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/rounding.go new file mode 100644 index 00000000000..71360cb2996 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/rounding.go @@ -0,0 +1,142 @@ +// Code generated from mode3/internal/rounding.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// Splits 0 ≤ a < q into a₀ and a₁ with a = a₁*α + a₀ with -α/2 < a₀ ≤ α/2, +// except for when we would have a₁ = (q-1)/α in which case a₁=0 is taken +// and -α/2 ≤ a₀ < 0. Returns a₀ + q. Note 0 ≤ a₁ < (q-1)/α. +// Recall α = 2γ₂. +func decompose(a uint32) (a0plusQ, a1 uint32) { + // a₁ = ⌈a / 128⌉ + a1 = (a + 127) >> 7 + + if Alpha == 523776 { + // 1025/2²² is close enough to 1/4092 so that a₁ + // becomes a/α rounded down. + a1 = ((a1*1025 + (1 << 21)) >> 22) + + // For the corner-case a₁ = (q-1)/α = 16, we have to set a₁=0. + a1 &= 15 + } else if Alpha == 190464 { + // 1488/2²⁴ is close enough to 1/1488 so that a₁ + // becomes a/α rounded down. + a1 = ((a1 * 11275) + (1 << 23)) >> 24 + + // For the corner-case a₁ = (q-1)/α = 44, we have to set a₁=0. + a1 ^= uint32(int32(43-a1)>>31) & a1 + } else { + panic("unsupported α") + } + + a0plusQ = a - a1*Alpha + + // In the corner-case, when we set a₁=0, we will incorrectly + // have a₀ > (q-1)/2 and we'll need to subtract q. As we + // return a₀ + q, that comes down to adding q if a₀ < (q-1)/2. + a0plusQ += uint32(int32(a0plusQ-(common.Q-1)/2)>>31) & common.Q + + return +} + +// Assume 0 ≤ r, f < Q with ‖f‖_∞ ≤ α/2. Decompose r as r = r1*α + r0 as +// computed by decompose(). Write r' := r - f (mod Q). Now, decompose +// r'=r-f again as r' = r'1*α + r'0 using decompose(). As f is small, we +// have r'1 = r1 + h, where h ∈ {-1, 0, 1}. makeHint() computes |h| +// given z0 := r0 - f (mod Q) and r1. With |h|, which is called the hint, +// we can reconstruct r1 using only r' = r - f, which is done by useHint(). +// To wit: +// +// useHint( r - f, makeHint( r0 - f, r1 ) ) = r1. +// +// Assumes 0 ≤ z0 < Q. +func makeHint(z0, r1 uint32) uint32 { + // If -α/2 < r0 - f ≤ α/2, then r1*α + r0 - f is a valid decomposition of r' + // with the restrictions of decompose() and so r'1 = r1. So the hint + // should be 0. This is covered by the first two inequalities. + // There is one other case: if r0 - f = -α/2, then r1*α + r0 - f is also + // a valid decomposition if r1 = 0. In the other cases a one is carried + // and the hint should be 1. + if z0 <= Gamma2 || z0 > common.Q-Gamma2 || (z0 == common.Q-Gamma2 && r1 == 0) { + return 0 + } + return 1 +} + +// Uses the hint created by makeHint() to reconstruct r1 from r'=r-f; see +// documentation of makeHint() for context. +// Assumes 0 ≤ r' < Q. +func useHint(rp uint32, hint uint32) uint32 { + rp0plusQ, rp1 := decompose(rp) + if hint == 0 { + return rp1 + } + if rp0plusQ > common.Q { + return (rp1 + 1) & 15 + } + return (rp1 - 1) & 15 +} + +// Sets p to the hint polynomial for p0 the modified low bits and p1 +// the unmodified high bits --- see makeHint(). +// +// Returns the number of ones in the hint polynomial. +func PolyMakeHint(p, p0, p1 *common.Poly) (pop uint32) { + for i := 0; i < common.N; i++ { + h := makeHint(p0[i], p1[i]) + pop += h + p[i] = h + } + return +} + +// Computes corrections to the high bits of the polynomial q according +// to the hints in h and sets p to the corrected high bits. Returns p. +func PolyUseHint(p, q, hint *common.Poly) { + var q0PlusQ common.Poly + + // See useHint() and makeHint() for an explanation. We reimplement it + // here so that we can call Poly.Decompose(), which might be way faster + // than calling decompose() in a loop (for instance when having AVX2.) + + PolyDecompose(q, &q0PlusQ, p) + + for i := 0; i < common.N; i++ { + if hint[i] == 0 { + continue + } + if Gamma2 == 261888 { + if q0PlusQ[i] > common.Q { + p[i] = (p[i] + 1) & 15 + } else { + p[i] = (p[i] - 1) & 15 + } + } else if Gamma2 == 95232 { + if q0PlusQ[i] > common.Q { + if p[i] == 43 { + p[i] = 0 + } else { + p[i]++ + } + } else { + if p[i] == 0 { + p[i] = 43 + } else { + p[i]-- + } + } + } else { + panic("unsupported γ₂") + } + } +} + +// Splits each of the coefficients of p using decompose. +func PolyDecompose(p, p0PlusQ, p1 *common.Poly) { + for i := 0; i < common.N; i++ { + p0PlusQ[i], p1[i] = decompose(p[i]) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/sample.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/sample.go new file mode 100644 index 00000000000..c47185adac4 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/sample.go @@ -0,0 +1,370 @@ +// Code generated from mode3/internal/sample.go by gen.go + +package internal + +import ( + "encoding/binary" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/sign/dilithium/internal/common" + "github.com/cloudflare/circl/simd/keccakf1600" +) + +// DeriveX4Available indicates whether the system supports the quick fourway +// sampling variants like PolyDeriveUniformX4. +var DeriveX4Available = keccakf1600.IsEnabledX4() && !UseAES + +// For each i, sample ps[i] uniformly from the given seed and nonces[i]. +// ps[i] may be nil and is ignored in that case. +// +// Can only be called when DeriveX4Available is true. +func PolyDeriveUniformX4(ps [4]*common.Poly, seed *[32]byte, nonces [4]uint16) { + var perm keccakf1600.StateX4 + state := perm.Initialize(false) + + // Absorb the seed in the four states + for i := 0; i < 4; i++ { + v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)]) + for j := 0; j < 4; j++ { + state[i*4+j] = v + } + } + + // Absorb the nonces, the SHAKE128 domain separator (0b1111), the + // start of the padding (0b...001) and the end of the padding 0b100... + // Recall that the rate of SHAKE128 is 168 --- i.e. 21 uint64s. + for j := 0; j < 4; j++ { + state[4*4+j] = uint64(nonces[j]) | (0x1f << 16) + state[20*4+j] = 0x80 << 56 + } + + var idx [4]int // indices into ps + for j := 0; j < 4; j++ { + if ps[j] == nil { + idx[j] = common.N // mark nil polynomial as completed + } + } + + done := false + for !done { + // Applies KeccaK-f[1600] to state to get the next 21 uint64s of each + // of the four SHAKE128 streams. + perm.Permute() + + done = true + + PolyLoop: + for j := 0; j < 4; j++ { + if idx[j] == common.N { + continue + } + for i := 0; i < 7; i++ { + var t [8]uint32 + t[0] = uint32(state[i*3*4+j] & 0x7fffff) + t[1] = uint32((state[i*3*4+j] >> 24) & 0x7fffff) + t[2] = uint32((state[i*3*4+j] >> 48) | + ((state[(i*3+1)*4+j] & 0x7f) << 16)) + t[3] = uint32((state[(i*3+1)*4+j] >> 8) & 0x7fffff) + t[4] = uint32((state[(i*3+1)*4+j] >> 32) & 0x7fffff) + t[5] = uint32((state[(i*3+1)*4+j] >> 56) | + ((state[(i*3+2)*4+j] & 0x7fff) << 8)) + t[6] = uint32((state[(i*3+2)*4+j] >> 16) & 0x7fffff) + t[7] = uint32((state[(i*3+2)*4+j] >> 40) & 0x7fffff) + + for k := 0; k < 8; k++ { + if t[k] < common.Q { + ps[j][idx[j]] = t[k] + idx[j]++ + if idx[j] == common.N { + continue PolyLoop + } + } + } + } + done = false + } + } +} + +// Sample p uniformly from the given seed and nonce. +// +// p will be normalized. +func PolyDeriveUniform(p *common.Poly, seed *[32]byte, nonce uint16) { + var i, length int + var buf [12 * 16]byte // fits 168B SHAKE-128 rate and 12 16B AES blocks + + if UseAES { + length = 12 * 16 + } else { + length = 168 + } + + sample := func() { + // Note that 3 divides into 168 and 12*16, so we use up buf completely. + for j := 0; j < length && i < common.N; j += 3 { + t := (uint32(buf[j]) | (uint32(buf[j+1]) << 8) | + (uint32(buf[j+2]) << 16)) & 0x7fffff + + // We use rejection sampling + if t < common.Q { + p[i] = t + i++ + } + } + } + + if UseAES { + h := common.NewAesStream128(seed, nonce) + + for i < common.N { + h.SqueezeInto(buf[:length]) + sample() + } + } else { + var iv [32 + 2]byte // 32 byte seed + uint16 nonce + h := sha3.NewShake128() + copy(iv[:32], seed[:]) + iv[32] = uint8(nonce) + iv[33] = uint8(nonce >> 8) + _, _ = h.Write(iv[:]) + + for i < common.N { + _, _ = h.Read(buf[:168]) + sample() + } + } +} + +// Sample p uniformly with coefficients of norm less than or equal η, +// using the given seed and nonce. +// +// p will not be normalized, but will have coefficients in [q-η,q+η]. +func PolyDeriveUniformLeqEta(p *common.Poly, seed *[64]byte, nonce uint16) { + // Assumes 2 < η < 8. + var i, length int + var buf [9 * 16]byte // fits 136B SHAKE-256 rate and 9 16B AES blocks + + if UseAES { + length = 9 * 16 + } else { + length = 136 + } + + sample := func() { + // We use rejection sampling + for j := 0; j < length && i < common.N; j++ { + t1 := uint32(buf[j]) & 15 + t2 := uint32(buf[j]) >> 4 + if Eta == 2 { // branch is eliminated by compiler + if t1 <= 14 { + t1 -= ((205 * t1) >> 10) * 5 // reduce mod 5 + p[i] = common.Q + Eta - t1 + i++ + } + if t2 <= 14 && i < common.N { + t2 -= ((205 * t2) >> 10) * 5 // reduce mod 5 + p[i] = common.Q + Eta - t2 + i++ + } + } else if Eta == 4 { + if t1 <= 2*Eta { + p[i] = common.Q + Eta - t1 + i++ + } + if t2 <= 2*Eta && i < common.N { + p[i] = common.Q + Eta - t2 + i++ + } + } else { + panic("unsupported η") + } + } + } + + if UseAES { + h := common.NewAesStream256(seed, nonce) + + for i < common.N { + h.SqueezeInto(buf[:length]) + sample() + } + } else { + var iv [64 + 2]byte // 64 byte seed + uint16 nonce + + h := sha3.NewShake256() + copy(iv[:64], seed[:]) + iv[64] = uint8(nonce) + iv[65] = uint8(nonce >> 8) + + // 136 is SHAKE-256 rate + _, _ = h.Write(iv[:]) + + for i < common.N { + _, _ = h.Read(buf[:136]) + sample() + } + } +} + +// Sample v[i] uniformly with coefficients in (-γ₁,…,γ₁] using the +// given seed and nonce+i +// +// p will be normalized. +func VecLDeriveUniformLeGamma1(v *VecL, seed *[64]byte, nonce uint16) { + for i := 0; i < L; i++ { + PolyDeriveUniformLeGamma1(&v[i], seed, nonce+uint16(i)) + } +} + +// Sample p uniformly with coefficients in (-γ₁,…,γK1s] using the +// given seed and nonce. +// +// p will be normalized. +func PolyDeriveUniformLeGamma1(p *common.Poly, seed *[64]byte, nonce uint16) { + var buf [PolyLeGamma1Size]byte + + if UseAES { + h := common.NewAesStream256(seed, nonce) + h.SqueezeInto(buf[:]) + } else { + var iv [66]byte + h := sha3.NewShake256() + copy(iv[:64], seed[:]) + iv[64] = uint8(nonce) + iv[65] = uint8(nonce >> 8) + _, _ = h.Write(iv[:]) + _, _ = h.Read(buf[:]) + } + + PolyUnpackLeGamma1(p, buf[:]) +} + +// For each i, sample ps[i] uniformly with τ non-zero coefficients in {q-1,1} +// using the given seed and w1[i]. ps[i] may be nil and is ignored +// in that case. ps[i] will be normalized. +// +// Can only be called when DeriveX4Available is true. +// +// This function is currently not used (yet). +func PolyDeriveUniformBallX4(ps [4]*common.Poly, seed *[32]byte) { + var perm keccakf1600.StateX4 + state := perm.Initialize(false) + + // Absorb the seed in the four states + for i := 0; i < 4; i++ { + v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)]) + for j := 0; j < 4; j++ { + state[i*4+j] = v + } + } + + // SHAKE256 domain separator and padding + for j := 0; j < 4; j++ { + state[4*4+j] ^= 0x1f + state[16*4+j] ^= 0x80 << 56 + } + perm.Permute() + + var signs [4]uint64 + var idx [4]uint16 // indices into ps + + for j := 0; j < 4; j++ { + if ps[j] != nil { + signs[j] = state[j] + *ps[j] = common.Poly{} // zero ps[j] + idx[j] = common.N - Tau + } else { + idx[j] = common.N // mark as completed + } + } + + stateOffset := 1 + for { + done := true + + PolyLoop: + for j := 0; j < 4; j++ { + if idx[j] == common.N { + continue + } + + for i := stateOffset; i < 17; i++ { + var bs [8]byte + binary.LittleEndian.PutUint64(bs[:], state[4*i+j]) + for k := 0; k < 8; k++ { + b := uint16(bs[k]) + + if b > idx[j] { + continue + } + + ps[j][idx[j]] = ps[j][b] + ps[j][b] = 1 + // Takes least significant bit of signs and uses it for the sign. + // Note 1 ^ (1 | (Q-1)) = Q-1. + ps[j][b] ^= uint32((-(signs[j] & 1)) & (1 | (common.Q - 1))) + signs[j] >>= 1 + + idx[j]++ + if idx[j] == common.N { + continue PolyLoop + } + } + } + + done = false + } + + if done { + break + } + + perm.Permute() + stateOffset = 0 + } +} + +// Samples p uniformly with τ non-zero coefficients in {q-1,1}. +// +// The polynomial p will be normalized. +func PolyDeriveUniformBall(p *common.Poly, seed *[32]byte) { + var buf [136]byte // SHAKE-256 rate is 136 + + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Read(buf[:]) + + // Essentially we generate a sequence of τ ones or minus ones, + // prepend 196 zeroes and shuffle the concatenation using the + // usual algorithm (Fisher--Yates.) + signs := binary.LittleEndian.Uint64(buf[:]) + bufOff := 8 // offset into buf + + *p = common.Poly{} // zero p + for i := uint16(common.N - Tau); i < common.N; i++ { + var b uint16 + + // Find location of where to move the new coefficient to using + // rejection sampling. + for { + if bufOff >= 136 { + _, _ = h.Read(buf[:]) + bufOff = 0 + } + + b = uint16(buf[bufOff]) + bufOff++ + + if b <= i { + break + } + } + + p[i] = p[b] + p[b] = 1 + // Takes least significant bit of signs and uses it for the sign. + // Note 1 ^ (1 | (Q-1)) = Q-1. + p[b] ^= uint32((-(signs & 1)) & (1 | (common.Q - 1))) + signs >>= 1 + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/vec.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/vec.go new file mode 100644 index 00000000000..f52973e45e8 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/vec.go @@ -0,0 +1,281 @@ +// Code generated from mode3/internal/vec.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// A vector of L polynomials. +type VecL [L]common.Poly + +// A vector of K polynomials. +type VecK [K]common.Poly + +// Normalize the polynomials in this vector. +func (v *VecL) Normalize() { + for i := 0; i < L; i++ { + v[i].Normalize() + } +} + +// Normalize the polynomials in this vector assuming their coefficients +// are already bounded by 2q. +func (v *VecL) NormalizeAssumingLe2Q() { + for i := 0; i < L; i++ { + v[i].NormalizeAssumingLe2Q() + } +} + +// Sets v to w + u. Does not normalize. +func (v *VecL) Add(w, u *VecL) { + for i := 0; i < L; i++ { + v[i].Add(&w[i], &u[i]) + } +} + +// Applies NTT componentwise. See Poly.NTT() for details. +func (v *VecL) NTT() { + for i := 0; i < L; i++ { + v[i].NTT() + } +} + +// Checks whether any of the coefficients exceeds the given bound in supnorm +// +// Requires the vector to be normalized. +func (v *VecL) Exceeds(bound uint32) bool { + for i := 0; i < L; i++ { + if v[i].Exceeds(bound) { + return true + } + } + return false +} + +// Applies Poly.Power2Round componentwise. +// +// Requires the vector to be normalized. +func (v *VecL) Power2Round(v0PlusQ, v1 *VecL) { + for i := 0; i < L; i++ { + v[i].Power2Round(&v0PlusQ[i], &v1[i]) + } +} + +// Applies Poly.Decompose componentwise. +// +// Requires the vector to be normalized. +func (v *VecL) Decompose(v0PlusQ, v1 *VecL) { + for i := 0; i < L; i++ { + PolyDecompose(&v[i], &v0PlusQ[i], &v1[i]) + } +} + +// Sequentially packs each polynomial using Poly.PackLeqEta(). +func (v *VecL) PackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyPackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Sets v to the polynomials packed in buf using VecL.PackLeqEta(). +func (v *VecL) UnpackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyUnpackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Sequentially packs each polynomial using PolyPackLeGamma1(). +func (v *VecL) PackLeGamma1(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyPackLeGamma1(&v[i], buf[offset:]) + offset += PolyLeGamma1Size + } +} + +// Sets v to the polynomials packed in buf using VecL.PackLeGamma1(). +func (v *VecL) UnpackLeGamma1(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyUnpackLeGamma1(&v[i], buf[offset:]) + offset += PolyLeGamma1Size + } +} + +// Normalize the polynomials in this vector. +func (v *VecK) Normalize() { + for i := 0; i < K; i++ { + v[i].Normalize() + } +} + +// Normalize the polynomials in this vector assuming their coefficients +// are already bounded by 2q. +func (v *VecK) NormalizeAssumingLe2Q() { + for i := 0; i < K; i++ { + v[i].NormalizeAssumingLe2Q() + } +} + +// Sets v to w + u. Does not normalize. +func (v *VecK) Add(w, u *VecK) { + for i := 0; i < K; i++ { + v[i].Add(&w[i], &u[i]) + } +} + +// Checks whether any of the coefficients exceeds the given bound in supnorm +// +// Requires the vector to be normalized. +func (v *VecK) Exceeds(bound uint32) bool { + for i := 0; i < K; i++ { + if v[i].Exceeds(bound) { + return true + } + } + return false +} + +// Applies Poly.Power2Round componentwise. +// +// Requires the vector to be normalized. +func (v *VecK) Power2Round(v0PlusQ, v1 *VecK) { + for i := 0; i < K; i++ { + v[i].Power2Round(&v0PlusQ[i], &v1[i]) + } +} + +// Applies Poly.Decompose componentwise. +// +// Requires the vector to be normalized. +func (v *VecK) Decompose(v0PlusQ, v1 *VecK) { + for i := 0; i < K; i++ { + PolyDecompose(&v[i], &v0PlusQ[i], &v1[i]) + } +} + +// Sets v to the hint vector for v0 the modified low bits and v1 +// the unmodified high bits --- see makeHint(). +// +// Returns the number of ones in the hint vector. +func (v *VecK) MakeHint(v0, v1 *VecK) (pop uint32) { + for i := 0; i < K; i++ { + pop += PolyMakeHint(&v[i], &v0[i], &v1[i]) + } + return +} + +// Computes corrections to the high bits of the polynomials in the vector +// w using the hints in h and sets v to the corrected high bits. Returns v. +// See useHint(). +func (v *VecK) UseHint(q, hint *VecK) *VecK { + for i := 0; i < K; i++ { + PolyUseHint(&v[i], &q[i], &hint[i]) + } + return v +} + +// Sequentially packs each polynomial using Poly.PackT1(). +func (v *VecK) PackT1(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].PackT1(buf[offset:]) + offset += common.PolyT1Size + } +} + +// Sets v to the vector packed into buf by PackT1(). +func (v *VecK) UnpackT1(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].UnpackT1(buf[offset:]) + offset += common.PolyT1Size + } +} + +// Sequentially packs each polynomial using Poly.PackT0(). +func (v *VecK) PackT0(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].PackT0(buf[offset:]) + offset += common.PolyT0Size + } +} + +// Sets v to the vector packed into buf by PackT0(). +func (v *VecK) UnpackT0(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].UnpackT0(buf[offset:]) + offset += common.PolyT0Size + } +} + +// Sequentially packs each polynomial using Poly.PackLeqEta(). +func (v *VecK) PackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + PolyPackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Sets v to the polynomials packed in buf using VecK.PackLeqEta(). +func (v *VecK) UnpackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + PolyUnpackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Applies NTT componentwise. See Poly.NTT() for details. +func (v *VecK) NTT() { + for i := 0; i < K; i++ { + v[i].NTT() + } +} + +// Sequentially packs each polynomial using PolyPackW1(). +func (v *VecK) PackW1(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + PolyPackW1(&v[i], buf[offset:]) + offset += PolyW1Size + } +} + +// Sets v to a - b. +// +// Warning: assumes coefficients of the polynomials of b are less than 2q. +func (v *VecK) Sub(a, b *VecK) { + for i := 0; i < K; i++ { + v[i].Sub(&a[i], &b[i]) + } +} + +// Sets v to 2ᵈ w without reducing. +func (v *VecK) MulBy2toD(w *VecK) { + for i := 0; i < K; i++ { + v[i].MulBy2toD(&w[i]) + } +} + +// Applies InvNTT componentwise. See Poly.InvNTT() for details. +func (v *VecK) InvNTT() { + for i := 0; i < K; i++ { + v[i].InvNTT() + } +} + +// Applies Poly.ReduceLe2Q() componentwise. +func (v *VecK) ReduceLe2Q() { + for i := 0; i < K; i++ { + v[i].ReduceLe2Q() + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/dilithium.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/dilithium.go new file mode 100644 index 00000000000..3ab9d6b5365 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/dilithium.go @@ -0,0 +1,181 @@ +// Code generated from modePkg.templ.go. DO NOT EDIT. + +// mode3 implements the CRYSTALS-Dilithium signature scheme Dilithium3 +// as submitted to round3 of the NIST PQC competition and described in +// +// https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf +package mode3 + +import ( + "crypto" + "errors" + "io" + + "github.com/cloudflare/circl/sign/dilithium/internal/common" + "github.com/cloudflare/circl/sign/dilithium/mode3/internal" +) + +const ( + // Size of seed for NewKeyFromSeed + SeedSize = common.SeedSize + + // Size of a packed PublicKey + PublicKeySize = internal.PublicKeySize + + // Size of a packed PrivateKey + PrivateKeySize = internal.PrivateKeySize + + // Size of a signature + SignatureSize = internal.SignatureSize +) + +// PublicKey is the type of Dilithium3 public key +type PublicKey internal.PublicKey + +// PrivateKey is the type of Dilithium3 private key +type PrivateKey internal.PrivateKey + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + pk, sk, err := internal.GenerateKey(rand) + return (*PublicKey)(pk), (*PrivateKey)(sk), err +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { + pk, sk := internal.NewKeyFromSeed(seed) + return (*PublicKey)(pk), (*PrivateKey)(sk) +} + +// SignTo signs the given message and writes the signature into signature. +// It will panic if signature is not of length at least SignatureSize. +func SignTo(sk *PrivateKey, msg []byte, signature []byte) { + internal.SignTo( + (*internal.PrivateKey)(sk), + msg, + signature, + ) +} + +// Verify checks whether the given signature by pk on msg is valid. +func Verify(pk *PublicKey, msg []byte, signature []byte) bool { + return internal.Verify( + (*internal.PublicKey)(pk), + msg, + signature, + ) +} + +// Sets pk to the public key encoded in buf. +func (pk *PublicKey) Unpack(buf *[PublicKeySize]byte) { + (*internal.PublicKey)(pk).Unpack(buf) +} + +// Sets sk to the private key encoded in buf. +func (sk *PrivateKey) Unpack(buf *[PrivateKeySize]byte) { + (*internal.PrivateKey)(sk).Unpack(buf) +} + +// Packs the public key into buf. +func (pk *PublicKey) Pack(buf *[PublicKeySize]byte) { + (*internal.PublicKey)(pk).Pack(buf) +} + +// Packs the private key into buf. +func (sk *PrivateKey) Pack(buf *[PrivateKeySize]byte) { + (*internal.PrivateKey)(sk).Pack(buf) +} + +// Packs the public key. +func (pk *PublicKey) Bytes() []byte { + var buf [PublicKeySize]byte + pk.Pack(&buf) + return buf[:] +} + +// Packs the private key. +func (sk *PrivateKey) Bytes() []byte { + var buf [PrivateKeySize]byte + sk.Pack(&buf) + return buf[:] +} + +// Packs the public key. +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + return pk.Bytes(), nil +} + +// Packs the private key. +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + return sk.Bytes(), nil +} + +// Unpacks the public key from data. +func (pk *PublicKey) UnmarshalBinary(data []byte) error { + if len(data) != PublicKeySize { + return errors.New("packed public key must be of mode3.PublicKeySize bytes") + } + var buf [PublicKeySize]byte + copy(buf[:], data) + pk.Unpack(&buf) + return nil +} + +// Unpacks the private key from data. +func (sk *PrivateKey) UnmarshalBinary(data []byte) error { + if len(data) != PrivateKeySize { + return errors.New("packed private key must be of mode3.PrivateKeySize bytes") + } + var buf [PrivateKeySize]byte + copy(buf[:], data) + sk.Unpack(&buf) + return nil +} + +// Sign signs the given message. +// +// opts.HashFunc() must return zero, which can be achieved by passing +// crypto.Hash(0) for opts. rand is ignored. Will only return an error +// if opts.HashFunc() is non-zero. +// +// This function is used to make PrivateKey implement the crypto.Signer +// interface. The package-level SignTo function might be more convenient +// to use. +func (sk *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ( + signature []byte, err error) { + var sig [SignatureSize]byte + + if opts.HashFunc() != crypto.Hash(0) { + return nil, errors.New("dilithium: cannot sign hashed message") + } + + SignTo(sk, msg, sig[:]) + return sig[:], nil +} + +// Computes the public key corresponding to this private key. +// +// Returns a *PublicKey. The type crypto.PublicKey is used to make +// PrivateKey implement the crypto.Signer interface. +func (sk *PrivateKey) Public() crypto.PublicKey { + return (*PublicKey)((*internal.PrivateKey)(sk).Public()) +} + +// Equal returns whether the two private keys equal. +func (sk *PrivateKey) Equal(other crypto.PrivateKey) bool { + castOther, ok := other.(*PrivateKey) + if !ok { + return false + } + return (*internal.PrivateKey)(sk).Equal((*internal.PrivateKey)(castOther)) +} + +// Equal returns whether the two public keys equal. +func (pk *PublicKey) Equal(other crypto.PublicKey) bool { + castOther, ok := other.(*PublicKey) + if !ok { + return false + } + return (*internal.PublicKey)(pk).Equal((*internal.PublicKey)(castOther)) +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/dilithium.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/dilithium.go new file mode 100644 index 00000000000..59e43cc1372 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/dilithium.go @@ -0,0 +1,475 @@ +package internal + +import ( + cryptoRand "crypto/rand" + "crypto/subtle" + "io" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +const ( + // Size of a packed polynomial of norm ≤η. + // (Note that the formula is not valid in general.) + PolyLeqEtaSize = (common.N * DoubleEtaBits) / 8 + + // β = τη, the maximum size of c s₂. + Beta = Tau * Eta + + // γ₁ range of y + Gamma1 = 1 << Gamma1Bits + + // Size of packed polynomial of norm <γ₁ such as z + PolyLeGamma1Size = (Gamma1Bits + 1) * common.N / 8 + + // α = 2γ₂ parameter for decompose + Alpha = 2 * Gamma2 + + // Size of a packed private key + PrivateKeySize = 32 + 32 + 32 + PolyLeqEtaSize*(L+K) + common.PolyT0Size*K + + // Size of a packed public key + PublicKeySize = 32 + common.PolyT1Size*K + + // Size of a packed signature + SignatureSize = L*PolyLeGamma1Size + Omega + K + 32 + + // Size of packed w₁ + PolyW1Size = (common.N * (common.QBits - Gamma1Bits)) / 8 +) + +// PublicKey is the type of Dilithium public keys. +type PublicKey struct { + rho [32]byte + t1 VecK + + // Cached values + t1p [common.PolyT1Size * K]byte + A *Mat + tr *[32]byte +} + +// PrivateKey is the type of Dilithium private keys. +type PrivateKey struct { + rho [32]byte + key [32]byte + s1 VecL + s2 VecK + t0 VecK + tr [32]byte + + // Cached values + A Mat // ExpandA(ρ) + s1h VecL // NTT(s₁) + s2h VecK // NTT(s₂) + t0h VecK // NTT(t₀) +} + +type unpackedSignature struct { + z VecL + hint VecK + c [32]byte +} + +// Packs the signature into buf. +func (sig *unpackedSignature) Pack(buf []byte) { + copy(buf[:], sig.c[:]) + sig.z.PackLeGamma1(buf[32:]) + sig.hint.PackHint(buf[32+L*PolyLeGamma1Size:]) +} + +// Sets sig to the signature encoded in the buffer. +// +// Returns whether buf contains a properly packed signature. +func (sig *unpackedSignature) Unpack(buf []byte) bool { + if len(buf) < SignatureSize { + return false + } + copy(sig.c[:], buf[:]) + sig.z.UnpackLeGamma1(buf[32:]) + if sig.z.Exceeds(Gamma1 - Beta) { + return false + } + if !sig.hint.UnpackHint(buf[32+L*PolyLeGamma1Size:]) { + return false + } + return true +} + +// Packs the public key into buf. +func (pk *PublicKey) Pack(buf *[PublicKeySize]byte) { + copy(buf[:32], pk.rho[:]) + copy(buf[32:], pk.t1p[:]) +} + +// Sets pk to the public key encoded in buf. +func (pk *PublicKey) Unpack(buf *[PublicKeySize]byte) { + copy(pk.rho[:], buf[:32]) + copy(pk.t1p[:], buf[32:]) + + pk.t1.UnpackT1(pk.t1p[:]) + pk.A = new(Mat) + pk.A.Derive(&pk.rho) + + // tr = CRH(ρ ‖ t1) = CRH(pk) + pk.tr = new([32]byte) + h := sha3.NewShake256() + _, _ = h.Write(buf[:]) + _, _ = h.Read(pk.tr[:]) +} + +// Packs the private key into buf. +func (sk *PrivateKey) Pack(buf *[PrivateKeySize]byte) { + copy(buf[:32], sk.rho[:]) + copy(buf[32:64], sk.key[:]) + copy(buf[64:96], sk.tr[:]) + offset := 96 + sk.s1.PackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * L + sk.s2.PackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * K + sk.t0.PackT0(buf[offset:]) +} + +// Sets sk to the private key encoded in buf. +func (sk *PrivateKey) Unpack(buf *[PrivateKeySize]byte) { + copy(sk.rho[:], buf[:32]) + copy(sk.key[:], buf[32:64]) + copy(sk.tr[:], buf[64:96]) + offset := 96 + sk.s1.UnpackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * L + sk.s2.UnpackLeqEta(buf[offset:]) + offset += PolyLeqEtaSize * K + sk.t0.UnpackT0(buf[offset:]) + + // Cached values + sk.A.Derive(&sk.rho) + sk.t0h = sk.t0 + sk.t0h.NTT() + sk.s1h = sk.s1 + sk.s1h.NTT() + sk.s2h = sk.s2 + sk.s2h.NTT() +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [32]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + pk, sk := NewKeyFromSeed(&seed) + return pk, sk, nil +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +func NewKeyFromSeed(seed *[common.SeedSize]byte) (*PublicKey, *PrivateKey) { + var eSeed [128]byte // expanded seed + var pk PublicKey + var sk PrivateKey + var sSeed [64]byte + + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Read(eSeed[:]) + + copy(pk.rho[:], eSeed[:32]) + copy(sSeed[:], eSeed[32:96]) + copy(sk.key[:], eSeed[96:]) + copy(sk.rho[:], pk.rho[:]) + + sk.A.Derive(&pk.rho) + + for i := uint16(0); i < L; i++ { + PolyDeriveUniformLeqEta(&sk.s1[i], &sSeed, i) + } + + for i := uint16(0); i < K; i++ { + PolyDeriveUniformLeqEta(&sk.s2[i], &sSeed, i+L) + } + + sk.s1h = sk.s1 + sk.s1h.NTT() + sk.s2h = sk.s2 + sk.s2h.NTT() + + sk.computeT0andT1(&sk.t0, &pk.t1) + + sk.t0h = sk.t0 + sk.t0h.NTT() + + // Complete public key far enough to be packed + pk.t1.PackT1(pk.t1p[:]) + pk.A = &sk.A + + // Finish private key + var packedPk [PublicKeySize]byte + pk.Pack(&packedPk) + + // tr = CRH(ρ ‖ t1) = CRH(pk) + h.Reset() + _, _ = h.Write(packedPk[:]) + _, _ = h.Read(sk.tr[:]) + + // Finish cache of public key + pk.tr = &sk.tr + + return &pk, &sk +} + +// Computes t0 and t1 from sk.s1h, sk.s2 and sk.A. +func (sk *PrivateKey) computeT0andT1(t0, t1 *VecK) { + var t VecK + + // Set t to A s₁ + s₂ + for i := 0; i < K; i++ { + PolyDotHat(&t[i], &sk.A[i], &sk.s1h) + t[i].ReduceLe2Q() + t[i].InvNTT() + } + t.Add(&t, &sk.s2) + t.Normalize() + + // Compute t₀, t₁ = Power2Round(t) + t.Power2Round(t0, t1) +} + +// Verify checks whether the given signature by pk on msg is valid. +func Verify(pk *PublicKey, msg []byte, signature []byte) bool { + var sig unpackedSignature + var mu [64]byte + var zh VecL + var Az, Az2dct1, w1 VecK + var ch common.Poly + var cp [32]byte + var w1Packed [PolyW1Size * K]byte + + // Note that Unpack() checked whether ‖z‖_∞ < γ₁ - β + // and ensured that there at most ω ones in pk.hint. + if !sig.Unpack(signature) { + return false + } + + // μ = CRH(tr ‖ msg) + h := sha3.NewShake256() + _, _ = h.Write(pk.tr[:]) + _, _ = h.Write(msg) + _, _ = h.Read(mu[:]) + + // Compute Az + zh = sig.z + zh.NTT() + + for i := 0; i < K; i++ { + PolyDotHat(&Az[i], &pk.A[i], &zh) + } + + // Next, we compute Az - 2ᵈ·c·t₁. + // Note that the coefficients of t₁ are bounded by 256 = 2⁹, + // so the coefficients of Az2dct1 will bounded by 2⁹⁺ᵈ = 2²³ < 2q, + // which is small enough for NTT(). + Az2dct1.MulBy2toD(&pk.t1) + Az2dct1.NTT() + PolyDeriveUniformBall(&ch, &sig.c) + ch.NTT() + for i := 0; i < K; i++ { + Az2dct1[i].MulHat(&Az2dct1[i], &ch) + } + Az2dct1.Sub(&Az, &Az2dct1) + Az2dct1.ReduceLe2Q() + Az2dct1.InvNTT() + Az2dct1.NormalizeAssumingLe2Q() + + // UseHint(pk.hint, Az - 2ᵈ·c·t₁) + // = UseHint(pk.hint, w - c·s₂ + c·t₀) + // = UseHint(pk.hint, r + c·t₀) + // = r₁ = w₁. + w1.UseHint(&Az2dct1, &sig.hint) + w1.PackW1(w1Packed[:]) + + // c' = H(μ, w₁) + h.Reset() + _, _ = h.Write(mu[:]) + _, _ = h.Write(w1Packed[:]) + _, _ = h.Read(cp[:]) + + return sig.c == cp +} + +// SignTo signs the given message and writes the signature into signature. +// +//nolint:funlen +func SignTo(sk *PrivateKey, msg []byte, signature []byte) { + var mu, rhop [64]byte + var w1Packed [PolyW1Size * K]byte + var y, yh VecL + var w, w0, w1, w0mcs2, ct0, w0mcs2pct0 VecK + var ch common.Poly + var yNonce uint16 + var sig unpackedSignature + + if len(signature) < SignatureSize { + panic("Signature does not fit in that byteslice") + } + + // μ = CRH(tr ‖ msg) + h := sha3.NewShake256() + _, _ = h.Write(sk.tr[:]) + _, _ = h.Write(msg) + _, _ = h.Read(mu[:]) + + // ρ' = CRH(key ‖ μ) + h.Reset() + _, _ = h.Write(sk.key[:]) + _, _ = h.Write(mu[:]) + _, _ = h.Read(rhop[:]) + + // Main rejection loop + attempt := 0 + for { + attempt++ + if attempt >= 576 { + // Depending on the mode, one try has a chance between 1/7 and 1/4 + // of succeeding. Thus it is safe to say that 576 iterations + // are enough as (6/7)⁵⁷⁶ < 2⁻¹²⁸. + panic("This should only happen 1 in 2^{128}: something is wrong.") + } + + // y = ExpandMask(ρ', key) + VecLDeriveUniformLeGamma1(&y, &rhop, yNonce) + yNonce += uint16(L) + + // Set w to A y + yh = y + yh.NTT() + for i := 0; i < K; i++ { + PolyDotHat(&w[i], &sk.A[i], &yh) + w[i].ReduceLe2Q() + w[i].InvNTT() + } + + // Decompose w into w₀ and w₁ + w.NormalizeAssumingLe2Q() + w.Decompose(&w0, &w1) + + // c~ = H(μ ‖ w₁) + w1.PackW1(w1Packed[:]) + h.Reset() + _, _ = h.Write(mu[:]) + _, _ = h.Write(w1Packed[:]) + _, _ = h.Read(sig.c[:]) + + PolyDeriveUniformBall(&ch, &sig.c) + ch.NTT() + + // Ensure ‖ w₀ - c·s2 ‖_∞ < γ₂ - β. + // + // By Lemma 3 of the specification this is equivalent to checking that + // both ‖ r₀ ‖_∞ < γ₂ - β and r₁ = w₁, for the decomposition + // w - c·s₂ = r₁ α + r₀ as computed by decompose(). + // See also §4.1 of the specification. + for i := 0; i < K; i++ { + w0mcs2[i].MulHat(&ch, &sk.s2h[i]) + w0mcs2[i].InvNTT() + } + w0mcs2.Sub(&w0, &w0mcs2) + w0mcs2.Normalize() + + if w0mcs2.Exceeds(Gamma2 - Beta) { + continue + } + + // z = y + c·s₁ + for i := 0; i < L; i++ { + sig.z[i].MulHat(&ch, &sk.s1h[i]) + sig.z[i].InvNTT() + } + sig.z.Add(&sig.z, &y) + sig.z.Normalize() + + // Ensure ‖z‖_∞ < γ₁ - β + if sig.z.Exceeds(Gamma1 - Beta) { + continue + } + + // Compute c·t₀ + for i := 0; i < K; i++ { + ct0[i].MulHat(&ch, &sk.t0h[i]) + ct0[i].InvNTT() + } + ct0.NormalizeAssumingLe2Q() + + // Ensure ‖c·t₀‖_∞ < γ₂. + if ct0.Exceeds(Gamma2) { + continue + } + + // Create the hint to be able to reconstruct w₁ from w - c·s₂ + c·t0. + // Note that we're not using makeHint() in the obvious way as we + // do not know whether ‖ sc·s₂ - c·t₀ ‖_∞ < γ₂. Instead we note + // that our makeHint() is actually the same as a makeHint for a + // different decomposition: + // + // Earlier we ensured indirectly with a check that r₁ = w₁ where + // r = w - c·s₂. Hence r₀ = r - r₁ α = w - c·s₂ - w₁ α = w₀ - c·s₂. + // Thus MakeHint(w₀ - c·s₂ + c·t₀, w₁) = MakeHint(r0 + c·t₀, r₁) + // and UseHint(w - c·s₂ + c·t₀, w₁) = UseHint(r + c·t₀, r₁). + // As we just ensured that ‖ c·t₀ ‖_∞ < γ₂ our usage is correct. + w0mcs2pct0.Add(&w0mcs2, &ct0) + w0mcs2pct0.NormalizeAssumingLe2Q() + hintPop := sig.hint.MakeHint(&w0mcs2pct0, &w1) + if hintPop > Omega { + continue + } + + break + } + + sig.Pack(signature[:]) +} + +// Computes the public key corresponding to this private key. +func (sk *PrivateKey) Public() *PublicKey { + var t0 VecK + pk := &PublicKey{ + rho: sk.rho, + A: &sk.A, + tr: &sk.tr, + } + sk.computeT0andT1(&t0, &pk.t1) + pk.t1.PackT1(pk.t1p[:]) + return pk +} + +// Equal returns whether the two public keys are equal +func (pk *PublicKey) Equal(other *PublicKey) bool { + return pk.rho == other.rho && pk.t1 == other.t1 +} + +// Equal returns whether the two private keys are equal +func (sk *PrivateKey) Equal(other *PrivateKey) bool { + ret := (subtle.ConstantTimeCompare(sk.rho[:], other.rho[:]) & + subtle.ConstantTimeCompare(sk.key[:], other.key[:]) & + subtle.ConstantTimeCompare(sk.tr[:], other.tr[:])) + + acc := uint32(0) + for i := 0; i < L; i++ { + for j := 0; j < common.N; j++ { + acc |= sk.s1[i][j] ^ other.s1[i][j] + } + } + for i := 0; i < K; i++ { + for j := 0; j < common.N; j++ { + acc |= sk.s2[i][j] ^ other.s2[i][j] + acc |= sk.t0[i][j] ^ other.t0[i][j] + } + } + return (ret & subtle.ConstantTimeEq(int32(acc), 0)) == 1 +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/mat.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/mat.go new file mode 100644 index 00000000000..ce39b7f9a1b --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/mat.go @@ -0,0 +1,57 @@ +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// A k by l matrix of polynomials. +type Mat [K]VecL + +// Expands the given seed to a complete matrix. +// +// This function is called ExpandA in the specification. +func (m *Mat) Derive(seed *[32]byte) { + if !DeriveX4Available { + for i := uint16(0); i < K; i++ { + for j := uint16(0); j < L; j++ { + PolyDeriveUniform(&m[i][j], seed, (i<<8)+j) + } + } + return + } + + idx := 0 + var nonces [4]uint16 + var ps [4]*common.Poly + for i := uint16(0); i < K; i++ { + for j := uint16(0); j < L; j++ { + nonces[idx] = (i << 8) + j + ps[idx] = &m[i][j] + idx++ + if idx == 4 { + idx = 0 + PolyDeriveUniformX4(ps, seed, nonces) + } + } + } + if idx != 0 { + for i := idx; i < 4; i++ { + ps[i] = nil + } + PolyDeriveUniformX4(ps, seed, nonces) + } +} + +// Set p to the inner product of a and b using pointwise multiplication. +// +// Assumes a and b are in Montgomery form and their coefficients are +// pairwise sufficiently small to multiply, see Poly.MulHat(). Resulting +// coefficients are bounded by 2Lq. +func PolyDotHat(p *common.Poly, a, b *VecL) { + var t common.Poly + *p = common.Poly{} // zero p + for i := 0; i < L; i++ { + t.MulHat(&a[i], &b[i]) + p.Add(&t, p) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/pack.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/pack.go new file mode 100644 index 00000000000..6a152d73ebb --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/pack.go @@ -0,0 +1,268 @@ +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// Writes p with norm less than or equal η into buf, which must be of +// size PolyLeqEtaSize. +// +// Assumes coefficients of p are not normalized, but in [q-η,q+η]. +func PolyPackLeqEta(p *common.Poly, buf []byte) { + if DoubleEtaBits == 4 { // compiler eliminates branch + j := 0 + for i := 0; i < PolyLeqEtaSize; i++ { + buf[i] = (byte(common.Q+Eta-p[j]) | + byte(common.Q+Eta-p[j+1])<<4) + j += 2 + } + } else if DoubleEtaBits == 3 { + j := 0 + for i := 0; i < PolyLeqEtaSize; i += 3 { + buf[i] = (byte(common.Q+Eta-p[j]) | + (byte(common.Q+Eta-p[j+1]) << 3) | + (byte(common.Q+Eta-p[j+2]) << 6)) + buf[i+1] = ((byte(common.Q+Eta-p[j+2]) >> 2) | + (byte(common.Q+Eta-p[j+3]) << 1) | + (byte(common.Q+Eta-p[j+4]) << 4) | + (byte(common.Q+Eta-p[j+5]) << 7)) + buf[i+2] = ((byte(common.Q+Eta-p[j+5]) >> 1) | + (byte(common.Q+Eta-p[j+6]) << 2) | + (byte(common.Q+Eta-p[j+7]) << 5)) + j += 8 + } + } else { + panic("eta not supported") + } +} + +// Sets p to the polynomial of norm less than or equal η encoded in the +// given buffer of size PolyLeqEtaSize. +// +// Output coefficients of p are not normalized, but in [q-η,q+η] provided +// buf was created using PackLeqEta. +// +// Beware, for arbitrary buf the coefficients of p might end up in +// the interval [q-2^b,q+2^b] where b is the least b with η≤2^b. +func PolyUnpackLeqEta(p *common.Poly, buf []byte) { + if DoubleEtaBits == 4 { // compiler eliminates branch + j := 0 + for i := 0; i < PolyLeqEtaSize; i++ { + p[j] = common.Q + Eta - uint32(buf[i]&15) + p[j+1] = common.Q + Eta - uint32(buf[i]>>4) + j += 2 + } + } else if DoubleEtaBits == 3 { + j := 0 + for i := 0; i < PolyLeqEtaSize; i += 3 { + p[j] = common.Q + Eta - uint32(buf[i]&7) + p[j+1] = common.Q + Eta - uint32((buf[i]>>3)&7) + p[j+2] = common.Q + Eta - uint32((buf[i]>>6)|((buf[i+1]<<2)&7)) + p[j+3] = common.Q + Eta - uint32((buf[i+1]>>1)&7) + p[j+4] = common.Q + Eta - uint32((buf[i+1]>>4)&7) + p[j+5] = common.Q + Eta - uint32((buf[i+1]>>7)|((buf[i+2]<<1)&7)) + p[j+6] = common.Q + Eta - uint32((buf[i+2]>>2)&7) + p[j+7] = common.Q + Eta - uint32((buf[i+2]>>5)&7) + j += 8 + } + } else { + panic("eta not supported") + } +} + +// Writes v with coefficients in {0, 1} of which at most ω non-zero +// to buf, which must have length ω+k. +func (v *VecK) PackHint(buf []byte) { + // The packed hint starts with the indices of the non-zero coefficients + // For instance: + // + // (x⁵⁶ + x¹⁰⁰, x²⁵⁵, 0, x² + x²³, x¹) + // + // Yields + // + // 56, 100, 255, 2, 23, 1 + // + // Then we pad with zeroes until we have a list of ω items: + // // 56, 100, 255, 2, 23, 1, 0, 0, ..., 0 + // + // Then we finish with a list of the switch-over-indices in this + // list between polynomials, so: + // + // 56, 100, 255, 2, 23, 1, 0, 0, ..., 0, 2, 3, 3, 5, 6 + + off := uint8(0) + for i := 0; i < K; i++ { + for j := uint16(0); j < common.N; j++ { + if v[i][j] != 0 { + buf[off] = uint8(j) + off++ + } + } + buf[Omega+i] = off + } + for ; off < Omega; off++ { + buf[off] = 0 + } +} + +// Sets v to the vector encoded using VecK.PackHint() +// +// Returns whether unpacking was successful. +func (v *VecK) UnpackHint(buf []byte) bool { + // A priori, there would be several reasonable ways to encode the same + // hint vector. We take care to only allow only one encoding, to ensure + // "strong unforgeability". + // + // See PackHint() source for description of the encoding. + *v = VecK{} // zero v + prevSOP := uint8(0) // previous switch-over-point + for i := 0; i < K; i++ { + SOP := buf[Omega+i] + if SOP < prevSOP || SOP > Omega { + return false // ensures switch-over-points are increasing + } + for j := prevSOP; j < SOP; j++ { + if j > prevSOP && buf[j] <= buf[j-1] { + return false // ensures indices are increasing (within a poly) + } + v[i][buf[j]] = 1 + } + prevSOP = SOP + } + for j := prevSOP; j < Omega; j++ { + if buf[j] != 0 { + return false // ensures padding indices are zero + } + } + + return true +} + +// Sets p to the polynomial packed into buf by PolyPackLeGamma1. +// +// p will be normalized. +func PolyUnpackLeGamma1(p *common.Poly, buf []byte) { + if Gamma1Bits == 17 { + j := 0 + for i := 0; i < PolyLeGamma1Size; i += 9 { + p0 := uint32(buf[i]) | (uint32(buf[i+1]) << 8) | + (uint32(buf[i+2]&0x3) << 16) + p1 := uint32(buf[i+2]>>2) | (uint32(buf[i+3]) << 6) | + (uint32(buf[i+4]&0xf) << 14) + p2 := uint32(buf[i+4]>>4) | (uint32(buf[i+5]) << 4) | + (uint32(buf[i+6]&0x3f) << 12) + p3 := uint32(buf[i+6]>>6) | (uint32(buf[i+7]) << 2) | + (uint32(buf[i+8]) << 10) + + // coefficients in [0,…,2γ₁) + p0 = Gamma1 - p0 // (-γ₁,…,γ₁] + p1 = Gamma1 - p1 + p2 = Gamma1 - p2 + p3 = Gamma1 - p3 + + p0 += uint32(int32(p0)>>31) & common.Q // normalize + p1 += uint32(int32(p1)>>31) & common.Q + p2 += uint32(int32(p2)>>31) & common.Q + p3 += uint32(int32(p3)>>31) & common.Q + + p[j] = p0 + p[j+1] = p1 + p[j+2] = p2 + p[j+3] = p3 + + j += 4 + } + } else if Gamma1Bits == 19 { + j := 0 + for i := 0; i < PolyLeGamma1Size; i += 5 { + p0 := uint32(buf[i]) | (uint32(buf[i+1]) << 8) | + (uint32(buf[i+2]&0xf) << 16) + p1 := uint32(buf[i+2]>>4) | (uint32(buf[i+3]) << 4) | + (uint32(buf[i+4]) << 12) + + p0 = Gamma1 - p0 + p1 = Gamma1 - p1 + + p0 += uint32(int32(p0)>>31) & common.Q + p1 += uint32(int32(p1)>>31) & common.Q + + p[j] = p0 + p[j+1] = p1 + + j += 2 + } + } else { + panic("γ₁ not supported") + } +} + +// Writes p whose coefficients are in (-γ₁,γ₁] into buf +// which has to be of length PolyLeGamma1Size. +// +// Assumes p is normalized. +func PolyPackLeGamma1(p *common.Poly, buf []byte) { + if Gamma1Bits == 17 { + j := 0 + // coefficients in [0,…,γ₁] ∪ (q-γ₁,…,q) + for i := 0; i < PolyLeGamma1Size; i += 9 { + p0 := Gamma1 - p[j] // [0,…,γ₁] ∪ (γ₁-q,…,2γ₁-q) + p0 += uint32(int32(p0)>>31) & common.Q // [0,…,2γ₁) + p1 := Gamma1 - p[j+1] + p1 += uint32(int32(p1)>>31) & common.Q + p2 := Gamma1 - p[j+2] + p2 += uint32(int32(p2)>>31) & common.Q + p3 := Gamma1 - p[j+3] + p3 += uint32(int32(p3)>>31) & common.Q + + buf[i+0] = byte(p0) + buf[i+1] = byte(p0 >> 8) + buf[i+2] = byte(p0>>16) | byte(p1<<2) + buf[i+3] = byte(p1 >> 6) + buf[i+4] = byte(p1>>14) | byte(p2<<4) + buf[i+5] = byte(p2 >> 4) + buf[i+6] = byte(p2>>12) | byte(p3<<6) + buf[i+7] = byte(p3 >> 2) + buf[i+8] = byte(p3 >> 10) + + j += 4 + } + } else if Gamma1Bits == 19 { + j := 0 + for i := 0; i < PolyLeGamma1Size; i += 5 { + // Coefficients are in [0, γ₁] ∪ (Q-γ₁, Q) + p0 := Gamma1 - p[j] + p0 += uint32(int32(p0)>>31) & common.Q + p1 := Gamma1 - p[j+1] + p1 += uint32(int32(p1)>>31) & common.Q + + buf[i+0] = byte(p0) + buf[i+1] = byte(p0 >> 8) + buf[i+2] = byte(p0>>16) | byte(p1<<4) + buf[i+3] = byte(p1 >> 4) + buf[i+4] = byte(p1 >> 12) + + j += 2 + } + } else { + panic("γ₁ not supported") + } +} + +// Pack w₁ into buf, which must be of length PolyW1Size. +// +// Assumes w₁ is normalized. +func PolyPackW1(p *common.Poly, buf []byte) { + if Gamma1Bits == 19 { + p.PackLe16(buf) + } else if Gamma1Bits == 17 { + j := 0 + for i := 0; i < PolyW1Size; i += 3 { + buf[i] = byte(p[j]) | byte(p[j+1]<<6) + buf[i+1] = byte(p[j+1]>>2) | byte(p[j+2]<<4) + buf[i+2] = byte(p[j+2]>>4) | byte(p[j+3]<<2) + j += 4 + } + } else { + panic("unsupported γ₁") + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/params.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/params.go new file mode 100644 index 00000000000..c229252349f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/params.go @@ -0,0 +1,16 @@ +// Code generated from params.templ.go. DO NOT EDIT. + +package internal + +const ( + Name = "Dilithium3" + UseAES = false + K = 6 + L = 5 + Eta = 4 + DoubleEtaBits = 4 + Omega = 55 + Tau = 49 + Gamma1Bits = 19 + Gamma2 = 261888 +) diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/rounding.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/rounding.go new file mode 100644 index 00000000000..f44c951d263 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/rounding.go @@ -0,0 +1,140 @@ +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// Splits 0 ≤ a < q into a₀ and a₁ with a = a₁*α + a₀ with -α/2 < a₀ ≤ α/2, +// except for when we would have a₁ = (q-1)/α in which case a₁=0 is taken +// and -α/2 ≤ a₀ < 0. Returns a₀ + q. Note 0 ≤ a₁ < (q-1)/α. +// Recall α = 2γ₂. +func decompose(a uint32) (a0plusQ, a1 uint32) { + // a₁ = ⌈a / 128⌉ + a1 = (a + 127) >> 7 + + if Alpha == 523776 { + // 1025/2²² is close enough to 1/4092 so that a₁ + // becomes a/α rounded down. + a1 = ((a1*1025 + (1 << 21)) >> 22) + + // For the corner-case a₁ = (q-1)/α = 16, we have to set a₁=0. + a1 &= 15 + } else if Alpha == 190464 { + // 1488/2²⁴ is close enough to 1/1488 so that a₁ + // becomes a/α rounded down. + a1 = ((a1 * 11275) + (1 << 23)) >> 24 + + // For the corner-case a₁ = (q-1)/α = 44, we have to set a₁=0. + a1 ^= uint32(int32(43-a1)>>31) & a1 + } else { + panic("unsupported α") + } + + a0plusQ = a - a1*Alpha + + // In the corner-case, when we set a₁=0, we will incorrectly + // have a₀ > (q-1)/2 and we'll need to subtract q. As we + // return a₀ + q, that comes down to adding q if a₀ < (q-1)/2. + a0plusQ += uint32(int32(a0plusQ-(common.Q-1)/2)>>31) & common.Q + + return +} + +// Assume 0 ≤ r, f < Q with ‖f‖_∞ ≤ α/2. Decompose r as r = r1*α + r0 as +// computed by decompose(). Write r' := r - f (mod Q). Now, decompose +// r'=r-f again as r' = r'1*α + r'0 using decompose(). As f is small, we +// have r'1 = r1 + h, where h ∈ {-1, 0, 1}. makeHint() computes |h| +// given z0 := r0 - f (mod Q) and r1. With |h|, which is called the hint, +// we can reconstruct r1 using only r' = r - f, which is done by useHint(). +// To wit: +// +// useHint( r - f, makeHint( r0 - f, r1 ) ) = r1. +// +// Assumes 0 ≤ z0 < Q. +func makeHint(z0, r1 uint32) uint32 { + // If -α/2 < r0 - f ≤ α/2, then r1*α + r0 - f is a valid decomposition of r' + // with the restrictions of decompose() and so r'1 = r1. So the hint + // should be 0. This is covered by the first two inequalities. + // There is one other case: if r0 - f = -α/2, then r1*α + r0 - f is also + // a valid decomposition if r1 = 0. In the other cases a one is carried + // and the hint should be 1. + if z0 <= Gamma2 || z0 > common.Q-Gamma2 || (z0 == common.Q-Gamma2 && r1 == 0) { + return 0 + } + return 1 +} + +// Uses the hint created by makeHint() to reconstruct r1 from r'=r-f; see +// documentation of makeHint() for context. +// Assumes 0 ≤ r' < Q. +func useHint(rp uint32, hint uint32) uint32 { + rp0plusQ, rp1 := decompose(rp) + if hint == 0 { + return rp1 + } + if rp0plusQ > common.Q { + return (rp1 + 1) & 15 + } + return (rp1 - 1) & 15 +} + +// Sets p to the hint polynomial for p0 the modified low bits and p1 +// the unmodified high bits --- see makeHint(). +// +// Returns the number of ones in the hint polynomial. +func PolyMakeHint(p, p0, p1 *common.Poly) (pop uint32) { + for i := 0; i < common.N; i++ { + h := makeHint(p0[i], p1[i]) + pop += h + p[i] = h + } + return +} + +// Computes corrections to the high bits of the polynomial q according +// to the hints in h and sets p to the corrected high bits. Returns p. +func PolyUseHint(p, q, hint *common.Poly) { + var q0PlusQ common.Poly + + // See useHint() and makeHint() for an explanation. We reimplement it + // here so that we can call Poly.Decompose(), which might be way faster + // than calling decompose() in a loop (for instance when having AVX2.) + + PolyDecompose(q, &q0PlusQ, p) + + for i := 0; i < common.N; i++ { + if hint[i] == 0 { + continue + } + if Gamma2 == 261888 { + if q0PlusQ[i] > common.Q { + p[i] = (p[i] + 1) & 15 + } else { + p[i] = (p[i] - 1) & 15 + } + } else if Gamma2 == 95232 { + if q0PlusQ[i] > common.Q { + if p[i] == 43 { + p[i] = 0 + } else { + p[i]++ + } + } else { + if p[i] == 0 { + p[i] = 43 + } else { + p[i]-- + } + } + } else { + panic("unsupported γ₂") + } + } +} + +// Splits each of the coefficients of p using decompose. +func PolyDecompose(p, p0PlusQ, p1 *common.Poly) { + for i := 0; i < common.N; i++ { + p0PlusQ[i], p1[i] = decompose(p[i]) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/sample.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/sample.go new file mode 100644 index 00000000000..256ec731f94 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/sample.go @@ -0,0 +1,368 @@ +package internal + +import ( + "encoding/binary" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/sign/dilithium/internal/common" + "github.com/cloudflare/circl/simd/keccakf1600" +) + +// DeriveX4Available indicates whether the system supports the quick fourway +// sampling variants like PolyDeriveUniformX4. +var DeriveX4Available = keccakf1600.IsEnabledX4() && !UseAES + +// For each i, sample ps[i] uniformly from the given seed and nonces[i]. +// ps[i] may be nil and is ignored in that case. +// +// Can only be called when DeriveX4Available is true. +func PolyDeriveUniformX4(ps [4]*common.Poly, seed *[32]byte, nonces [4]uint16) { + var perm keccakf1600.StateX4 + state := perm.Initialize(false) + + // Absorb the seed in the four states + for i := 0; i < 4; i++ { + v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)]) + for j := 0; j < 4; j++ { + state[i*4+j] = v + } + } + + // Absorb the nonces, the SHAKE128 domain separator (0b1111), the + // start of the padding (0b...001) and the end of the padding 0b100... + // Recall that the rate of SHAKE128 is 168 --- i.e. 21 uint64s. + for j := 0; j < 4; j++ { + state[4*4+j] = uint64(nonces[j]) | (0x1f << 16) + state[20*4+j] = 0x80 << 56 + } + + var idx [4]int // indices into ps + for j := 0; j < 4; j++ { + if ps[j] == nil { + idx[j] = common.N // mark nil polynomial as completed + } + } + + done := false + for !done { + // Applies KeccaK-f[1600] to state to get the next 21 uint64s of each + // of the four SHAKE128 streams. + perm.Permute() + + done = true + + PolyLoop: + for j := 0; j < 4; j++ { + if idx[j] == common.N { + continue + } + for i := 0; i < 7; i++ { + var t [8]uint32 + t[0] = uint32(state[i*3*4+j] & 0x7fffff) + t[1] = uint32((state[i*3*4+j] >> 24) & 0x7fffff) + t[2] = uint32((state[i*3*4+j] >> 48) | + ((state[(i*3+1)*4+j] & 0x7f) << 16)) + t[3] = uint32((state[(i*3+1)*4+j] >> 8) & 0x7fffff) + t[4] = uint32((state[(i*3+1)*4+j] >> 32) & 0x7fffff) + t[5] = uint32((state[(i*3+1)*4+j] >> 56) | + ((state[(i*3+2)*4+j] & 0x7fff) << 8)) + t[6] = uint32((state[(i*3+2)*4+j] >> 16) & 0x7fffff) + t[7] = uint32((state[(i*3+2)*4+j] >> 40) & 0x7fffff) + + for k := 0; k < 8; k++ { + if t[k] < common.Q { + ps[j][idx[j]] = t[k] + idx[j]++ + if idx[j] == common.N { + continue PolyLoop + } + } + } + } + done = false + } + } +} + +// Sample p uniformly from the given seed and nonce. +// +// p will be normalized. +func PolyDeriveUniform(p *common.Poly, seed *[32]byte, nonce uint16) { + var i, length int + var buf [12 * 16]byte // fits 168B SHAKE-128 rate and 12 16B AES blocks + + if UseAES { + length = 12 * 16 + } else { + length = 168 + } + + sample := func() { + // Note that 3 divides into 168 and 12*16, so we use up buf completely. + for j := 0; j < length && i < common.N; j += 3 { + t := (uint32(buf[j]) | (uint32(buf[j+1]) << 8) | + (uint32(buf[j+2]) << 16)) & 0x7fffff + + // We use rejection sampling + if t < common.Q { + p[i] = t + i++ + } + } + } + + if UseAES { + h := common.NewAesStream128(seed, nonce) + + for i < common.N { + h.SqueezeInto(buf[:length]) + sample() + } + } else { + var iv [32 + 2]byte // 32 byte seed + uint16 nonce + h := sha3.NewShake128() + copy(iv[:32], seed[:]) + iv[32] = uint8(nonce) + iv[33] = uint8(nonce >> 8) + _, _ = h.Write(iv[:]) + + for i < common.N { + _, _ = h.Read(buf[:168]) + sample() + } + } +} + +// Sample p uniformly with coefficients of norm less than or equal η, +// using the given seed and nonce. +// +// p will not be normalized, but will have coefficients in [q-η,q+η]. +func PolyDeriveUniformLeqEta(p *common.Poly, seed *[64]byte, nonce uint16) { + // Assumes 2 < η < 8. + var i, length int + var buf [9 * 16]byte // fits 136B SHAKE-256 rate and 9 16B AES blocks + + if UseAES { + length = 9 * 16 + } else { + length = 136 + } + + sample := func() { + // We use rejection sampling + for j := 0; j < length && i < common.N; j++ { + t1 := uint32(buf[j]) & 15 + t2 := uint32(buf[j]) >> 4 + if Eta == 2 { // branch is eliminated by compiler + if t1 <= 14 { + t1 -= ((205 * t1) >> 10) * 5 // reduce mod 5 + p[i] = common.Q + Eta - t1 + i++ + } + if t2 <= 14 && i < common.N { + t2 -= ((205 * t2) >> 10) * 5 // reduce mod 5 + p[i] = common.Q + Eta - t2 + i++ + } + } else if Eta == 4 { + if t1 <= 2*Eta { + p[i] = common.Q + Eta - t1 + i++ + } + if t2 <= 2*Eta && i < common.N { + p[i] = common.Q + Eta - t2 + i++ + } + } else { + panic("unsupported η") + } + } + } + + if UseAES { + h := common.NewAesStream256(seed, nonce) + + for i < common.N { + h.SqueezeInto(buf[:length]) + sample() + } + } else { + var iv [64 + 2]byte // 64 byte seed + uint16 nonce + + h := sha3.NewShake256() + copy(iv[:64], seed[:]) + iv[64] = uint8(nonce) + iv[65] = uint8(nonce >> 8) + + // 136 is SHAKE-256 rate + _, _ = h.Write(iv[:]) + + for i < common.N { + _, _ = h.Read(buf[:136]) + sample() + } + } +} + +// Sample v[i] uniformly with coefficients in (-γ₁,…,γ₁] using the +// given seed and nonce+i +// +// p will be normalized. +func VecLDeriveUniformLeGamma1(v *VecL, seed *[64]byte, nonce uint16) { + for i := 0; i < L; i++ { + PolyDeriveUniformLeGamma1(&v[i], seed, nonce+uint16(i)) + } +} + +// Sample p uniformly with coefficients in (-γ₁,…,γK1s] using the +// given seed and nonce. +// +// p will be normalized. +func PolyDeriveUniformLeGamma1(p *common.Poly, seed *[64]byte, nonce uint16) { + var buf [PolyLeGamma1Size]byte + + if UseAES { + h := common.NewAesStream256(seed, nonce) + h.SqueezeInto(buf[:]) + } else { + var iv [66]byte + h := sha3.NewShake256() + copy(iv[:64], seed[:]) + iv[64] = uint8(nonce) + iv[65] = uint8(nonce >> 8) + _, _ = h.Write(iv[:]) + _, _ = h.Read(buf[:]) + } + + PolyUnpackLeGamma1(p, buf[:]) +} + +// For each i, sample ps[i] uniformly with τ non-zero coefficients in {q-1,1} +// using the given seed and w1[i]. ps[i] may be nil and is ignored +// in that case. ps[i] will be normalized. +// +// Can only be called when DeriveX4Available is true. +// +// This function is currently not used (yet). +func PolyDeriveUniformBallX4(ps [4]*common.Poly, seed *[32]byte) { + var perm keccakf1600.StateX4 + state := perm.Initialize(false) + + // Absorb the seed in the four states + for i := 0; i < 4; i++ { + v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)]) + for j := 0; j < 4; j++ { + state[i*4+j] = v + } + } + + // SHAKE256 domain separator and padding + for j := 0; j < 4; j++ { + state[4*4+j] ^= 0x1f + state[16*4+j] ^= 0x80 << 56 + } + perm.Permute() + + var signs [4]uint64 + var idx [4]uint16 // indices into ps + + for j := 0; j < 4; j++ { + if ps[j] != nil { + signs[j] = state[j] + *ps[j] = common.Poly{} // zero ps[j] + idx[j] = common.N - Tau + } else { + idx[j] = common.N // mark as completed + } + } + + stateOffset := 1 + for { + done := true + + PolyLoop: + for j := 0; j < 4; j++ { + if idx[j] == common.N { + continue + } + + for i := stateOffset; i < 17; i++ { + var bs [8]byte + binary.LittleEndian.PutUint64(bs[:], state[4*i+j]) + for k := 0; k < 8; k++ { + b := uint16(bs[k]) + + if b > idx[j] { + continue + } + + ps[j][idx[j]] = ps[j][b] + ps[j][b] = 1 + // Takes least significant bit of signs and uses it for the sign. + // Note 1 ^ (1 | (Q-1)) = Q-1. + ps[j][b] ^= uint32((-(signs[j] & 1)) & (1 | (common.Q - 1))) + signs[j] >>= 1 + + idx[j]++ + if idx[j] == common.N { + continue PolyLoop + } + } + } + + done = false + } + + if done { + break + } + + perm.Permute() + stateOffset = 0 + } +} + +// Samples p uniformly with τ non-zero coefficients in {q-1,1}. +// +// The polynomial p will be normalized. +func PolyDeriveUniformBall(p *common.Poly, seed *[32]byte) { + var buf [136]byte // SHAKE-256 rate is 136 + + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Read(buf[:]) + + // Essentially we generate a sequence of τ ones or minus ones, + // prepend 196 zeroes and shuffle the concatenation using the + // usual algorithm (Fisher--Yates.) + signs := binary.LittleEndian.Uint64(buf[:]) + bufOff := 8 // offset into buf + + *p = common.Poly{} // zero p + for i := uint16(common.N - Tau); i < common.N; i++ { + var b uint16 + + // Find location of where to move the new coefficient to using + // rejection sampling. + for { + if bufOff >= 136 { + _, _ = h.Read(buf[:]) + bufOff = 0 + } + + b = uint16(buf[bufOff]) + bufOff++ + + if b <= i { + break + } + } + + p[i] = p[b] + p[b] = 1 + // Takes least significant bit of signs and uses it for the sign. + // Note 1 ^ (1 | (Q-1)) = Q-1. + p[b] ^= uint32((-(signs & 1)) & (1 | (common.Q - 1))) + signs >>= 1 + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/vec.go b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/vec.go new file mode 100644 index 00000000000..1a5fe4ca5e7 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/vec.go @@ -0,0 +1,279 @@ +package internal + +import ( + "github.com/cloudflare/circl/sign/dilithium/internal/common" +) + +// A vector of L polynomials. +type VecL [L]common.Poly + +// A vector of K polynomials. +type VecK [K]common.Poly + +// Normalize the polynomials in this vector. +func (v *VecL) Normalize() { + for i := 0; i < L; i++ { + v[i].Normalize() + } +} + +// Normalize the polynomials in this vector assuming their coefficients +// are already bounded by 2q. +func (v *VecL) NormalizeAssumingLe2Q() { + for i := 0; i < L; i++ { + v[i].NormalizeAssumingLe2Q() + } +} + +// Sets v to w + u. Does not normalize. +func (v *VecL) Add(w, u *VecL) { + for i := 0; i < L; i++ { + v[i].Add(&w[i], &u[i]) + } +} + +// Applies NTT componentwise. See Poly.NTT() for details. +func (v *VecL) NTT() { + for i := 0; i < L; i++ { + v[i].NTT() + } +} + +// Checks whether any of the coefficients exceeds the given bound in supnorm +// +// Requires the vector to be normalized. +func (v *VecL) Exceeds(bound uint32) bool { + for i := 0; i < L; i++ { + if v[i].Exceeds(bound) { + return true + } + } + return false +} + +// Applies Poly.Power2Round componentwise. +// +// Requires the vector to be normalized. +func (v *VecL) Power2Round(v0PlusQ, v1 *VecL) { + for i := 0; i < L; i++ { + v[i].Power2Round(&v0PlusQ[i], &v1[i]) + } +} + +// Applies Poly.Decompose componentwise. +// +// Requires the vector to be normalized. +func (v *VecL) Decompose(v0PlusQ, v1 *VecL) { + for i := 0; i < L; i++ { + PolyDecompose(&v[i], &v0PlusQ[i], &v1[i]) + } +} + +// Sequentially packs each polynomial using Poly.PackLeqEta(). +func (v *VecL) PackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyPackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Sets v to the polynomials packed in buf using VecL.PackLeqEta(). +func (v *VecL) UnpackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyUnpackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Sequentially packs each polynomial using PolyPackLeGamma1(). +func (v *VecL) PackLeGamma1(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyPackLeGamma1(&v[i], buf[offset:]) + offset += PolyLeGamma1Size + } +} + +// Sets v to the polynomials packed in buf using VecL.PackLeGamma1(). +func (v *VecL) UnpackLeGamma1(buf []byte) { + offset := 0 + for i := 0; i < L; i++ { + PolyUnpackLeGamma1(&v[i], buf[offset:]) + offset += PolyLeGamma1Size + } +} + +// Normalize the polynomials in this vector. +func (v *VecK) Normalize() { + for i := 0; i < K; i++ { + v[i].Normalize() + } +} + +// Normalize the polynomials in this vector assuming their coefficients +// are already bounded by 2q. +func (v *VecK) NormalizeAssumingLe2Q() { + for i := 0; i < K; i++ { + v[i].NormalizeAssumingLe2Q() + } +} + +// Sets v to w + u. Does not normalize. +func (v *VecK) Add(w, u *VecK) { + for i := 0; i < K; i++ { + v[i].Add(&w[i], &u[i]) + } +} + +// Checks whether any of the coefficients exceeds the given bound in supnorm +// +// Requires the vector to be normalized. +func (v *VecK) Exceeds(bound uint32) bool { + for i := 0; i < K; i++ { + if v[i].Exceeds(bound) { + return true + } + } + return false +} + +// Applies Poly.Power2Round componentwise. +// +// Requires the vector to be normalized. +func (v *VecK) Power2Round(v0PlusQ, v1 *VecK) { + for i := 0; i < K; i++ { + v[i].Power2Round(&v0PlusQ[i], &v1[i]) + } +} + +// Applies Poly.Decompose componentwise. +// +// Requires the vector to be normalized. +func (v *VecK) Decompose(v0PlusQ, v1 *VecK) { + for i := 0; i < K; i++ { + PolyDecompose(&v[i], &v0PlusQ[i], &v1[i]) + } +} + +// Sets v to the hint vector for v0 the modified low bits and v1 +// the unmodified high bits --- see makeHint(). +// +// Returns the number of ones in the hint vector. +func (v *VecK) MakeHint(v0, v1 *VecK) (pop uint32) { + for i := 0; i < K; i++ { + pop += PolyMakeHint(&v[i], &v0[i], &v1[i]) + } + return +} + +// Computes corrections to the high bits of the polynomials in the vector +// w using the hints in h and sets v to the corrected high bits. Returns v. +// See useHint(). +func (v *VecK) UseHint(q, hint *VecK) *VecK { + for i := 0; i < K; i++ { + PolyUseHint(&v[i], &q[i], &hint[i]) + } + return v +} + +// Sequentially packs each polynomial using Poly.PackT1(). +func (v *VecK) PackT1(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].PackT1(buf[offset:]) + offset += common.PolyT1Size + } +} + +// Sets v to the vector packed into buf by PackT1(). +func (v *VecK) UnpackT1(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].UnpackT1(buf[offset:]) + offset += common.PolyT1Size + } +} + +// Sequentially packs each polynomial using Poly.PackT0(). +func (v *VecK) PackT0(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].PackT0(buf[offset:]) + offset += common.PolyT0Size + } +} + +// Sets v to the vector packed into buf by PackT0(). +func (v *VecK) UnpackT0(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + v[i].UnpackT0(buf[offset:]) + offset += common.PolyT0Size + } +} + +// Sequentially packs each polynomial using Poly.PackLeqEta(). +func (v *VecK) PackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + PolyPackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Sets v to the polynomials packed in buf using VecK.PackLeqEta(). +func (v *VecK) UnpackLeqEta(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + PolyUnpackLeqEta(&v[i], buf[offset:]) + offset += PolyLeqEtaSize + } +} + +// Applies NTT componentwise. See Poly.NTT() for details. +func (v *VecK) NTT() { + for i := 0; i < K; i++ { + v[i].NTT() + } +} + +// Sequentially packs each polynomial using PolyPackW1(). +func (v *VecK) PackW1(buf []byte) { + offset := 0 + for i := 0; i < K; i++ { + PolyPackW1(&v[i], buf[offset:]) + offset += PolyW1Size + } +} + +// Sets v to a - b. +// +// Warning: assumes coefficients of the polynomials of b are less than 2q. +func (v *VecK) Sub(a, b *VecK) { + for i := 0; i < K; i++ { + v[i].Sub(&a[i], &b[i]) + } +} + +// Sets v to 2ᵈ w without reducing. +func (v *VecK) MulBy2toD(w *VecK) { + for i := 0; i < K; i++ { + v[i].MulBy2toD(&w[i]) + } +} + +// Applies InvNTT componentwise. See Poly.InvNTT() for details. +func (v *VecK) InvNTT() { + for i := 0; i < K; i++ { + v[i].InvNTT() + } +} + +// Applies Poly.ReduceLe2Q() componentwise. +func (v *VecK) ReduceLe2Q() { + for i := 0; i < K; i++ { + v[i].ReduceLe2Q() + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go new file mode 100644 index 00000000000..2c73c26fb1f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go @@ -0,0 +1,453 @@ +// Package ed25519 implements Ed25519 signature scheme as described in RFC-8032. +// +// This package provides optimized implementations of the three signature +// variants and maintaining closer compatibility with crypto/ed25519. +// +// | Scheme Name | Sign Function | Verification | Context | +// |-------------|-------------------|---------------|-------------------| +// | Ed25519 | Sign | Verify | None | +// | Ed25519Ph | SignPh | VerifyPh | Yes, can be empty | +// | Ed25519Ctx | SignWithCtx | VerifyWithCtx | Yes, non-empty | +// | All above | (PrivateKey).Sign | VerifyAny | As above | +// +// Specific functions for sign and verify are defined. A generic signing +// function for all schemes is available through the crypto.Signer interface, +// which is implemented by the PrivateKey type. A correspond all-in-one +// verification method is provided by the VerifyAny function. +// +// Signing with Ed25519Ph or Ed25519Ctx requires a context string for domain +// separation. This parameter is passed using a SignerOptions struct defined +// in this package. While Ed25519Ph accepts an empty context, Ed25519Ctx +// enforces non-empty context strings. +// +// # Compatibility with crypto.ed25519 +// +// These functions are compatible with the “Ed25519” function defined in +// RFC-8032. However, unlike RFC 8032's formulation, this package's private +// key representation includes a public key suffix to make multiple signing +// operations with the same key more efficient. This package refers to the +// RFC-8032 private key as the “seed”. +// +// References +// +// - RFC-8032: https://rfc-editor.org/rfc/rfc8032.txt +// - Ed25519: https://ed25519.cr.yp.to/ +// - EdDSA: High-speed high-security signatures. https://doi.org/10.1007/s13389-012-0027-1 +package ed25519 + +import ( + "bytes" + "crypto" + cryptoRand "crypto/rand" + "crypto/sha512" + "crypto/subtle" + "errors" + "fmt" + "io" + "strconv" + + "github.com/cloudflare/circl/sign" +) + +const ( + // ContextMaxSize is the maximum length (in bytes) allowed for context. + ContextMaxSize = 255 + // PublicKeySize is the size, in bytes, of public keys as used in this package. + PublicKeySize = 32 + // PrivateKeySize is the size, in bytes, of private keys as used in this package. + PrivateKeySize = 64 + // SignatureSize is the size, in bytes, of signatures generated and verified by this package. + SignatureSize = 64 + // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + SeedSize = 32 +) + +const ( + paramB = 256 / 8 // Size of keys in bytes. +) + +// SignerOptions implements crypto.SignerOpts and augments with parameters +// that are specific to the Ed25519 signature schemes. +type SignerOptions struct { + // Hash must be crypto.Hash(0) for Ed25519/Ed25519ctx, or crypto.SHA512 + // for Ed25519ph. + crypto.Hash + + // Context is an optional domain separation string for Ed25519ph and a + // must for Ed25519ctx. Its length must be less or equal than 255 bytes. + Context string + + // Scheme is an identifier for choosing a signature scheme. The zero value + // is ED25519. + Scheme SchemeID +} + +// SchemeID is an identifier for each signature scheme. +type SchemeID uint + +const ( + ED25519 SchemeID = iota + ED25519Ph + ED25519Ctx +) + +// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. +type PrivateKey []byte + +// Equal reports whether priv and x have the same value. +func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { + xx, ok := x.(PrivateKey) + return ok && subtle.ConstantTimeCompare(priv, xx) == 1 +} + +// Public returns the PublicKey corresponding to priv. +func (priv PrivateKey) Public() crypto.PublicKey { + publicKey := make(PublicKey, PublicKeySize) + copy(publicKey, priv[SeedSize:]) + return publicKey +} + +// Seed returns the private key seed corresponding to priv. It is provided for +// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds +// in this package. +func (priv PrivateKey) Seed() []byte { + seed := make([]byte, SeedSize) + copy(seed, priv[:SeedSize]) + return seed +} + +func (priv PrivateKey) Scheme() sign.Scheme { return sch } + +func (pub PublicKey) Scheme() sign.Scheme { return sch } + +func (priv PrivateKey) MarshalBinary() (data []byte, err error) { + privateKey := make(PrivateKey, PrivateKeySize) + copy(privateKey, priv) + return privateKey, nil +} + +func (pub PublicKey) MarshalBinary() (data []byte, err error) { + publicKey := make(PublicKey, PublicKeySize) + copy(publicKey, pub) + return publicKey, nil +} + +// Equal reports whether pub and x have the same value. +func (pub PublicKey) Equal(x crypto.PublicKey) bool { + xx, ok := x.(PublicKey) + return ok && bytes.Equal(pub, xx) +} + +// Sign creates a signature of a message with priv key. +// This function is compatible with crypto.ed25519 and also supports the +// three signature variants defined in RFC-8032, namely Ed25519 (or pure +// EdDSA), Ed25519Ph, and Ed25519Ctx. +// The opts.HashFunc() must return zero to specify either Ed25519 or Ed25519Ctx +// variant. This can be achieved by passing crypto.Hash(0) as the value for +// opts. +// The opts.HashFunc() must return SHA512 to specify the Ed25519Ph variant. +// This can be achieved by passing crypto.SHA512 as the value for opts. +// Use a SignerOptions struct (defined in this package) to pass a context +// string for signing. +func (priv PrivateKey) Sign( + rand io.Reader, + message []byte, + opts crypto.SignerOpts, +) (signature []byte, err error) { + var ctx string + var scheme SchemeID + if o, ok := opts.(SignerOptions); ok { + ctx = o.Context + scheme = o.Scheme + } + + switch true { + case scheme == ED25519 && opts.HashFunc() == crypto.Hash(0): + return Sign(priv, message), nil + case scheme == ED25519Ph && opts.HashFunc() == crypto.SHA512: + return SignPh(priv, message, ctx), nil + case scheme == ED25519Ctx && opts.HashFunc() == crypto.Hash(0) && len(ctx) > 0: + return SignWithCtx(priv, message, ctx), nil + default: + return nil, errors.New("ed25519: bad hash algorithm") + } +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { + if rand == nil { + rand = cryptoRand.Reader + } + + seed := make([]byte, SeedSize) + if _, err := io.ReadFull(rand, seed); err != nil { + return nil, nil, err + } + + privateKey := NewKeyFromSeed(seed) + publicKey := make(PublicKey, PublicKeySize) + copy(publicKey, privateKey[SeedSize:]) + + return publicKey, privateKey, nil +} + +// NewKeyFromSeed calculates a private key from a seed. It will panic if +// len(seed) is not SeedSize. This function is provided for interoperability +// with RFC 8032. RFC 8032's private keys correspond to seeds in this +// package. +func NewKeyFromSeed(seed []byte) PrivateKey { + privateKey := make(PrivateKey, PrivateKeySize) + newKeyFromSeed(privateKey, seed) + return privateKey +} + +func newKeyFromSeed(privateKey, seed []byte) { + if l := len(seed); l != SeedSize { + panic("ed25519: bad seed length: " + strconv.Itoa(l)) + } + var P pointR1 + k := sha512.Sum512(seed) + clamp(k[:]) + reduceModOrder(k[:paramB], false) + P.fixedMult(k[:paramB]) + copy(privateKey[:SeedSize], seed) + _ = P.ToBytes(privateKey[SeedSize:]) +} + +func signAll(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) { + if l := len(privateKey); l != PrivateKeySize { + panic("ed25519: bad private key length: " + strconv.Itoa(l)) + } + + H := sha512.New() + var PHM []byte + + if preHash { + _, _ = H.Write(message) + PHM = H.Sum(nil) + H.Reset() + } else { + PHM = message + } + + // 1. Hash the 32-byte private key using SHA-512. + _, _ = H.Write(privateKey[:SeedSize]) + h := H.Sum(nil) + clamp(h[:]) + prefix, s := h[paramB:], h[:paramB] + + // 2. Compute SHA-512(dom2(F, C) || prefix || PH(M)) + H.Reset() + + writeDom(H, ctx, preHash) + + _, _ = H.Write(prefix) + _, _ = H.Write(PHM) + r := H.Sum(nil) + reduceModOrder(r[:], true) + + // 3. Compute the point [r]B. + var P pointR1 + P.fixedMult(r[:paramB]) + R := (&[paramB]byte{})[:] + if err := P.ToBytes(R); err != nil { + panic(err) + } + + // 4. Compute SHA512(dom2(F, C) || R || A || PH(M)). + H.Reset() + + writeDom(H, ctx, preHash) + + _, _ = H.Write(R) + _, _ = H.Write(privateKey[SeedSize:]) + _, _ = H.Write(PHM) + hRAM := H.Sum(nil) + + reduceModOrder(hRAM[:], true) + + // 5. Compute S = (r + k * s) mod order. + S := (&[paramB]byte{})[:] + calculateS(S, r[:paramB], hRAM[:paramB], s) + + // 6. The signature is the concatenation of R and S. + copy(signature[:paramB], R[:]) + copy(signature[paramB:], S[:]) +} + +// Sign signs the message with privateKey and returns a signature. +// This function supports the signature variant defined in RFC-8032: Ed25519, +// also known as the pure version of EdDSA. +// It will panic if len(privateKey) is not PrivateKeySize. +func Sign(privateKey PrivateKey, message []byte) []byte { + signature := make([]byte, SignatureSize) + signAll(signature, privateKey, message, []byte(""), false) + return signature +} + +// SignPh creates a signature of a message with private key and context. +// This function supports the signature variant defined in RFC-8032: Ed25519ph, +// meaning it internally hashes the message using SHA-512, and optionally +// accepts a context string. +// It will panic if len(privateKey) is not PrivateKeySize. +// Context could be passed to this function, which length should be no more than +// ContextMaxSize=255. It can be empty. +func SignPh(privateKey PrivateKey, message []byte, ctx string) []byte { + if len(ctx) > ContextMaxSize { + panic(fmt.Errorf("ed25519: bad context length: %v", len(ctx))) + } + + signature := make([]byte, SignatureSize) + signAll(signature, privateKey, message, []byte(ctx), true) + return signature +} + +// SignWithCtx creates a signature of a message with private key and context. +// This function supports the signature variant defined in RFC-8032: Ed25519ctx, +// meaning it accepts a non-empty context string. +// It will panic if len(privateKey) is not PrivateKeySize. +// Context must be passed to this function, which length should be no more than +// ContextMaxSize=255 and cannot be empty. +func SignWithCtx(privateKey PrivateKey, message []byte, ctx string) []byte { + if len(ctx) == 0 || len(ctx) > ContextMaxSize { + panic(fmt.Errorf("ed25519: bad context length: %v > %v", len(ctx), ContextMaxSize)) + } + + signature := make([]byte, SignatureSize) + signAll(signature, privateKey, message, []byte(ctx), false) + return signature +} + +func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool { + if len(public) != PublicKeySize || + len(signature) != SignatureSize || + !isLessThanOrder(signature[paramB:]) { + return false + } + + var P pointR1 + if ok := P.FromBytes(public); !ok { + return false + } + + H := sha512.New() + var PHM []byte + + if preHash { + _, _ = H.Write(message) + PHM = H.Sum(nil) + H.Reset() + } else { + PHM = message + } + + R := signature[:paramB] + + writeDom(H, ctx, preHash) + + _, _ = H.Write(R) + _, _ = H.Write(public) + _, _ = H.Write(PHM) + hRAM := H.Sum(nil) + reduceModOrder(hRAM[:], true) + + var Q pointR1 + encR := (&[paramB]byte{})[:] + P.neg() + Q.doubleMult(&P, signature[paramB:], hRAM[:paramB]) + _ = Q.ToBytes(encR) + return bytes.Equal(R, encR) +} + +// VerifyAny returns true if the signature is valid. Failure cases are invalid +// signature, or when the public key cannot be decoded. +// This function supports all the three signature variants defined in RFC-8032, +// namely Ed25519 (or pure EdDSA), Ed25519Ph, and Ed25519Ctx. +// The opts.HashFunc() must return zero to specify either Ed25519 or Ed25519Ctx +// variant. This can be achieved by passing crypto.Hash(0) as the value for opts. +// The opts.HashFunc() must return SHA512 to specify the Ed25519Ph variant. +// This can be achieved by passing crypto.SHA512 as the value for opts. +// Use a SignerOptions struct to pass a context string for signing. +func VerifyAny(public PublicKey, message, signature []byte, opts crypto.SignerOpts) bool { + var ctx string + var scheme SchemeID + if o, ok := opts.(SignerOptions); ok { + ctx = o.Context + scheme = o.Scheme + } + + switch true { + case scheme == ED25519 && opts.HashFunc() == crypto.Hash(0): + return Verify(public, message, signature) + case scheme == ED25519Ph && opts.HashFunc() == crypto.SHA512: + return VerifyPh(public, message, signature, ctx) + case scheme == ED25519Ctx && opts.HashFunc() == crypto.Hash(0) && len(ctx) > 0: + return VerifyWithCtx(public, message, signature, ctx) + default: + return false + } +} + +// Verify returns true if the signature is valid. Failure cases are invalid +// signature, or when the public key cannot be decoded. +// This function supports the signature variant defined in RFC-8032: Ed25519, +// also known as the pure version of EdDSA. +func Verify(public PublicKey, message, signature []byte) bool { + return verify(public, message, signature, []byte(""), false) +} + +// VerifyPh returns true if the signature is valid. Failure cases are invalid +// signature, or when the public key cannot be decoded. +// This function supports the signature variant defined in RFC-8032: Ed25519ph, +// meaning it internally hashes the message using SHA-512. +// Context could be passed to this function, which length should be no more than +// 255. It can be empty. +func VerifyPh(public PublicKey, message, signature []byte, ctx string) bool { + return verify(public, message, signature, []byte(ctx), true) +} + +// VerifyWithCtx returns true if the signature is valid. Failure cases are invalid +// signature, or when the public key cannot be decoded, or when context is +// not provided. +// This function supports the signature variant defined in RFC-8032: Ed25519ctx, +// meaning it does not handle prehashed messages. Non-empty context string must be +// provided, and must not be more than 255 of length. +func VerifyWithCtx(public PublicKey, message, signature []byte, ctx string) bool { + if len(ctx) == 0 || len(ctx) > ContextMaxSize { + return false + } + + return verify(public, message, signature, []byte(ctx), false) +} + +func clamp(k []byte) { + k[0] &= 248 + k[paramB-1] = (k[paramB-1] & 127) | 64 +} + +// isLessThanOrder returns true if 0 <= x < order. +func isLessThanOrder(x []byte) bool { + i := len(order) - 1 + for i > 0 && x[i] == order[i] { + i-- + } + return x[i] < order[i] +} + +func writeDom(h io.Writer, ctx []byte, preHash bool) { + dom2 := "SigEd25519 no Ed25519 collisions" + + if len(ctx) > 0 { + _, _ = h.Write([]byte(dom2)) + if preHash { + _, _ = h.Write([]byte{byte(0x01), byte(len(ctx))}) + } else { + _, _ = h.Write([]byte{byte(0x00), byte(len(ctx))}) + } + _, _ = h.Write(ctx) + } else if preHash { + _, _ = h.Write([]byte(dom2)) + _, _ = h.Write([]byte{0x01, 0x00}) + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/modular.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/modular.go new file mode 100644 index 00000000000..10efafdcafb --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/modular.go @@ -0,0 +1,175 @@ +package ed25519 + +import ( + "encoding/binary" + "math/bits" +) + +var order = [paramB]byte{ + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +} + +// isLessThan returns true if 0 <= x < y, and assumes that slices have the same length. +func isLessThan(x, y []byte) bool { + i := len(x) - 1 + for i > 0 && x[i] == y[i] { + i-- + } + return x[i] < y[i] +} + +// reduceModOrder calculates k = k mod order of the curve. +func reduceModOrder(k []byte, is512Bit bool) { + var X [((2 * paramB) * 8) / 64]uint64 + numWords := len(k) >> 3 + for i := 0; i < numWords; i++ { + X[i] = binary.LittleEndian.Uint64(k[i*8 : (i+1)*8]) + } + red512(&X, is512Bit) + for i := 0; i < numWords; i++ { + binary.LittleEndian.PutUint64(k[i*8:(i+1)*8], X[i]) + } +} + +// red512 calculates x = x mod Order of the curve. +func red512(x *[8]uint64, full bool) { + // Implementation of Algs.(14.47)+(14.52) of Handbook of Applied + // Cryptography, by A. Menezes, P. van Oorschot, and S. Vanstone. + const ( + ell0 = uint64(0x5812631a5cf5d3ed) + ell1 = uint64(0x14def9dea2f79cd6) + ell160 = uint64(0x812631a5cf5d3ed0) + ell161 = uint64(0x4def9dea2f79cd65) + ell162 = uint64(0x0000000000000001) + ) + + var c0, c1, c2, c3 uint64 + r0, r1, r2, r3, r4 := x[0], x[1], x[2], x[3], uint64(0) + + if full { + q0, q1, q2, q3 := x[4], x[5], x[6], x[7] + + for i := 0; i < 3; i++ { + h0, s0 := bits.Mul64(q0, ell160) + h1, s1 := bits.Mul64(q1, ell160) + h2, s2 := bits.Mul64(q2, ell160) + h3, s3 := bits.Mul64(q3, ell160) + + s1, c0 = bits.Add64(h0, s1, 0) + s2, c1 = bits.Add64(h1, s2, c0) + s3, c2 = bits.Add64(h2, s3, c1) + s4, _ := bits.Add64(h3, 0, c2) + + h0, l0 := bits.Mul64(q0, ell161) + h1, l1 := bits.Mul64(q1, ell161) + h2, l2 := bits.Mul64(q2, ell161) + h3, l3 := bits.Mul64(q3, ell161) + + l1, c0 = bits.Add64(h0, l1, 0) + l2, c1 = bits.Add64(h1, l2, c0) + l3, c2 = bits.Add64(h2, l3, c1) + l4, _ := bits.Add64(h3, 0, c2) + + s1, c0 = bits.Add64(s1, l0, 0) + s2, c1 = bits.Add64(s2, l1, c0) + s3, c2 = bits.Add64(s3, l2, c1) + s4, c3 = bits.Add64(s4, l3, c2) + s5, s6 := bits.Add64(l4, 0, c3) + + s2, c0 = bits.Add64(s2, q0, 0) + s3, c1 = bits.Add64(s3, q1, c0) + s4, c2 = bits.Add64(s4, q2, c1) + s5, c3 = bits.Add64(s5, q3, c2) + s6, s7 := bits.Add64(s6, 0, c3) + + q := q0 | q1 | q2 | q3 + m := -((q | -q) >> 63) // if q=0 then m=0...0 else m=1..1 + s0 &= m + s1 &= m + s2 &= m + s3 &= m + q0, q1, q2, q3 = s4, s5, s6, s7 + + if (i+1)%2 == 0 { + r0, c0 = bits.Add64(r0, s0, 0) + r1, c1 = bits.Add64(r1, s1, c0) + r2, c2 = bits.Add64(r2, s2, c1) + r3, c3 = bits.Add64(r3, s3, c2) + r4, _ = bits.Add64(r4, 0, c3) + } else { + r0, c0 = bits.Sub64(r0, s0, 0) + r1, c1 = bits.Sub64(r1, s1, c0) + r2, c2 = bits.Sub64(r2, s2, c1) + r3, c3 = bits.Sub64(r3, s3, c2) + r4, _ = bits.Sub64(r4, 0, c3) + } + } + + m := -(r4 >> 63) + r0, c0 = bits.Add64(r0, m&ell160, 0) + r1, c1 = bits.Add64(r1, m&ell161, c0) + r2, c2 = bits.Add64(r2, m&ell162, c1) + r3, c3 = bits.Add64(r3, 0, c2) + r4, _ = bits.Add64(r4, m&1, c3) + x[4], x[5], x[6], x[7] = 0, 0, 0, 0 + } + + q0 := (r4 << 4) | (r3 >> 60) + r3 &= (uint64(1) << 60) - 1 + + h0, s0 := bits.Mul64(ell0, q0) + h1, s1 := bits.Mul64(ell1, q0) + s1, c0 = bits.Add64(h0, s1, 0) + s2, _ := bits.Add64(h1, 0, c0) + + r0, c0 = bits.Sub64(r0, s0, 0) + r1, c1 = bits.Sub64(r1, s1, c0) + r2, c2 = bits.Sub64(r2, s2, c1) + r3, _ = bits.Sub64(r3, 0, c2) + + x[0], x[1], x[2], x[3] = r0, r1, r2, r3 +} + +// calculateS performs s = r+k*a mod Order of the curve. +func calculateS(s, r, k, a []byte) { + K := [4]uint64{ + binary.LittleEndian.Uint64(k[0*8 : 1*8]), + binary.LittleEndian.Uint64(k[1*8 : 2*8]), + binary.LittleEndian.Uint64(k[2*8 : 3*8]), + binary.LittleEndian.Uint64(k[3*8 : 4*8]), + } + S := [8]uint64{ + binary.LittleEndian.Uint64(r[0*8 : 1*8]), + binary.LittleEndian.Uint64(r[1*8 : 2*8]), + binary.LittleEndian.Uint64(r[2*8 : 3*8]), + binary.LittleEndian.Uint64(r[3*8 : 4*8]), + } + var c3 uint64 + for i := range K { + ai := binary.LittleEndian.Uint64(a[i*8 : (i+1)*8]) + + h0, l0 := bits.Mul64(K[0], ai) + h1, l1 := bits.Mul64(K[1], ai) + h2, l2 := bits.Mul64(K[2], ai) + h3, l3 := bits.Mul64(K[3], ai) + + l1, c0 := bits.Add64(h0, l1, 0) + l2, c1 := bits.Add64(h1, l2, c0) + l3, c2 := bits.Add64(h2, l3, c1) + l4, _ := bits.Add64(h3, 0, c2) + + S[i+0], c0 = bits.Add64(S[i+0], l0, 0) + S[i+1], c1 = bits.Add64(S[i+1], l1, c0) + S[i+2], c2 = bits.Add64(S[i+2], l2, c1) + S[i+3], c3 = bits.Add64(S[i+3], l3, c2) + S[i+4], _ = bits.Add64(S[i+4], l4, c3) + } + red512(&S, true) + binary.LittleEndian.PutUint64(s[0*8:1*8], S[0]) + binary.LittleEndian.PutUint64(s[1*8:2*8], S[1]) + binary.LittleEndian.PutUint64(s[2*8:3*8], S[2]) + binary.LittleEndian.PutUint64(s[3*8:4*8], S[3]) +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/mult.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/mult.go new file mode 100644 index 00000000000..3216aae303c --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/mult.go @@ -0,0 +1,180 @@ +package ed25519 + +import ( + "crypto/subtle" + "encoding/binary" + "math/bits" + + "github.com/cloudflare/circl/internal/conv" + "github.com/cloudflare/circl/math" + fp "github.com/cloudflare/circl/math/fp25519" +) + +var paramD = fp.Elt{ + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52, +} + +// mLSBRecoding parameters. +const ( + fxT = 257 + fxV = 2 + fxW = 3 + fx2w1 = 1 << (uint(fxW) - 1) + numWords64 = (paramB * 8 / 64) +) + +// mLSBRecoding is the odd-only modified LSB-set. +// +// Reference: +// +// "Efficient and secure algorithms for GLV-based scalar multiplication and +// their implementation on GLV–GLS curves" by (Faz-Hernandez et al.) +// http://doi.org/10.1007/s13389-014-0085-7. +func mLSBRecoding(L []int8, k []byte) { + const ee = (fxT + fxW*fxV - 1) / (fxW * fxV) + const dd = ee * fxV + const ll = dd * fxW + if len(L) == (ll + 1) { + var m [numWords64 + 1]uint64 + for i := 0; i < numWords64; i++ { + m[i] = binary.LittleEndian.Uint64(k[8*i : 8*i+8]) + } + condAddOrderN(&m) + L[dd-1] = 1 + for i := 0; i < dd-1; i++ { + kip1 := (m[(i+1)/64] >> (uint(i+1) % 64)) & 0x1 + L[i] = int8(kip1<<1) - 1 + } + { // right-shift by d + right := uint(dd % 64) + left := uint(64) - right + lim := ((numWords64+1)*64 - dd) / 64 + j := dd / 64 + for i := 0; i < lim; i++ { + m[i] = (m[i+j] >> right) | (m[i+j+1] << left) + } + m[lim] = m[lim+j] >> right + } + for i := dd; i < ll; i++ { + L[i] = L[i%dd] * int8(m[0]&0x1) + div2subY(m[:], int64(L[i]>>1), numWords64) + } + L[ll] = int8(m[0]) + } +} + +// absolute returns always a positive value. +func absolute(x int32) int32 { + mask := x >> 31 + return (x + mask) ^ mask +} + +// condAddOrderN updates x = x+order if x is even, otherwise x remains unchanged. +func condAddOrderN(x *[numWords64 + 1]uint64) { + isOdd := (x[0] & 0x1) - 1 + c := uint64(0) + for i := 0; i < numWords64; i++ { + orderWord := binary.LittleEndian.Uint64(order[8*i : 8*i+8]) + o := isOdd & orderWord + x0, c0 := bits.Add64(x[i], o, c) + x[i] = x0 + c = c0 + } + x[numWords64], _ = bits.Add64(x[numWords64], 0, c) +} + +// div2subY update x = (x/2) - y. +func div2subY(x []uint64, y int64, l int) { + s := uint64(y >> 63) + for i := 0; i < l-1; i++ { + x[i] = (x[i] >> 1) | (x[i+1] << 63) + } + x[l-1] = (x[l-1] >> 1) + + b := uint64(0) + x0, b0 := bits.Sub64(x[0], uint64(y), b) + x[0] = x0 + b = b0 + for i := 1; i < l-1; i++ { + x0, b0 := bits.Sub64(x[i], s, b) + x[i] = x0 + b = b0 + } + x[l-1], _ = bits.Sub64(x[l-1], s, b) +} + +func (P *pointR1) fixedMult(scalar []byte) { + if len(scalar) != paramB { + panic("wrong scalar size") + } + const ee = (fxT + fxW*fxV - 1) / (fxW * fxV) + const dd = ee * fxV + const ll = dd * fxW + + L := make([]int8, ll+1) + mLSBRecoding(L[:], scalar) + S := &pointR3{} + P.SetIdentity() + for ii := ee - 1; ii >= 0; ii-- { + P.double() + for j := 0; j < fxV; j++ { + dig := L[fxW*dd-j*ee+ii-ee] + for i := (fxW-1)*dd - j*ee + ii - ee; i >= (2*dd - j*ee + ii - ee); i = i - dd { + dig = 2*dig + L[i] + } + idx := absolute(int32(dig)) + sig := L[dd-j*ee+ii-ee] + Tabj := &tabSign[fxV-j-1] + for k := 0; k < fx2w1; k++ { + S.cmov(&Tabj[k], subtle.ConstantTimeEq(int32(k), idx)) + } + S.cneg(subtle.ConstantTimeEq(int32(sig), -1)) + P.mixAdd(S) + } + } +} + +const ( + omegaFix = 7 + omegaVar = 5 +) + +// doubleMult returns P=mG+nQ. +func (P *pointR1) doubleMult(Q *pointR1, m, n []byte) { + nafFix := math.OmegaNAF(conv.BytesLe2BigInt(m), omegaFix) + nafVar := math.OmegaNAF(conv.BytesLe2BigInt(n), omegaVar) + + if len(nafFix) > len(nafVar) { + nafVar = append(nafVar, make([]int32, len(nafFix)-len(nafVar))...) + } else if len(nafFix) < len(nafVar) { + nafFix = append(nafFix, make([]int32, len(nafVar)-len(nafFix))...) + } + + var TabQ [1 << (omegaVar - 2)]pointR2 + Q.oddMultiples(TabQ[:]) + P.SetIdentity() + for i := len(nafFix) - 1; i >= 0; i-- { + P.double() + // Generator point + if nafFix[i] != 0 { + idxM := absolute(nafFix[i]) >> 1 + R := tabVerif[idxM] + if nafFix[i] < 0 { + R.neg() + } + P.mixAdd(&R) + } + // Variable input point + if nafVar[i] != 0 { + idxN := absolute(nafVar[i]) >> 1 + S := TabQ[idxN] + if nafVar[i] < 0 { + S.neg() + } + P.add(&S) + } + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/point.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/point.go new file mode 100644 index 00000000000..374a69503c3 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/point.go @@ -0,0 +1,195 @@ +package ed25519 + +import fp "github.com/cloudflare/circl/math/fp25519" + +type ( + pointR1 struct{ x, y, z, ta, tb fp.Elt } + pointR2 struct { + pointR3 + z2 fp.Elt + } +) +type pointR3 struct{ addYX, subYX, dt2 fp.Elt } + +func (P *pointR1) neg() { + fp.Neg(&P.x, &P.x) + fp.Neg(&P.ta, &P.ta) +} + +func (P *pointR1) SetIdentity() { + P.x = fp.Elt{} + fp.SetOne(&P.y) + fp.SetOne(&P.z) + P.ta = fp.Elt{} + P.tb = fp.Elt{} +} + +func (P *pointR1) toAffine() { + fp.Inv(&P.z, &P.z) + fp.Mul(&P.x, &P.x, &P.z) + fp.Mul(&P.y, &P.y, &P.z) + fp.Modp(&P.x) + fp.Modp(&P.y) + fp.SetOne(&P.z) + P.ta = P.x + P.tb = P.y +} + +func (P *pointR1) ToBytes(k []byte) error { + P.toAffine() + var x [fp.Size]byte + err := fp.ToBytes(k[:fp.Size], &P.y) + if err != nil { + return err + } + err = fp.ToBytes(x[:], &P.x) + if err != nil { + return err + } + b := x[0] & 1 + k[paramB-1] = k[paramB-1] | (b << 7) + return nil +} + +func (P *pointR1) FromBytes(k []byte) bool { + if len(k) != paramB { + panic("wrong size") + } + signX := k[paramB-1] >> 7 + copy(P.y[:], k[:fp.Size]) + P.y[fp.Size-1] &= 0x7F + p := fp.P() + if !isLessThan(P.y[:], p[:]) { + return false + } + + one, u, v := &fp.Elt{}, &fp.Elt{}, &fp.Elt{} + fp.SetOne(one) + fp.Sqr(u, &P.y) // u = y^2 + fp.Mul(v, u, ¶mD) // v = dy^2 + fp.Sub(u, u, one) // u = y^2-1 + fp.Add(v, v, one) // v = dy^2+1 + isQR := fp.InvSqrt(&P.x, u, v) // x = sqrt(u/v) + if !isQR { + return false + } + fp.Modp(&P.x) // x = x mod p + if fp.IsZero(&P.x) && signX == 1 { + return false + } + if signX != (P.x[0] & 1) { + fp.Neg(&P.x, &P.x) + } + P.ta = P.x + P.tb = P.y + fp.SetOne(&P.z) + return true +} + +// double calculates 2P for curves with A=-1. +func (P *pointR1) double() { + Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb + a, b, c, e, f, g, h := Px, Py, Pz, Pta, Px, Py, Ptb + fp.Add(e, Px, Py) // x+y + fp.Sqr(a, Px) // A = x^2 + fp.Sqr(b, Py) // B = y^2 + fp.Sqr(c, Pz) // z^2 + fp.Add(c, c, c) // C = 2*z^2 + fp.Add(h, a, b) // H = A+B + fp.Sqr(e, e) // (x+y)^2 + fp.Sub(e, e, h) // E = (x+y)^2-A-B + fp.Sub(g, b, a) // G = B-A + fp.Sub(f, c, g) // F = C-G + fp.Mul(Pz, f, g) // Z = F * G + fp.Mul(Px, e, f) // X = E * F + fp.Mul(Py, g, h) // Y = G * H, T = E * H +} + +func (P *pointR1) mixAdd(Q *pointR3) { + fp.Add(&P.z, &P.z, &P.z) // D = 2*z1 + P.coreAddition(Q) +} + +func (P *pointR1) add(Q *pointR2) { + fp.Mul(&P.z, &P.z, &Q.z2) // D = 2*z1*z2 + P.coreAddition(&Q.pointR3) +} + +// coreAddition calculates P=P+Q for curves with A=-1. +func (P *pointR1) coreAddition(Q *pointR3) { + Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb + addYX2, subYX2, dt2 := &Q.addYX, &Q.subYX, &Q.dt2 + a, b, c, d, e, f, g, h := Px, Py, &fp.Elt{}, Pz, Pta, Px, Py, Ptb + fp.Mul(c, Pta, Ptb) // t1 = ta*tb + fp.Sub(h, Py, Px) // y1-x1 + fp.Add(b, Py, Px) // y1+x1 + fp.Mul(a, h, subYX2) // A = (y1-x1)*(y2-x2) + fp.Mul(b, b, addYX2) // B = (y1+x1)*(y2+x2) + fp.Mul(c, c, dt2) // C = 2*D*t1*t2 + fp.Sub(e, b, a) // E = B-A + fp.Add(h, b, a) // H = B+A + fp.Sub(f, d, c) // F = D-C + fp.Add(g, d, c) // G = D+C + fp.Mul(Pz, f, g) // Z = F * G + fp.Mul(Px, e, f) // X = E * F + fp.Mul(Py, g, h) // Y = G * H, T = E * H +} + +func (P *pointR1) oddMultiples(T []pointR2) { + var R pointR2 + n := len(T) + T[0].fromR1(P) + _2P := *P + _2P.double() + R.fromR1(&_2P) + for i := 1; i < n; i++ { + P.add(&R) + T[i].fromR1(P) + } +} + +func (P *pointR1) isEqual(Q *pointR1) bool { + l, r := &fp.Elt{}, &fp.Elt{} + fp.Mul(l, &P.x, &Q.z) + fp.Mul(r, &Q.x, &P.z) + fp.Sub(l, l, r) + b := fp.IsZero(l) + fp.Mul(l, &P.y, &Q.z) + fp.Mul(r, &Q.y, &P.z) + fp.Sub(l, l, r) + b = b && fp.IsZero(l) + fp.Mul(l, &P.ta, &P.tb) + fp.Mul(l, l, &Q.z) + fp.Mul(r, &Q.ta, &Q.tb) + fp.Mul(r, r, &P.z) + fp.Sub(l, l, r) + b = b && fp.IsZero(l) + return b +} + +func (P *pointR3) neg() { + P.addYX, P.subYX = P.subYX, P.addYX + fp.Neg(&P.dt2, &P.dt2) +} + +func (P *pointR2) fromR1(Q *pointR1) { + fp.Add(&P.addYX, &Q.y, &Q.x) + fp.Sub(&P.subYX, &Q.y, &Q.x) + fp.Mul(&P.dt2, &Q.ta, &Q.tb) + fp.Mul(&P.dt2, &P.dt2, ¶mD) + fp.Add(&P.dt2, &P.dt2, &P.dt2) + fp.Add(&P.z2, &Q.z, &Q.z) +} + +func (P *pointR3) cneg(b int) { + t := &fp.Elt{} + fp.Cswap(&P.addYX, &P.subYX, uint(b)) + fp.Neg(t, &P.dt2) + fp.Cmov(&P.dt2, t, uint(b)) +} + +func (P *pointR3) cmov(Q *pointR3, b int) { + fp.Cmov(&P.addYX, &Q.addYX, uint(b)) + fp.Cmov(&P.subYX, &Q.subYX, uint(b)) + fp.Cmov(&P.dt2, &Q.dt2, uint(b)) +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go new file mode 100644 index 00000000000..c3505b67ace --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go @@ -0,0 +1,9 @@ +//go:build go1.13 +// +build go1.13 + +package ed25519 + +import cryptoEd25519 "crypto/ed25519" + +// PublicKey is the type of Ed25519 public keys. +type PublicKey cryptoEd25519.PublicKey diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go new file mode 100644 index 00000000000..d57d86eff08 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go @@ -0,0 +1,7 @@ +//go:build !go1.13 +// +build !go1.13 + +package ed25519 + +// PublicKey is the type of Ed25519 public keys. +type PublicKey []byte diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go new file mode 100644 index 00000000000..e4520f52034 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go @@ -0,0 +1,87 @@ +package ed25519 + +import ( + "crypto/rand" + "encoding/asn1" + + "github.com/cloudflare/circl/sign" +) + +var sch sign.Scheme = &scheme{} + +// Scheme returns a signature interface. +func Scheme() sign.Scheme { return sch } + +type scheme struct{} + +func (*scheme) Name() string { return "Ed25519" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SignatureSize() int { return SignatureSize } +func (*scheme) SeedSize() int { return SeedSize } +func (*scheme) TLSIdentifier() uint { return 0x0807 } +func (*scheme) SupportsContext() bool { return false } +func (*scheme) Oid() asn1.ObjectIdentifier { + return asn1.ObjectIdentifier{1, 3, 101, 112} +} + +func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) { + return GenerateKey(rand.Reader) +} + +func (*scheme) Sign( + sk sign.PrivateKey, + message []byte, + opts *sign.SignatureOpts, +) []byte { + priv, ok := sk.(PrivateKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + if opts != nil && opts.Context != "" { + panic(sign.ErrContextNotSupported) + } + return Sign(priv, message) +} + +func (*scheme) Verify( + pk sign.PublicKey, + message, signature []byte, + opts *sign.SignatureOpts, +) bool { + pub, ok := pk.(PublicKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + if opts != nil { + if opts.Context != "" { + panic(sign.ErrContextNotSupported) + } + } + return Verify(pub, message, signature) +} + +func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { + privateKey := NewKeyFromSeed(seed) + publicKey := make(PublicKey, PublicKeySize) + copy(publicKey, privateKey[SeedSize:]) + return publicKey, privateKey +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { + if len(buf) < PublicKeySize { + return nil, sign.ErrPubKeySize + } + pub := make(PublicKey, PublicKeySize) + copy(pub, buf[:PublicKeySize]) + return pub, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) { + if len(buf) < PrivateKeySize { + return nil, sign.ErrPrivKeySize + } + priv := make(PrivateKey, PrivateKeySize) + copy(priv, buf[:PrivateKeySize]) + return priv, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed25519/tables.go b/src/vendor/github.com/cloudflare/circl/sign/ed25519/tables.go new file mode 100644 index 00000000000..8763b426fc0 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed25519/tables.go @@ -0,0 +1,213 @@ +package ed25519 + +import fp "github.com/cloudflare/circl/math/fp25519" + +var tabSign = [fxV][fx2w1]pointR3{ + { + pointR3{ + addYX: fp.Elt{0x85, 0x3b, 0x8c, 0xf5, 0xc6, 0x93, 0xbc, 0x2f, 0x19, 0x0e, 0x8c, 0xfb, 0xc6, 0x2d, 0x93, 0xcf, 0xc2, 0x42, 0x3d, 0x64, 0x98, 0x48, 0x0b, 0x27, 0x65, 0xba, 0xd4, 0x33, 0x3a, 0x9d, 0xcf, 0x07}, + subYX: fp.Elt{0x3e, 0x91, 0x40, 0xd7, 0x05, 0x39, 0x10, 0x9d, 0xb3, 0xbe, 0x40, 0xd1, 0x05, 0x9f, 0x39, 0xfd, 0x09, 0x8a, 0x8f, 0x68, 0x34, 0x84, 0xc1, 0xa5, 0x67, 0x12, 0xf8, 0x98, 0x92, 0x2f, 0xfd, 0x44}, + dt2: fp.Elt{0x68, 0xaa, 0x7a, 0x87, 0x05, 0x12, 0xc9, 0xab, 0x9e, 0xc4, 0xaa, 0xcc, 0x23, 0xe8, 0xd9, 0x26, 0x8c, 0x59, 0x43, 0xdd, 0xcb, 0x7d, 0x1b, 0x5a, 0xa8, 0x65, 0x0c, 0x9f, 0x68, 0x7b, 0x11, 0x6f}, + }, + { + addYX: fp.Elt{0x7c, 0xb0, 0x9e, 0xe6, 0xc5, 0xbf, 0xfa, 0x13, 0x8e, 0x0d, 0x22, 0xde, 0xc8, 0xd1, 0xce, 0x52, 0x02, 0xd5, 0x62, 0x31, 0x71, 0x0e, 0x8e, 0x9d, 0xb0, 0xd6, 0x00, 0xa5, 0x5a, 0x0e, 0xce, 0x72}, + subYX: fp.Elt{0x1a, 0x8e, 0x5c, 0xdc, 0xa4, 0xb3, 0x6c, 0x51, 0x18, 0xa0, 0x09, 0x80, 0x9a, 0x46, 0x33, 0xd5, 0xe0, 0x3c, 0x4d, 0x3b, 0xfc, 0x49, 0xa2, 0x43, 0x29, 0xe1, 0x29, 0xa9, 0x93, 0xea, 0x7c, 0x35}, + dt2: fp.Elt{0x08, 0x46, 0x6f, 0x68, 0x7f, 0x0b, 0x7c, 0x9e, 0xad, 0xba, 0x07, 0x61, 0x74, 0x83, 0x2f, 0xfc, 0x26, 0xd6, 0x09, 0xb9, 0x00, 0x34, 0x36, 0x4f, 0x01, 0xf3, 0x48, 0xdb, 0x43, 0xba, 0x04, 0x44}, + }, + { + addYX: fp.Elt{0x4c, 0xda, 0x0d, 0x13, 0x66, 0xfd, 0x82, 0x84, 0x9f, 0x75, 0x5b, 0xa2, 0x17, 0xfe, 0x34, 0xbf, 0x1f, 0xcb, 0xba, 0x90, 0x55, 0x80, 0x83, 0xfd, 0x63, 0xb9, 0x18, 0xf8, 0x5b, 0x5d, 0x94, 0x1e}, + subYX: fp.Elt{0xb9, 0xdb, 0x6c, 0x04, 0x88, 0x22, 0xd8, 0x79, 0x83, 0x2f, 0x8d, 0x65, 0x6b, 0xd2, 0xab, 0x1b, 0xdd, 0x65, 0xe5, 0x93, 0x63, 0xf8, 0xa2, 0xd8, 0x3c, 0xf1, 0x4b, 0xc5, 0x99, 0xd1, 0xf2, 0x12}, + dt2: fp.Elt{0x05, 0x4c, 0xb8, 0x3b, 0xfe, 0xf5, 0x9f, 0x2e, 0xd1, 0xb2, 0xb8, 0xff, 0xfe, 0x6d, 0xd9, 0x37, 0xe0, 0xae, 0xb4, 0x5a, 0x51, 0x80, 0x7e, 0x9b, 0x1d, 0xd1, 0x8d, 0x8c, 0x56, 0xb1, 0x84, 0x35}, + }, + { + addYX: fp.Elt{0x39, 0x71, 0x43, 0x34, 0xe3, 0x42, 0x45, 0xa1, 0xf2, 0x68, 0x71, 0xa7, 0xe8, 0x23, 0xfd, 0x9f, 0x86, 0x48, 0xff, 0xe5, 0x96, 0x74, 0xcf, 0x05, 0x49, 0xe2, 0xb3, 0x6c, 0x17, 0x77, 0x2f, 0x6d}, + subYX: fp.Elt{0x73, 0x3f, 0xc1, 0xc7, 0x6a, 0x66, 0xa1, 0x20, 0xdd, 0x11, 0xfb, 0x7a, 0x6e, 0xa8, 0x51, 0xb8, 0x3f, 0x9d, 0xa2, 0x97, 0x84, 0xb5, 0xc7, 0x90, 0x7c, 0xab, 0x48, 0xd6, 0x84, 0xa3, 0xd5, 0x1a}, + dt2: fp.Elt{0x63, 0x27, 0x3c, 0x49, 0x4b, 0xfc, 0x22, 0xf2, 0x0b, 0x50, 0xc2, 0x0f, 0xb4, 0x1f, 0x31, 0x0c, 0x2f, 0x53, 0xab, 0xaa, 0x75, 0x6f, 0xe0, 0x69, 0x39, 0x56, 0xe0, 0x3b, 0xb7, 0xa8, 0xbf, 0x45}, + }, + }, + { + { + addYX: fp.Elt{0x00, 0x45, 0xd9, 0x0d, 0x58, 0x03, 0xfc, 0x29, 0x93, 0xec, 0xbb, 0x6f, 0xa4, 0x7a, 0xd2, 0xec, 0xf8, 0xa7, 0xe2, 0xc2, 0x5f, 0x15, 0x0a, 0x13, 0xd5, 0xa1, 0x06, 0xb7, 0x1a, 0x15, 0x6b, 0x41}, + subYX: fp.Elt{0x85, 0x8c, 0xb2, 0x17, 0xd6, 0x3b, 0x0a, 0xd3, 0xea, 0x3b, 0x77, 0x39, 0xb7, 0x77, 0xd3, 0xc5, 0xbf, 0x5c, 0x6a, 0x1e, 0x8c, 0xe7, 0xc6, 0xc6, 0xc4, 0xb7, 0x2a, 0x8b, 0xf7, 0xb8, 0x61, 0x0d}, + dt2: fp.Elt{0xb0, 0x36, 0xc1, 0xe9, 0xef, 0xd7, 0xa8, 0x56, 0x20, 0x4b, 0xe4, 0x58, 0xcd, 0xe5, 0x07, 0xbd, 0xab, 0xe0, 0x57, 0x1b, 0xda, 0x2f, 0xe6, 0xaf, 0xd2, 0xe8, 0x77, 0x42, 0xf7, 0x2a, 0x1a, 0x19}, + }, + { + addYX: fp.Elt{0x6a, 0x6d, 0x6d, 0xd1, 0xfa, 0xf5, 0x03, 0x30, 0xbd, 0x6d, 0xc2, 0xc8, 0xf5, 0x38, 0x80, 0x4f, 0xb2, 0xbe, 0xa1, 0x76, 0x50, 0x1a, 0x73, 0xf2, 0x78, 0x2b, 0x8e, 0x3a, 0x1e, 0x34, 0x47, 0x7b}, + subYX: fp.Elt{0xc3, 0x2c, 0x36, 0xdc, 0xc5, 0x45, 0xbc, 0xef, 0x1b, 0x64, 0xd6, 0x65, 0x28, 0xe9, 0xda, 0x84, 0x13, 0xbe, 0x27, 0x8e, 0x3f, 0x98, 0x2a, 0x37, 0xee, 0x78, 0x97, 0xd6, 0xc0, 0x6f, 0xb4, 0x53}, + dt2: fp.Elt{0x58, 0x5d, 0xa7, 0xa3, 0x68, 0xbb, 0x20, 0x30, 0x2e, 0x03, 0xe9, 0xb1, 0xd4, 0x90, 0x72, 0xe3, 0x71, 0xb2, 0x36, 0x3e, 0x73, 0xa0, 0x2e, 0x3d, 0xd1, 0x85, 0x33, 0x62, 0x4e, 0xa7, 0x7b, 0x31}, + }, + { + addYX: fp.Elt{0xbf, 0xc4, 0x38, 0x53, 0xfb, 0x68, 0xa9, 0x77, 0xce, 0x55, 0xf9, 0x05, 0xcb, 0xeb, 0xfb, 0x8c, 0x46, 0xc2, 0x32, 0x7c, 0xf0, 0xdb, 0xd7, 0x2c, 0x62, 0x8e, 0xdd, 0x54, 0x75, 0xcf, 0x3f, 0x33}, + subYX: fp.Elt{0x49, 0x50, 0x1f, 0x4e, 0x6e, 0x55, 0x55, 0xde, 0x8c, 0x4e, 0x77, 0x96, 0x38, 0x3b, 0xfe, 0xb6, 0x43, 0x3c, 0x86, 0x69, 0xc2, 0x72, 0x66, 0x1f, 0x6b, 0xf9, 0x87, 0xbc, 0x4f, 0x37, 0x3e, 0x3c}, + dt2: fp.Elt{0xd2, 0x2f, 0x06, 0x6b, 0x08, 0x07, 0x69, 0x77, 0xc0, 0x94, 0xcc, 0xae, 0x43, 0x00, 0x59, 0x6e, 0xa3, 0x63, 0xa8, 0xdd, 0xfa, 0x24, 0x18, 0xd0, 0x35, 0xc7, 0x78, 0xf7, 0x0d, 0xd4, 0x5a, 0x1e}, + }, + { + addYX: fp.Elt{0x45, 0xc1, 0x17, 0x51, 0xf8, 0xed, 0x7e, 0xc7, 0xa9, 0x1a, 0x11, 0x6e, 0x2d, 0xef, 0x0b, 0xd5, 0x3f, 0x98, 0xb0, 0xa3, 0x9d, 0x65, 0xf1, 0xcd, 0x53, 0x4a, 0x8a, 0x18, 0x70, 0x0a, 0x7f, 0x23}, + subYX: fp.Elt{0xdd, 0xef, 0xbe, 0x3a, 0x31, 0xe0, 0xbc, 0xbe, 0x6d, 0x5d, 0x79, 0x87, 0xd6, 0xbe, 0x68, 0xe3, 0x59, 0x76, 0x8c, 0x86, 0x0e, 0x7a, 0x92, 0x13, 0x14, 0x8f, 0x67, 0xb3, 0xcb, 0x1a, 0x76, 0x76}, + dt2: fp.Elt{0x56, 0x7a, 0x1c, 0x9d, 0xca, 0x96, 0xf9, 0xf9, 0x03, 0x21, 0xd4, 0xe8, 0xb3, 0xd5, 0xe9, 0x52, 0xc8, 0x54, 0x1e, 0x1b, 0x13, 0xb6, 0xfd, 0x47, 0x7d, 0x02, 0x32, 0x33, 0x27, 0xe2, 0x1f, 0x19}, + }, + }, +} + +var tabVerif = [1 << (omegaFix - 2)]pointR3{ + { /* 1P */ + addYX: fp.Elt{0x85, 0x3b, 0x8c, 0xf5, 0xc6, 0x93, 0xbc, 0x2f, 0x19, 0x0e, 0x8c, 0xfb, 0xc6, 0x2d, 0x93, 0xcf, 0xc2, 0x42, 0x3d, 0x64, 0x98, 0x48, 0x0b, 0x27, 0x65, 0xba, 0xd4, 0x33, 0x3a, 0x9d, 0xcf, 0x07}, + subYX: fp.Elt{0x3e, 0x91, 0x40, 0xd7, 0x05, 0x39, 0x10, 0x9d, 0xb3, 0xbe, 0x40, 0xd1, 0x05, 0x9f, 0x39, 0xfd, 0x09, 0x8a, 0x8f, 0x68, 0x34, 0x84, 0xc1, 0xa5, 0x67, 0x12, 0xf8, 0x98, 0x92, 0x2f, 0xfd, 0x44}, + dt2: fp.Elt{0x68, 0xaa, 0x7a, 0x87, 0x05, 0x12, 0xc9, 0xab, 0x9e, 0xc4, 0xaa, 0xcc, 0x23, 0xe8, 0xd9, 0x26, 0x8c, 0x59, 0x43, 0xdd, 0xcb, 0x7d, 0x1b, 0x5a, 0xa8, 0x65, 0x0c, 0x9f, 0x68, 0x7b, 0x11, 0x6f}, + }, + { /* 3P */ + addYX: fp.Elt{0x30, 0x97, 0xee, 0x4c, 0xa8, 0xb0, 0x25, 0xaf, 0x8a, 0x4b, 0x86, 0xe8, 0x30, 0x84, 0x5a, 0x02, 0x32, 0x67, 0x01, 0x9f, 0x02, 0x50, 0x1b, 0xc1, 0xf4, 0xf8, 0x80, 0x9a, 0x1b, 0x4e, 0x16, 0x7a}, + subYX: fp.Elt{0x65, 0xd2, 0xfc, 0xa4, 0xe8, 0x1f, 0x61, 0x56, 0x7d, 0xba, 0xc1, 0xe5, 0xfd, 0x53, 0xd3, 0x3b, 0xbd, 0xd6, 0x4b, 0x21, 0x1a, 0xf3, 0x31, 0x81, 0x62, 0xda, 0x5b, 0x55, 0x87, 0x15, 0xb9, 0x2a}, + dt2: fp.Elt{0x89, 0xd8, 0xd0, 0x0d, 0x3f, 0x93, 0xae, 0x14, 0x62, 0xda, 0x35, 0x1c, 0x22, 0x23, 0x94, 0x58, 0x4c, 0xdb, 0xf2, 0x8c, 0x45, 0xe5, 0x70, 0xd1, 0xc6, 0xb4, 0xb9, 0x12, 0xaf, 0x26, 0x28, 0x5a}, + }, + { /* 5P */ + addYX: fp.Elt{0x33, 0xbb, 0xa5, 0x08, 0x44, 0xbc, 0x12, 0xa2, 0x02, 0xed, 0x5e, 0xc7, 0xc3, 0x48, 0x50, 0x8d, 0x44, 0xec, 0xbf, 0x5a, 0x0c, 0xeb, 0x1b, 0xdd, 0xeb, 0x06, 0xe2, 0x46, 0xf1, 0xcc, 0x45, 0x29}, + subYX: fp.Elt{0xba, 0xd6, 0x47, 0xa4, 0xc3, 0x82, 0x91, 0x7f, 0xb7, 0x29, 0x27, 0x4b, 0xd1, 0x14, 0x00, 0xd5, 0x87, 0xa0, 0x64, 0xb8, 0x1c, 0xf1, 0x3c, 0xe3, 0xf3, 0x55, 0x1b, 0xeb, 0x73, 0x7e, 0x4a, 0x15}, + dt2: fp.Elt{0x85, 0x82, 0x2a, 0x81, 0xf1, 0xdb, 0xbb, 0xbc, 0xfc, 0xd1, 0xbd, 0xd0, 0x07, 0x08, 0x0e, 0x27, 0x2d, 0xa7, 0xbd, 0x1b, 0x0b, 0x67, 0x1b, 0xb4, 0x9a, 0xb6, 0x3b, 0x6b, 0x69, 0xbe, 0xaa, 0x43}, + }, + { /* 7P */ + addYX: fp.Elt{0xbf, 0xa3, 0x4e, 0x94, 0xd0, 0x5c, 0x1a, 0x6b, 0xd2, 0xc0, 0x9d, 0xb3, 0x3a, 0x35, 0x70, 0x74, 0x49, 0x2e, 0x54, 0x28, 0x82, 0x52, 0xb2, 0x71, 0x7e, 0x92, 0x3c, 0x28, 0x69, 0xea, 0x1b, 0x46}, + subYX: fp.Elt{0xb1, 0x21, 0x32, 0xaa, 0x9a, 0x2c, 0x6f, 0xba, 0xa7, 0x23, 0xba, 0x3b, 0x53, 0x21, 0xa0, 0x6c, 0x3a, 0x2c, 0x19, 0x92, 0x4f, 0x76, 0xea, 0x9d, 0xe0, 0x17, 0x53, 0x2e, 0x5d, 0xdd, 0x6e, 0x1d}, + dt2: fp.Elt{0xa2, 0xb3, 0xb8, 0x01, 0xc8, 0x6d, 0x83, 0xf1, 0x9a, 0xa4, 0x3e, 0x05, 0x47, 0x5f, 0x03, 0xb3, 0xf3, 0xad, 0x77, 0x58, 0xba, 0x41, 0x9c, 0x52, 0xa7, 0x90, 0x0f, 0x6a, 0x1c, 0xbb, 0x9f, 0x7a}, + }, + { /* 9P */ + addYX: fp.Elt{0x2f, 0x63, 0xa8, 0xa6, 0x8a, 0x67, 0x2e, 0x9b, 0xc5, 0x46, 0xbc, 0x51, 0x6f, 0x9e, 0x50, 0xa6, 0xb5, 0xf5, 0x86, 0xc6, 0xc9, 0x33, 0xb2, 0xce, 0x59, 0x7f, 0xdd, 0x8a, 0x33, 0xed, 0xb9, 0x34}, + subYX: fp.Elt{0x64, 0x80, 0x9d, 0x03, 0x7e, 0x21, 0x6e, 0xf3, 0x9b, 0x41, 0x20, 0xf5, 0xb6, 0x81, 0xa0, 0x98, 0x44, 0xb0, 0x5e, 0xe7, 0x08, 0xc6, 0xcb, 0x96, 0x8f, 0x9c, 0xdc, 0xfa, 0x51, 0x5a, 0xc0, 0x49}, + dt2: fp.Elt{0x1b, 0xaf, 0x45, 0x90, 0xbf, 0xe8, 0xb4, 0x06, 0x2f, 0xd2, 0x19, 0xa7, 0xe8, 0x83, 0xff, 0xe2, 0x16, 0xcf, 0xd4, 0x93, 0x29, 0xfc, 0xf6, 0xaa, 0x06, 0x8b, 0x00, 0x1b, 0x02, 0x72, 0xc1, 0x73}, + }, + { /* 11P */ + addYX: fp.Elt{0xde, 0x2a, 0x80, 0x8a, 0x84, 0x00, 0xbf, 0x2f, 0x27, 0x2e, 0x30, 0x02, 0xcf, 0xfe, 0xd9, 0xe5, 0x06, 0x34, 0x70, 0x17, 0x71, 0x84, 0x3e, 0x11, 0xaf, 0x8f, 0x6d, 0x54, 0xe2, 0xaa, 0x75, 0x42}, + subYX: fp.Elt{0x48, 0x43, 0x86, 0x49, 0x02, 0x5b, 0x5f, 0x31, 0x81, 0x83, 0x08, 0x77, 0x69, 0xb3, 0xd6, 0x3e, 0x95, 0xeb, 0x8d, 0x6a, 0x55, 0x75, 0xa0, 0xa3, 0x7f, 0xc7, 0xd5, 0x29, 0x80, 0x59, 0xab, 0x18}, + dt2: fp.Elt{0xe9, 0x89, 0x60, 0xfd, 0xc5, 0x2c, 0x2b, 0xd8, 0xa4, 0xe4, 0x82, 0x32, 0xa1, 0xb4, 0x1e, 0x03, 0x22, 0x86, 0x1a, 0xb5, 0x99, 0x11, 0x31, 0x44, 0x48, 0xf9, 0x3d, 0xb5, 0x22, 0x55, 0xc6, 0x3d}, + }, + { /* 13P */ + addYX: fp.Elt{0x6d, 0x7f, 0x00, 0xa2, 0x22, 0xc2, 0x70, 0xbf, 0xdb, 0xde, 0xbc, 0xb5, 0x9a, 0xb3, 0x84, 0xbf, 0x07, 0xba, 0x07, 0xfb, 0x12, 0x0e, 0x7a, 0x53, 0x41, 0xf2, 0x46, 0xc3, 0xee, 0xd7, 0x4f, 0x23}, + subYX: fp.Elt{0x93, 0xbf, 0x7f, 0x32, 0x3b, 0x01, 0x6f, 0x50, 0x6b, 0x6f, 0x77, 0x9b, 0xc9, 0xeb, 0xfc, 0xae, 0x68, 0x59, 0xad, 0xaa, 0x32, 0xb2, 0x12, 0x9d, 0xa7, 0x24, 0x60, 0x17, 0x2d, 0x88, 0x67, 0x02}, + dt2: fp.Elt{0x78, 0xa3, 0x2e, 0x73, 0x19, 0xa1, 0x60, 0x53, 0x71, 0xd4, 0x8d, 0xdf, 0xb1, 0xe6, 0x37, 0x24, 0x33, 0xe5, 0xa7, 0x91, 0xf8, 0x37, 0xef, 0xa2, 0x63, 0x78, 0x09, 0xaa, 0xfd, 0xa6, 0x7b, 0x49}, + }, + { /* 15P */ + addYX: fp.Elt{0xa0, 0xea, 0xcf, 0x13, 0x03, 0xcc, 0xce, 0x24, 0x6d, 0x24, 0x9c, 0x18, 0x8d, 0xc2, 0x48, 0x86, 0xd0, 0xd4, 0xf2, 0xc1, 0xfa, 0xbd, 0xbd, 0x2d, 0x2b, 0xe7, 0x2d, 0xf1, 0x17, 0x29, 0xe2, 0x61}, + subYX: fp.Elt{0x0b, 0xcf, 0x8c, 0x46, 0x86, 0xcd, 0x0b, 0x04, 0xd6, 0x10, 0x99, 0x2a, 0xa4, 0x9b, 0x82, 0xd3, 0x92, 0x51, 0xb2, 0x07, 0x08, 0x30, 0x08, 0x75, 0xbf, 0x5e, 0xd0, 0x18, 0x42, 0xcd, 0xb5, 0x43}, + dt2: fp.Elt{0x16, 0xb5, 0xd0, 0x9b, 0x2f, 0x76, 0x9a, 0x5d, 0xee, 0xde, 0x3f, 0x37, 0x4e, 0xaf, 0x38, 0xeb, 0x70, 0x42, 0xd6, 0x93, 0x7d, 0x5a, 0x2e, 0x03, 0x42, 0xd8, 0xe4, 0x0a, 0x21, 0x61, 0x1d, 0x51}, + }, + { /* 17P */ + addYX: fp.Elt{0x81, 0x9d, 0x0e, 0x95, 0xef, 0x76, 0xc6, 0x92, 0x4f, 0x04, 0xd7, 0xc0, 0xcd, 0x20, 0x46, 0xa5, 0x48, 0x12, 0x8f, 0x6f, 0x64, 0x36, 0x9b, 0xaa, 0xe3, 0x55, 0xb8, 0xdd, 0x24, 0x59, 0x32, 0x6d}, + subYX: fp.Elt{0x87, 0xde, 0x20, 0x44, 0x48, 0x86, 0x13, 0x08, 0xb4, 0xed, 0x92, 0xb5, 0x16, 0xf0, 0x1c, 0x8a, 0x25, 0x2d, 0x94, 0x29, 0x27, 0x4e, 0xfa, 0x39, 0x10, 0x28, 0x48, 0xe2, 0x6f, 0xfe, 0xa7, 0x71}, + dt2: fp.Elt{0x54, 0xc8, 0xc8, 0xa5, 0xb8, 0x82, 0x71, 0x6c, 0x03, 0x2a, 0x5f, 0xfe, 0x79, 0x14, 0xfd, 0x33, 0x0c, 0x8d, 0x77, 0x83, 0x18, 0x59, 0xcf, 0x72, 0xa9, 0xea, 0x9e, 0x55, 0xb6, 0xc4, 0x46, 0x47}, + }, + { /* 19P */ + addYX: fp.Elt{0x2b, 0x9a, 0xc6, 0x6d, 0x3c, 0x7b, 0x77, 0xd3, 0x17, 0xf6, 0x89, 0x6f, 0x27, 0xb2, 0xfa, 0xde, 0xb5, 0x16, 0x3a, 0xb5, 0xf7, 0x1c, 0x65, 0x45, 0xb7, 0x9f, 0xfe, 0x34, 0xde, 0x51, 0x9a, 0x5c}, + subYX: fp.Elt{0x47, 0x11, 0x74, 0x64, 0xc8, 0x46, 0x85, 0x34, 0x49, 0xc8, 0xfc, 0x0e, 0xdd, 0xae, 0x35, 0x7d, 0x32, 0xa3, 0x72, 0x06, 0x76, 0x9a, 0x93, 0xff, 0xd6, 0xe6, 0xb5, 0x7d, 0x49, 0x63, 0x96, 0x21}, + dt2: fp.Elt{0x67, 0x0e, 0xf1, 0x79, 0xcf, 0xf1, 0x10, 0xf5, 0x5b, 0x51, 0x58, 0xe6, 0xa1, 0xda, 0xdd, 0xff, 0x77, 0x22, 0x14, 0x10, 0x17, 0xa7, 0xc3, 0x09, 0xbb, 0x23, 0x82, 0x60, 0x3c, 0x50, 0x04, 0x48}, + }, + { /* 21P */ + addYX: fp.Elt{0xc7, 0x7f, 0xa3, 0x2c, 0xd0, 0x9e, 0x24, 0xc4, 0xab, 0xac, 0x15, 0xa6, 0xe3, 0xa0, 0x59, 0xa0, 0x23, 0x0e, 0x6e, 0xc9, 0xd7, 0x6e, 0xa9, 0x88, 0x6d, 0x69, 0x50, 0x16, 0xa5, 0x98, 0x33, 0x55}, + subYX: fp.Elt{0x75, 0xd1, 0x36, 0x3a, 0xd2, 0x21, 0x68, 0x3b, 0x32, 0x9e, 0x9b, 0xe9, 0xa7, 0x0a, 0xb4, 0xbb, 0x47, 0x8a, 0x83, 0x20, 0xe4, 0x5c, 0x9e, 0x5d, 0x5e, 0x4c, 0xde, 0x58, 0x88, 0x09, 0x1e, 0x77}, + dt2: fp.Elt{0xdf, 0x1e, 0x45, 0x78, 0xd2, 0xf5, 0x12, 0x9a, 0xcb, 0x9c, 0x89, 0x85, 0x79, 0x5d, 0xda, 0x3a, 0x08, 0x95, 0xa5, 0x9f, 0x2d, 0x4a, 0x7f, 0x47, 0x11, 0xa6, 0xf5, 0x8f, 0xd6, 0xd1, 0x5e, 0x5a}, + }, + { /* 23P */ + addYX: fp.Elt{0x83, 0x0e, 0x15, 0xfe, 0x2a, 0x12, 0x95, 0x11, 0xd8, 0x35, 0x4b, 0x7e, 0x25, 0x9a, 0x20, 0xcf, 0x20, 0x1e, 0x71, 0x1e, 0x29, 0xf8, 0x87, 0x73, 0xf0, 0x92, 0xbf, 0xd8, 0x97, 0xb8, 0xac, 0x44}, + subYX: fp.Elt{0x59, 0x73, 0x52, 0x58, 0xc5, 0xe0, 0xe5, 0xba, 0x7e, 0x9d, 0xdb, 0xca, 0x19, 0x5c, 0x2e, 0x39, 0xe9, 0xab, 0x1c, 0xda, 0x1e, 0x3c, 0x65, 0x28, 0x44, 0xdc, 0xef, 0x5f, 0x13, 0x60, 0x9b, 0x01}, + dt2: fp.Elt{0x83, 0x4b, 0x13, 0x5e, 0x14, 0x68, 0x60, 0x1e, 0x16, 0x4c, 0x30, 0x24, 0x4f, 0xe6, 0xf5, 0xc4, 0xd7, 0x3e, 0x1a, 0xfc, 0xa8, 0x88, 0x6e, 0x50, 0x92, 0x2f, 0xad, 0xe6, 0xfd, 0x49, 0x0c, 0x15}, + }, + { /* 25P */ + addYX: fp.Elt{0x38, 0x11, 0x47, 0x09, 0x95, 0xf2, 0x7b, 0x8e, 0x51, 0xa6, 0x75, 0x4f, 0x39, 0xef, 0x6f, 0x5d, 0xad, 0x08, 0xa7, 0x25, 0xc4, 0x79, 0xaf, 0x10, 0x22, 0x99, 0xb9, 0x5b, 0x07, 0x5a, 0x2b, 0x6b}, + subYX: fp.Elt{0x68, 0xa8, 0xdc, 0x9c, 0x3c, 0x86, 0x49, 0xb8, 0xd0, 0x4a, 0x71, 0xb8, 0xdb, 0x44, 0x3f, 0xc8, 0x8d, 0x16, 0x36, 0x0c, 0x56, 0xe3, 0x3e, 0xfe, 0xc1, 0xfb, 0x05, 0x1e, 0x79, 0xd7, 0xa6, 0x78}, + dt2: fp.Elt{0x76, 0xb9, 0xa0, 0x47, 0x4b, 0x70, 0xbf, 0x58, 0xd5, 0x48, 0x17, 0x74, 0x55, 0xb3, 0x01, 0xa6, 0x90, 0xf5, 0x42, 0xd5, 0xb1, 0x1f, 0x2b, 0xaa, 0x00, 0x5d, 0xd5, 0x4a, 0xfc, 0x7f, 0x5c, 0x72}, + }, + { /* 27P */ + addYX: fp.Elt{0xb2, 0x99, 0xcf, 0xd1, 0x15, 0x67, 0x42, 0xe4, 0x34, 0x0d, 0xa2, 0x02, 0x11, 0xd5, 0x52, 0x73, 0x9f, 0x10, 0x12, 0x8b, 0x7b, 0x15, 0xd1, 0x23, 0xa3, 0xf3, 0xb1, 0x7c, 0x27, 0xc9, 0x4c, 0x79}, + subYX: fp.Elt{0xc0, 0x98, 0xd0, 0x1c, 0xf7, 0x2b, 0x80, 0x91, 0x66, 0x63, 0x5e, 0xed, 0xa4, 0x6c, 0x41, 0xfe, 0x4c, 0x99, 0x02, 0x49, 0x71, 0x5d, 0x58, 0xdf, 0xe7, 0xfa, 0x55, 0xf8, 0x25, 0x46, 0xd5, 0x4c}, + dt2: fp.Elt{0x53, 0x50, 0xac, 0xc2, 0x26, 0xc4, 0xf6, 0x4a, 0x58, 0x72, 0xf6, 0x32, 0xad, 0xed, 0x9a, 0xbc, 0x21, 0x10, 0x31, 0x0a, 0xf1, 0x32, 0xd0, 0x2a, 0x85, 0x8e, 0xcc, 0x6f, 0x7b, 0x35, 0x08, 0x70}, + }, + { /* 29P */ + addYX: fp.Elt{0x01, 0x3f, 0x77, 0x38, 0x27, 0x67, 0x88, 0x0b, 0xfb, 0xcc, 0xfb, 0x95, 0xfa, 0xc8, 0xcc, 0xb8, 0xb6, 0x29, 0xad, 0xb9, 0xa3, 0xd5, 0x2d, 0x8d, 0x6a, 0x0f, 0xad, 0x51, 0x98, 0x7e, 0xef, 0x06}, + subYX: fp.Elt{0x34, 0x4a, 0x58, 0x82, 0xbb, 0x9f, 0x1b, 0xd0, 0x2b, 0x79, 0xb4, 0xd2, 0x63, 0x64, 0xab, 0x47, 0x02, 0x62, 0x53, 0x48, 0x9c, 0x63, 0x31, 0xb6, 0x28, 0xd4, 0xd6, 0x69, 0x36, 0x2a, 0xa9, 0x13}, + dt2: fp.Elt{0xe5, 0x7d, 0x57, 0xc0, 0x1c, 0x77, 0x93, 0xca, 0x5c, 0xdc, 0x35, 0x50, 0x1e, 0xe4, 0x40, 0x75, 0x71, 0xe0, 0x02, 0xd8, 0x01, 0x0f, 0x68, 0x24, 0x6a, 0xf8, 0x2a, 0x8a, 0xdf, 0x6d, 0x29, 0x3c}, + }, + { /* 31P */ + addYX: fp.Elt{0x13, 0xa7, 0x14, 0xd9, 0xf9, 0x15, 0xad, 0xae, 0x12, 0xf9, 0x8f, 0x8c, 0xf9, 0x7b, 0x2f, 0xa9, 0x30, 0xd7, 0x53, 0x9f, 0x17, 0x23, 0xf8, 0xaf, 0xba, 0x77, 0x0c, 0x49, 0x93, 0xd3, 0x99, 0x7a}, + subYX: fp.Elt{0x41, 0x25, 0x1f, 0xbb, 0x2e, 0x4d, 0xeb, 0xfc, 0x1f, 0xb9, 0xad, 0x40, 0xc7, 0x10, 0x95, 0xb8, 0x05, 0xad, 0xa1, 0xd0, 0x7d, 0xa3, 0x71, 0xfc, 0x7b, 0x71, 0x47, 0x07, 0x70, 0x2c, 0x89, 0x0a}, + dt2: fp.Elt{0xe8, 0xa3, 0xbd, 0x36, 0x24, 0xed, 0x52, 0x8f, 0x94, 0x07, 0xe8, 0x57, 0x41, 0xc8, 0xa8, 0x77, 0xe0, 0x9c, 0x2f, 0x26, 0x63, 0x65, 0xa9, 0xa5, 0xd2, 0xf7, 0x02, 0x83, 0xd2, 0x62, 0x67, 0x28}, + }, + { /* 33P */ + addYX: fp.Elt{0x25, 0x5b, 0xe3, 0x3c, 0x09, 0x36, 0x78, 0x4e, 0x97, 0xaa, 0x6b, 0xb2, 0x1d, 0x18, 0xe1, 0x82, 0x3f, 0xb8, 0xc7, 0xcb, 0xd3, 0x92, 0xc1, 0x0c, 0x3a, 0x9d, 0x9d, 0x6a, 0x04, 0xda, 0xf1, 0x32}, + subYX: fp.Elt{0xbd, 0xf5, 0x2e, 0xce, 0x2b, 0x8e, 0x55, 0x7c, 0x63, 0xbc, 0x47, 0x67, 0xb4, 0x6c, 0x98, 0xe4, 0xb8, 0x89, 0xbb, 0x3b, 0x9f, 0x17, 0x4a, 0x15, 0x7a, 0x76, 0xf1, 0xd6, 0xa3, 0xf2, 0x86, 0x76}, + dt2: fp.Elt{0x6a, 0x7c, 0x59, 0x6d, 0xa6, 0x12, 0x8d, 0xaa, 0x2b, 0x85, 0xd3, 0x04, 0x03, 0x93, 0x11, 0x8f, 0x22, 0xb0, 0x09, 0xc2, 0x73, 0xdc, 0x91, 0x3f, 0xa6, 0x28, 0xad, 0xa9, 0xf8, 0x05, 0x13, 0x56}, + }, + { /* 35P */ + addYX: fp.Elt{0xd1, 0xae, 0x92, 0xec, 0x8d, 0x97, 0x0c, 0x10, 0xe5, 0x73, 0x6d, 0x4d, 0x43, 0xd5, 0x43, 0xca, 0x48, 0xba, 0x47, 0xd8, 0x22, 0x1b, 0x13, 0x83, 0x2c, 0x4d, 0x5d, 0xe3, 0x53, 0xec, 0xaa}, + subYX: fp.Elt{0xd5, 0xc0, 0xb0, 0xe7, 0x28, 0xcc, 0x22, 0x67, 0x53, 0x5c, 0x07, 0xdb, 0xbb, 0xe9, 0x9d, 0x70, 0x61, 0x0a, 0x01, 0xd7, 0xa7, 0x8d, 0xf6, 0xca, 0x6c, 0xcc, 0x57, 0x2c, 0xef, 0x1a, 0x0a, 0x03}, + dt2: fp.Elt{0xaa, 0xd2, 0x3a, 0x00, 0x73, 0xf7, 0xb1, 0x7b, 0x08, 0x66, 0x21, 0x2b, 0x80, 0x29, 0x3f, 0x0b, 0x3e, 0xd2, 0x0e, 0x52, 0x86, 0xdc, 0x21, 0x78, 0x80, 0x54, 0x06, 0x24, 0x1c, 0x9c, 0xbe, 0x20}, + }, + { /* 37P */ + addYX: fp.Elt{0xa6, 0x73, 0x96, 0x24, 0xd8, 0x87, 0x53, 0xe1, 0x93, 0xe4, 0x46, 0xf5, 0x2d, 0xbc, 0x43, 0x59, 0xb5, 0x63, 0x6f, 0xc3, 0x81, 0x9a, 0x7f, 0x1c, 0xde, 0xc1, 0x0a, 0x1f, 0x36, 0xb3, 0x0a, 0x75}, + subYX: fp.Elt{0x60, 0x5e, 0x02, 0xe2, 0x4a, 0xe4, 0xe0, 0x20, 0x38, 0xb9, 0xdc, 0xcb, 0x2f, 0x3b, 0x3b, 0xb0, 0x1c, 0x0d, 0x5a, 0xf9, 0x9c, 0x63, 0x5d, 0x10, 0x11, 0xe3, 0x67, 0x50, 0x54, 0x4c, 0x76, 0x69}, + dt2: fp.Elt{0x37, 0x10, 0xf8, 0xa2, 0x83, 0x32, 0x8a, 0x1e, 0xf1, 0xcb, 0x7f, 0xbd, 0x23, 0xda, 0x2e, 0x6f, 0x63, 0x25, 0x2e, 0xac, 0x5b, 0xd1, 0x2f, 0xb7, 0x40, 0x50, 0x07, 0xb7, 0x3f, 0x6b, 0xf9, 0x54}, + }, + { /* 39P */ + addYX: fp.Elt{0x79, 0x92, 0x66, 0x29, 0x04, 0xf2, 0xad, 0x0f, 0x4a, 0x72, 0x7d, 0x7d, 0x04, 0xa2, 0xdd, 0x3a, 0xf1, 0x60, 0x57, 0x8c, 0x82, 0x94, 0x3d, 0x6f, 0x9e, 0x53, 0xb7, 0x2b, 0xc5, 0xe9, 0x7f, 0x3d}, + subYX: fp.Elt{0xcd, 0x1e, 0xb1, 0x16, 0xc6, 0xaf, 0x7d, 0x17, 0x79, 0x64, 0x57, 0xfa, 0x9c, 0x4b, 0x76, 0x89, 0x85, 0xe7, 0xec, 0xe6, 0x10, 0xa1, 0xa8, 0xb7, 0xf0, 0xdb, 0x85, 0xbe, 0x9f, 0x83, 0xe6, 0x78}, + dt2: fp.Elt{0x6b, 0x85, 0xb8, 0x37, 0xf7, 0x2d, 0x33, 0x70, 0x8a, 0x17, 0x1a, 0x04, 0x43, 0x5d, 0xd0, 0x75, 0x22, 0x9e, 0xe5, 0xa0, 0x4a, 0xf7, 0x0f, 0x32, 0x42, 0x82, 0x08, 0x50, 0xf3, 0x68, 0xf2, 0x70}, + }, + { /* 41P */ + addYX: fp.Elt{0x47, 0x5f, 0x80, 0xb1, 0x83, 0x45, 0x86, 0x66, 0x19, 0x7c, 0xdd, 0x60, 0xd1, 0xc5, 0x35, 0xf5, 0x06, 0xb0, 0x4c, 0x1e, 0xb7, 0x4e, 0x87, 0xe9, 0xd9, 0x89, 0xd8, 0xfa, 0x5c, 0x34, 0x0d, 0x7c}, + subYX: fp.Elt{0x55, 0xf3, 0xdc, 0x70, 0x20, 0x11, 0x24, 0x23, 0x17, 0xe1, 0xfc, 0xe7, 0x7e, 0xc9, 0x0c, 0x38, 0x98, 0xb6, 0x52, 0x35, 0xed, 0xde, 0x1d, 0xb3, 0xb9, 0xc4, 0xb8, 0x39, 0xc0, 0x56, 0x4e, 0x40}, + dt2: fp.Elt{0x8a, 0x33, 0x78, 0x8c, 0x4b, 0x1f, 0x1f, 0x59, 0xe1, 0xb5, 0xe0, 0x67, 0xb1, 0x6a, 0x36, 0xa0, 0x44, 0x3d, 0x5f, 0xb4, 0x52, 0x41, 0xbc, 0x5c, 0x77, 0xc7, 0xae, 0x2a, 0x76, 0x54, 0xd7, 0x20}, + }, + { /* 43P */ + addYX: fp.Elt{0x58, 0xb7, 0x3b, 0xc7, 0x6f, 0xc3, 0x8f, 0x5e, 0x9a, 0xbb, 0x3c, 0x36, 0xa5, 0x43, 0xe5, 0xac, 0x22, 0xc9, 0x3b, 0x90, 0x7d, 0x4a, 0x93, 0xa9, 0x62, 0xec, 0xce, 0xf3, 0x46, 0x1e, 0x8f, 0x2b}, + subYX: fp.Elt{0x43, 0xf5, 0xb9, 0x35, 0xb1, 0xfe, 0x74, 0x9d, 0x6c, 0x95, 0x8c, 0xde, 0xf1, 0x7d, 0xb3, 0x84, 0xa9, 0x8b, 0x13, 0x57, 0x07, 0x2b, 0x32, 0xe9, 0xe1, 0x4c, 0x0b, 0x79, 0xa8, 0xad, 0xb8, 0x38}, + dt2: fp.Elt{0x5d, 0xf9, 0x51, 0xdf, 0x9c, 0x4a, 0xc0, 0xb5, 0xac, 0xde, 0x1f, 0xcb, 0xae, 0x52, 0x39, 0x2b, 0xda, 0x66, 0x8b, 0x32, 0x8b, 0x6d, 0x10, 0x1d, 0x53, 0x19, 0xba, 0xce, 0x32, 0xeb, 0x9a, 0x04}, + }, + { /* 45P */ + addYX: fp.Elt{0x31, 0x79, 0xfc, 0x75, 0x0b, 0x7d, 0x50, 0xaa, 0xd3, 0x25, 0x67, 0x7a, 0x4b, 0x92, 0xef, 0x0f, 0x30, 0x39, 0x6b, 0x39, 0x2b, 0x54, 0x82, 0x1d, 0xfc, 0x74, 0xf6, 0x30, 0x75, 0xe1, 0x5e, 0x79}, + subYX: fp.Elt{0x7e, 0xfe, 0xdc, 0x63, 0x3c, 0x7d, 0x76, 0xd7, 0x40, 0x6e, 0x85, 0x97, 0x48, 0x59, 0x9c, 0x20, 0x13, 0x7c, 0x4f, 0xe1, 0x61, 0x68, 0x67, 0xb6, 0xfc, 0x25, 0xd6, 0xc8, 0xe0, 0x65, 0xc6, 0x51}, + dt2: fp.Elt{0x81, 0xbd, 0xec, 0x52, 0x0a, 0x5b, 0x4a, 0x25, 0xe7, 0xaf, 0x34, 0xe0, 0x6e, 0x1f, 0x41, 0x5d, 0x31, 0x4a, 0xee, 0xca, 0x0d, 0x4d, 0xa2, 0xe6, 0x77, 0x44, 0xc5, 0x9d, 0xf4, 0x9b, 0xd1, 0x6c}, + }, + { /* 47P */ + addYX: fp.Elt{0x86, 0xc3, 0xaf, 0x65, 0x21, 0x61, 0xfe, 0x1f, 0x10, 0x1b, 0xd5, 0xb8, 0x88, 0x2a, 0x2a, 0x08, 0xaa, 0x0b, 0x99, 0x20, 0x7e, 0x62, 0xf6, 0x76, 0xe7, 0x43, 0x9e, 0x42, 0xa7, 0xb3, 0x01, 0x5e}, + subYX: fp.Elt{0xa3, 0x9c, 0x17, 0x52, 0x90, 0x61, 0x87, 0x7e, 0x85, 0x9f, 0x2c, 0x0b, 0x06, 0x0a, 0x1d, 0x57, 0x1e, 0x71, 0x99, 0x84, 0xa8, 0xba, 0xa2, 0x80, 0x38, 0xe6, 0xb2, 0x40, 0xdb, 0xf3, 0x20, 0x75}, + dt2: fp.Elt{0xa1, 0x57, 0x93, 0xd3, 0xe3, 0x0b, 0xb5, 0x3d, 0xa5, 0x94, 0x9e, 0x59, 0xdd, 0x6c, 0x7b, 0x96, 0x6e, 0x1e, 0x31, 0xdf, 0x64, 0x9a, 0x30, 0x1a, 0x86, 0xc9, 0xf3, 0xce, 0x9c, 0x2c, 0x09, 0x71}, + }, + { /* 49P */ + addYX: fp.Elt{0xcf, 0x1d, 0x05, 0x74, 0xac, 0xd8, 0x6b, 0x85, 0x1e, 0xaa, 0xb7, 0x55, 0x08, 0xa4, 0xf6, 0x03, 0xeb, 0x3c, 0x74, 0xc9, 0xcb, 0xe7, 0x4a, 0x3a, 0xde, 0xab, 0x37, 0x71, 0xbb, 0xa5, 0x73, 0x41}, + subYX: fp.Elt{0x8c, 0x91, 0x64, 0x03, 0x3f, 0x52, 0xd8, 0x53, 0x1c, 0x6b, 0xab, 0x3f, 0xf4, 0x04, 0xb4, 0xa2, 0xa4, 0xe5, 0x81, 0x66, 0x9e, 0x4a, 0x0b, 0x08, 0xa7, 0x7b, 0x25, 0xd0, 0x03, 0x5b, 0xa1, 0x0e}, + dt2: fp.Elt{0x8a, 0x21, 0xf9, 0xf0, 0x31, 0x6e, 0xc5, 0x17, 0x08, 0x47, 0xfc, 0x1a, 0x2b, 0x6e, 0x69, 0x5a, 0x76, 0xf1, 0xb2, 0xf4, 0x68, 0x16, 0x93, 0xf7, 0x67, 0x3a, 0x4e, 0x4a, 0x61, 0x65, 0xc5, 0x5f}, + }, + { /* 51P */ + addYX: fp.Elt{0x8e, 0x98, 0x90, 0x77, 0xe6, 0xe1, 0x92, 0x48, 0x22, 0xd7, 0x5c, 0x1c, 0x0f, 0x95, 0xd5, 0x01, 0xed, 0x3e, 0x92, 0xe5, 0x9a, 0x81, 0xb0, 0xe3, 0x1b, 0x65, 0x46, 0x9d, 0x40, 0xc7, 0x14, 0x32}, + subYX: fp.Elt{0xe5, 0x7a, 0x6d, 0xc4, 0x0d, 0x57, 0x6e, 0x13, 0x8f, 0xdc, 0xf8, 0x54, 0xcc, 0xaa, 0xd0, 0x0f, 0x86, 0xad, 0x0d, 0x31, 0x03, 0x9f, 0x54, 0x59, 0xa1, 0x4a, 0x45, 0x4c, 0x41, 0x1c, 0x71, 0x62}, + dt2: fp.Elt{0x70, 0x17, 0x65, 0x06, 0x74, 0x82, 0x29, 0x13, 0x36, 0x94, 0x27, 0x8a, 0x66, 0xa0, 0xa4, 0x3b, 0x3c, 0x22, 0x5d, 0x18, 0xec, 0xb8, 0xb6, 0xd9, 0x3c, 0x83, 0xcb, 0x3e, 0x07, 0x94, 0xea, 0x5b}, + }, + { /* 53P */ + addYX: fp.Elt{0xf8, 0xd2, 0x43, 0xf3, 0x63, 0xce, 0x70, 0xb4, 0xf1, 0xe8, 0x43, 0x05, 0x8f, 0xba, 0x67, 0x00, 0x6f, 0x7b, 0x11, 0xa2, 0xa1, 0x51, 0xda, 0x35, 0x2f, 0xbd, 0xf1, 0x44, 0x59, 0x78, 0xd0, 0x4a}, + subYX: fp.Elt{0xe4, 0x9b, 0xc8, 0x12, 0x09, 0xbf, 0x1d, 0x64, 0x9c, 0x57, 0x6e, 0x7d, 0x31, 0x8b, 0xf3, 0xac, 0x65, 0xb0, 0x97, 0xf6, 0x02, 0x9e, 0xfe, 0xab, 0xec, 0x1e, 0xf6, 0x48, 0xc1, 0xd5, 0xac, 0x3a}, + dt2: fp.Elt{0x01, 0x83, 0x31, 0xc3, 0x34, 0x3b, 0x8e, 0x85, 0x26, 0x68, 0x31, 0x07, 0x47, 0xc0, 0x99, 0xdc, 0x8c, 0xa8, 0x9d, 0xd3, 0x2e, 0x5b, 0x08, 0x34, 0x3d, 0x85, 0x02, 0xd9, 0xb1, 0x0c, 0xff, 0x3a}, + }, + { /* 55P */ + addYX: fp.Elt{0x05, 0x35, 0xc5, 0xf4, 0x0b, 0x43, 0x26, 0x92, 0x83, 0x22, 0x1f, 0x26, 0x13, 0x9c, 0xe4, 0x68, 0xc6, 0x27, 0xd3, 0x8f, 0x78, 0x33, 0xef, 0x09, 0x7f, 0x9e, 0xd9, 0x2b, 0x73, 0x9f, 0xcf, 0x2c}, + subYX: fp.Elt{0x5e, 0x40, 0x20, 0x3a, 0xeb, 0xc7, 0xc5, 0x87, 0xc9, 0x56, 0xad, 0xed, 0xef, 0x11, 0xe3, 0x8e, 0xf9, 0xd5, 0x29, 0xad, 0x48, 0x2e, 0x25, 0x29, 0x1d, 0x25, 0xcd, 0xf4, 0x86, 0x7e, 0x0e, 0x11}, + dt2: fp.Elt{0xe4, 0xf5, 0x03, 0xd6, 0x9e, 0xd8, 0xc0, 0x57, 0x0c, 0x20, 0xb0, 0xf0, 0x28, 0x86, 0x88, 0x12, 0xb7, 0x3b, 0x2e, 0xa0, 0x09, 0x27, 0x17, 0x53, 0x37, 0x3a, 0x69, 0xb9, 0xe0, 0x57, 0xc5, 0x05}, + }, + { /* 57P */ + addYX: fp.Elt{0xb0, 0x0e, 0xc2, 0x89, 0xb0, 0xbb, 0x76, 0xf7, 0x5c, 0xd8, 0x0f, 0xfa, 0xf6, 0x5b, 0xf8, 0x61, 0xfb, 0x21, 0x44, 0x63, 0x4e, 0x3f, 0xb9, 0xb6, 0x05, 0x12, 0x86, 0x41, 0x08, 0xef, 0x9f, 0x28}, + subYX: fp.Elt{0x6f, 0x7e, 0xc9, 0x1f, 0x31, 0xce, 0xf9, 0xd8, 0xae, 0xfd, 0xf9, 0x11, 0x30, 0x26, 0x3f, 0x7a, 0xdd, 0x25, 0xed, 0x8b, 0xa0, 0x7e, 0x5b, 0xe1, 0x5a, 0x87, 0xe9, 0x8f, 0x17, 0x4c, 0x15, 0x6e}, + dt2: fp.Elt{0xbf, 0x9a, 0xd6, 0xfe, 0x36, 0x63, 0x61, 0xcf, 0x4f, 0xc9, 0x35, 0x83, 0xe7, 0xe4, 0x16, 0x9b, 0xe7, 0x7f, 0x3a, 0x75, 0x65, 0x97, 0x78, 0x13, 0x19, 0xa3, 0x5c, 0xa9, 0x42, 0xf6, 0xfb, 0x6a}, + }, + { /* 59P */ + addYX: fp.Elt{0xcc, 0xa8, 0x13, 0xf9, 0x70, 0x50, 0xe5, 0x5d, 0x61, 0xf5, 0x0c, 0x2b, 0x7b, 0x16, 0x1d, 0x7d, 0x89, 0xd4, 0xea, 0x90, 0xb6, 0x56, 0x29, 0xda, 0xd9, 0x1e, 0x80, 0xdb, 0xce, 0x93, 0xc0, 0x12}, + subYX: fp.Elt{0xc1, 0xd2, 0xf5, 0x62, 0x0c, 0xde, 0xa8, 0x7d, 0x9a, 0x7b, 0x0e, 0xb0, 0xa4, 0x3d, 0xfc, 0x98, 0xe0, 0x70, 0xad, 0x0d, 0xda, 0x6a, 0xeb, 0x7d, 0xc4, 0x38, 0x50, 0xb9, 0x51, 0xb8, 0xb4, 0x0d}, + dt2: fp.Elt{0x0f, 0x19, 0xb8, 0x08, 0x93, 0x7f, 0x14, 0xfc, 0x10, 0xe3, 0x1a, 0xa1, 0xa0, 0x9d, 0x96, 0x06, 0xfd, 0xd7, 0xc7, 0xda, 0x72, 0x55, 0xe7, 0xce, 0xe6, 0x5c, 0x63, 0xc6, 0x99, 0x87, 0xaa, 0x33}, + }, + { /* 61P */ + addYX: fp.Elt{0xb1, 0x6c, 0x15, 0xfc, 0x88, 0xf5, 0x48, 0x83, 0x27, 0x6d, 0x0a, 0x1a, 0x9b, 0xba, 0xa2, 0x6d, 0xb6, 0x5a, 0xca, 0x87, 0x5c, 0x2d, 0x26, 0xe2, 0xa6, 0x89, 0xd5, 0xc8, 0xc1, 0xd0, 0x2c, 0x21}, + subYX: fp.Elt{0xf2, 0x5c, 0x08, 0xbd, 0x1e, 0xf5, 0x0f, 0xaf, 0x1f, 0x3f, 0xd3, 0x67, 0x89, 0x1a, 0xf5, 0x78, 0x3c, 0x03, 0x60, 0x50, 0xe1, 0xbf, 0xc2, 0x6e, 0x86, 0x1a, 0xe2, 0xe8, 0x29, 0x6f, 0x3c, 0x23}, + dt2: fp.Elt{0x81, 0xc7, 0x18, 0x7f, 0x10, 0xd5, 0xf4, 0xd2, 0x28, 0x9d, 0x7e, 0x52, 0xf2, 0xcd, 0x2e, 0x12, 0x41, 0x33, 0x3d, 0x3d, 0x2a, 0x86, 0x0a, 0xa7, 0xe3, 0x4c, 0x91, 0x11, 0x89, 0x77, 0xb7, 0x1d}, + }, + { /* 63P */ + addYX: fp.Elt{0xb6, 0x1a, 0x70, 0xdd, 0x69, 0x47, 0x39, 0xb3, 0xa5, 0x8d, 0xcf, 0x19, 0xd4, 0xde, 0xb8, 0xe2, 0x52, 0xc8, 0x2a, 0xfd, 0x61, 0x41, 0xdf, 0x15, 0xbe, 0x24, 0x7d, 0x01, 0x8a, 0xca, 0xe2, 0x7a}, + subYX: fp.Elt{0x6f, 0xc2, 0x6b, 0x7c, 0x39, 0x52, 0xf3, 0xdd, 0x13, 0x01, 0xd5, 0x53, 0xcc, 0xe2, 0x97, 0x7a, 0x30, 0xa3, 0x79, 0xbf, 0x3a, 0xf4, 0x74, 0x7c, 0xfc, 0xad, 0xe2, 0x26, 0xad, 0x97, 0xad, 0x31}, + dt2: fp.Elt{0x62, 0xb9, 0x20, 0x09, 0xed, 0x17, 0xe8, 0xb7, 0x9d, 0xda, 0x19, 0x3f, 0xcc, 0x18, 0x85, 0x1e, 0x64, 0x0a, 0x56, 0x25, 0x4f, 0xc1, 0x91, 0xe4, 0x83, 0x2c, 0x62, 0xa6, 0x53, 0xfc, 0xd1, 0x1e}, + }, +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed448/ed448.go b/src/vendor/github.com/cloudflare/circl/sign/ed448/ed448.go new file mode 100644 index 00000000000..324bd8f3346 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed448/ed448.go @@ -0,0 +1,411 @@ +// Package ed448 implements Ed448 signature scheme as described in RFC-8032. +// +// This package implements two signature variants. +// +// | Scheme Name | Sign Function | Verification | Context | +// |-------------|-------------------|---------------|-------------------| +// | Ed448 | Sign | Verify | Yes, can be empty | +// | Ed448Ph | SignPh | VerifyPh | Yes, can be empty | +// | All above | (PrivateKey).Sign | VerifyAny | As above | +// +// Specific functions for sign and verify are defined. A generic signing +// function for all schemes is available through the crypto.Signer interface, +// which is implemented by the PrivateKey type. A correspond all-in-one +// verification method is provided by the VerifyAny function. +// +// Both schemes require a context string for domain separation. This parameter +// is passed using a SignerOptions struct defined in this package. +// +// References: +// +// - RFC8032: https://rfc-editor.org/rfc/rfc8032.txt +// - EdDSA for more curves: https://eprint.iacr.org/2015/677 +// - High-speed high-security signatures: https://doi.org/10.1007/s13389-012-0027-1 +package ed448 + +import ( + "bytes" + "crypto" + cryptoRand "crypto/rand" + "crypto/subtle" + "errors" + "fmt" + "io" + "strconv" + + "github.com/cloudflare/circl/ecc/goldilocks" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/sign" +) + +const ( + // ContextMaxSize is the maximum length (in bytes) allowed for context. + ContextMaxSize = 255 + // PublicKeySize is the length in bytes of Ed448 public keys. + PublicKeySize = 57 + // PrivateKeySize is the length in bytes of Ed448 private keys. + PrivateKeySize = 114 + // SignatureSize is the length in bytes of signatures. + SignatureSize = 114 + // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + SeedSize = 57 +) + +const ( + paramB = 456 / 8 // Size of keys in bytes. + hashSize = 2 * paramB // Size of the hash function's output. +) + +// SignerOptions implements crypto.SignerOpts and augments with parameters +// that are specific to the Ed448 signature schemes. +type SignerOptions struct { + // Hash must be crypto.Hash(0) for both Ed448 and Ed448Ph. + crypto.Hash + + // Context is an optional domain separation string for signing. + // Its length must be less or equal than 255 bytes. + Context string + + // Scheme is an identifier for choosing a signature scheme. + Scheme SchemeID +} + +// SchemeID is an identifier for each signature scheme. +type SchemeID uint + +const ( + ED448 SchemeID = iota + ED448Ph +) + +// PublicKey is the type of Ed448 public keys. +type PublicKey []byte + +// Equal reports whether pub and x have the same value. +func (pub PublicKey) Equal(x crypto.PublicKey) bool { + xx, ok := x.(PublicKey) + return ok && bytes.Equal(pub, xx) +} + +// PrivateKey is the type of Ed448 private keys. It implements crypto.Signer. +type PrivateKey []byte + +// Equal reports whether priv and x have the same value. +func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { + xx, ok := x.(PrivateKey) + return ok && subtle.ConstantTimeCompare(priv, xx) == 1 +} + +// Public returns the PublicKey corresponding to priv. +func (priv PrivateKey) Public() crypto.PublicKey { + publicKey := make([]byte, PublicKeySize) + copy(publicKey, priv[SeedSize:]) + return PublicKey(publicKey) +} + +// Seed returns the private key seed corresponding to priv. It is provided for +// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds +// in this package. +func (priv PrivateKey) Seed() []byte { + seed := make([]byte, SeedSize) + copy(seed, priv[:SeedSize]) + return seed +} + +func (priv PrivateKey) Scheme() sign.Scheme { return sch } + +func (pub PublicKey) Scheme() sign.Scheme { return sch } + +func (priv PrivateKey) MarshalBinary() (data []byte, err error) { + privateKey := make(PrivateKey, PrivateKeySize) + copy(privateKey, priv) + return privateKey, nil +} + +func (pub PublicKey) MarshalBinary() (data []byte, err error) { + publicKey := make(PublicKey, PublicKeySize) + copy(publicKey, pub) + return publicKey, nil +} + +// Sign creates a signature of a message given a key pair. +// This function supports all the two signature variants defined in RFC-8032, +// namely Ed448 (or pure EdDSA) and Ed448Ph. +// The opts.HashFunc() must return zero to the specify Ed448 variant. This can +// be achieved by passing crypto.Hash(0) as the value for opts. +// Use an Options struct to pass a bool indicating that the ed448Ph variant +// should be used. +// The struct can also be optionally used to pass a context string for signing. +func (priv PrivateKey) Sign( + rand io.Reader, + message []byte, + opts crypto.SignerOpts, +) (signature []byte, err error) { + var ctx string + var scheme SchemeID + + if o, ok := opts.(SignerOptions); ok { + ctx = o.Context + scheme = o.Scheme + } + + switch true { + case scheme == ED448 && opts.HashFunc() == crypto.Hash(0): + return Sign(priv, message, ctx), nil + case scheme == ED448Ph && opts.HashFunc() == crypto.Hash(0): + return SignPh(priv, message, ctx), nil + default: + return nil, errors.New("ed448: bad hash algorithm") + } +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { + if rand == nil { + rand = cryptoRand.Reader + } + + seed := make(PrivateKey, SeedSize) + if _, err := io.ReadFull(rand, seed); err != nil { + return nil, nil, err + } + + privateKey := NewKeyFromSeed(seed) + publicKey := make([]byte, PublicKeySize) + copy(publicKey, privateKey[SeedSize:]) + + return publicKey, privateKey, nil +} + +// NewKeyFromSeed calculates a private key from a seed. It will panic if +// len(seed) is not SeedSize. This function is provided for interoperability +// with RFC 8032. RFC 8032's private keys correspond to seeds in this +// package. +func NewKeyFromSeed(seed []byte) PrivateKey { + privateKey := make([]byte, PrivateKeySize) + newKeyFromSeed(privateKey, seed) + return privateKey +} + +func newKeyFromSeed(privateKey, seed []byte) { + if l := len(seed); l != SeedSize { + panic("ed448: bad seed length: " + strconv.Itoa(l)) + } + + var h [hashSize]byte + H := sha3.NewShake256() + _, _ = H.Write(seed) + _, _ = H.Read(h[:]) + s := &goldilocks.Scalar{} + deriveSecretScalar(s, h[:paramB]) + + copy(privateKey[:SeedSize], seed) + _ = goldilocks.Curve{}.ScalarBaseMult(s).ToBytes(privateKey[SeedSize:]) +} + +func signAll(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) { + if len(ctx) > ContextMaxSize { + panic(fmt.Errorf("ed448: bad context length: " + strconv.Itoa(len(ctx)))) + } + + H := sha3.NewShake256() + var PHM []byte + + if preHash { + var h [64]byte + _, _ = H.Write(message) + _, _ = H.Read(h[:]) + PHM = h[:] + H.Reset() + } else { + PHM = message + } + + // 1. Hash the 57-byte private key using SHAKE256(x, 114). + var h [hashSize]byte + _, _ = H.Write(privateKey[:SeedSize]) + _, _ = H.Read(h[:]) + s := &goldilocks.Scalar{} + deriveSecretScalar(s, h[:paramB]) + prefix := h[paramB:] + + // 2. Compute SHAKE256(dom4(F, C) || prefix || PH(M), 114). + var rPM [hashSize]byte + H.Reset() + + writeDom(&H, ctx, preHash) + + _, _ = H.Write(prefix) + _, _ = H.Write(PHM) + _, _ = H.Read(rPM[:]) + + // 3. Compute the point [r]B. + r := &goldilocks.Scalar{} + r.FromBytes(rPM[:]) + R := (&[paramB]byte{})[:] + if err := (goldilocks.Curve{}.ScalarBaseMult(r).ToBytes(R)); err != nil { + panic(err) + } + // 4. Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114) + var hRAM [hashSize]byte + H.Reset() + + writeDom(&H, ctx, preHash) + + _, _ = H.Write(R) + _, _ = H.Write(privateKey[SeedSize:]) + _, _ = H.Write(PHM) + _, _ = H.Read(hRAM[:]) + + // 5. Compute S = (r + k * s) mod order. + k := &goldilocks.Scalar{} + k.FromBytes(hRAM[:]) + S := &goldilocks.Scalar{} + S.Mul(k, s) + S.Add(S, r) + + // 6. The signature is the concatenation of R and S. + copy(signature[:paramB], R[:]) + copy(signature[paramB:], S[:]) +} + +// Sign signs the message with privateKey and returns a signature. +// This function supports the signature variant defined in RFC-8032: Ed448, +// also known as the pure version of EdDSA. +// It will panic if len(privateKey) is not PrivateKeySize. +func Sign(priv PrivateKey, message []byte, ctx string) []byte { + signature := make([]byte, SignatureSize) + signAll(signature, priv, message, []byte(ctx), false) + return signature +} + +// SignPh creates a signature of a message given a keypair. +// This function supports the signature variant defined in RFC-8032: Ed448ph, +// meaning it internally hashes the message using SHAKE-256. +// Context could be passed to this function, which length should be no more than +// 255. It can be empty. +func SignPh(priv PrivateKey, message []byte, ctx string) []byte { + signature := make([]byte, SignatureSize) + signAll(signature, priv, message, []byte(ctx), true) + return signature +} + +func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool { + if len(public) != PublicKeySize || + len(signature) != SignatureSize || + len(ctx) > ContextMaxSize || + !isLessThanOrder(signature[paramB:]) { + return false + } + + P, err := goldilocks.FromBytes(public) + if err != nil { + return false + } + + H := sha3.NewShake256() + var PHM []byte + + if preHash { + var h [64]byte + _, _ = H.Write(message) + _, _ = H.Read(h[:]) + PHM = h[:] + H.Reset() + } else { + PHM = message + } + + var hRAM [hashSize]byte + R := signature[:paramB] + + writeDom(&H, ctx, preHash) + + _, _ = H.Write(R) + _, _ = H.Write(public) + _, _ = H.Write(PHM) + _, _ = H.Read(hRAM[:]) + + k := &goldilocks.Scalar{} + k.FromBytes(hRAM[:]) + S := &goldilocks.Scalar{} + S.FromBytes(signature[paramB:]) + + encR := (&[paramB]byte{})[:] + P.Neg() + _ = goldilocks.Curve{}.CombinedMult(S, k, P).ToBytes(encR) + return bytes.Equal(R, encR) +} + +// VerifyAny returns true if the signature is valid. Failure cases are invalid +// signature, or when the public key cannot be decoded. +// This function supports all the two signature variants defined in RFC-8032, +// namely Ed448 (or pure EdDSA) and Ed448Ph. +// The opts.HashFunc() must return zero, this can be achieved by passing +// crypto.Hash(0) as the value for opts. +// Use a SignerOptions struct to pass a context string for signing. +func VerifyAny(public PublicKey, message, signature []byte, opts crypto.SignerOpts) bool { + var ctx string + var scheme SchemeID + if o, ok := opts.(SignerOptions); ok { + ctx = o.Context + scheme = o.Scheme + } + + switch true { + case scheme == ED448 && opts.HashFunc() == crypto.Hash(0): + return Verify(public, message, signature, ctx) + case scheme == ED448Ph && opts.HashFunc() == crypto.Hash(0): + return VerifyPh(public, message, signature, ctx) + default: + return false + } +} + +// Verify returns true if the signature is valid. Failure cases are invalid +// signature, or when the public key cannot be decoded. +// This function supports the signature variant defined in RFC-8032: Ed448, +// also known as the pure version of EdDSA. +func Verify(public PublicKey, message, signature []byte, ctx string) bool { + return verify(public, message, signature, []byte(ctx), false) +} + +// VerifyPh returns true if the signature is valid. Failure cases are invalid +// signature, or when the public key cannot be decoded. +// This function supports the signature variant defined in RFC-8032: Ed448ph, +// meaning it internally hashes the message using SHAKE-256. +// Context could be passed to this function, which length should be no more than +// 255. It can be empty. +func VerifyPh(public PublicKey, message, signature []byte, ctx string) bool { + return verify(public, message, signature, []byte(ctx), true) +} + +func deriveSecretScalar(s *goldilocks.Scalar, h []byte) { + h[0] &= 0xFC // The two least significant bits of the first octet are cleared, + h[paramB-1] = 0x00 // all eight bits the last octet are cleared, and + h[paramB-2] |= 0x80 // the highest bit of the second to last octet is set. + s.FromBytes(h[:paramB]) +} + +// isLessThanOrder returns true if 0 <= x < order and if the last byte of x is zero. +func isLessThanOrder(x []byte) bool { + order := goldilocks.Curve{}.Order() + i := len(order) - 1 + for i > 0 && x[i] == order[i] { + i-- + } + return x[paramB-1] == 0 && x[i] < order[i] +} + +func writeDom(h io.Writer, ctx []byte, preHash bool) { + dom4 := "SigEd448" + _, _ = h.Write([]byte(dom4)) + + if preHash { + _, _ = h.Write([]byte{byte(0x01), byte(len(ctx))}) + } else { + _, _ = h.Write([]byte{byte(0x00), byte(len(ctx))}) + } + _, _ = h.Write(ctx) +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/ed448/signapi.go b/src/vendor/github.com/cloudflare/circl/sign/ed448/signapi.go new file mode 100644 index 00000000000..22da8bc0a57 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/ed448/signapi.go @@ -0,0 +1,87 @@ +package ed448 + +import ( + "crypto/rand" + "encoding/asn1" + + "github.com/cloudflare/circl/sign" +) + +var sch sign.Scheme = &scheme{} + +// Scheme returns a signature interface. +func Scheme() sign.Scheme { return sch } + +type scheme struct{} + +func (*scheme) Name() string { return "Ed448" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SignatureSize() int { return SignatureSize } +func (*scheme) SeedSize() int { return SeedSize } +func (*scheme) TLSIdentifier() uint { return 0x0808 } +func (*scheme) SupportsContext() bool { return true } +func (*scheme) Oid() asn1.ObjectIdentifier { + return asn1.ObjectIdentifier{1, 3, 101, 113} +} + +func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) { + return GenerateKey(rand.Reader) +} + +func (*scheme) Sign( + sk sign.PrivateKey, + message []byte, + opts *sign.SignatureOpts, +) []byte { + priv, ok := sk.(PrivateKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + ctx := "" + if opts != nil { + ctx = opts.Context + } + return Sign(priv, message, ctx) +} + +func (*scheme) Verify( + pk sign.PublicKey, + message, signature []byte, + opts *sign.SignatureOpts, +) bool { + pub, ok := pk.(PublicKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + ctx := "" + if opts != nil { + ctx = opts.Context + } + return Verify(pub, message, signature, ctx) +} + +func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { + privateKey := NewKeyFromSeed(seed) + publicKey := make(PublicKey, PublicKeySize) + copy(publicKey, privateKey[SeedSize:]) + return publicKey, privateKey +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { + if len(buf) < PublicKeySize { + return nil, sign.ErrPubKeySize + } + pub := make(PublicKey, PublicKeySize) + copy(pub, buf[:PublicKeySize]) + return pub, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) { + if len(buf) < PrivateKeySize { + return nil, sign.ErrPrivKeySize + } + priv := make(PrivateKey, PrivateKeySize) + copy(priv, buf[:PrivateKeySize]) + return priv, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/eddilithium2/eddilithium.go b/src/vendor/github.com/cloudflare/circl/sign/eddilithium2/eddilithium.go new file mode 100644 index 00000000000..9ab440199f0 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/eddilithium2/eddilithium.go @@ -0,0 +1,239 @@ +// Package eddilithium2 implements the hybrid signature scheme Ed25519-Dilithium2. +package eddilithium2 + +import ( + "crypto" + cryptoRand "crypto/rand" + "errors" + "io" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/sign" + "github.com/cloudflare/circl/sign/dilithium/mode2" + "github.com/cloudflare/circl/sign/ed25519" +) + +const ( + // SeedSize is the length of the seed for NewKeyFromSeed + SeedSize = mode2.SeedSize // = ed25519.SeedSize = 32 + + // PublicKeySize is the length in bytes of the packed public key. + PublicKeySize = mode2.PublicKeySize + ed25519.PublicKeySize + + // PrivateKeySize is the length in bytes of the packed public key. + PrivateKeySize = mode2.PrivateKeySize + ed25519.SeedSize + + // SignatureSize is the length in bytes of the signatures. + SignatureSize = mode2.SignatureSize + ed25519.SignatureSize +) + +// PublicKey is the type of an EdDilithium2 public key. +type PublicKey struct { + e ed25519.PublicKey + d mode2.PublicKey +} + +// PrivateKey is the type of an EdDilithium2 private key. +type PrivateKey struct { + e ed25519.PrivateKey + d mode2.PrivateKey +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [SeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + + pk, sk := NewKeyFromSeed(&seed) + return pk, sk, nil +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { + var seed1 [32]byte + var seed2 [ed25519.SeedSize]byte + + // Internally, Ed25519 and Dilithium hash the seeds they are passed again + // with different hash functions, so it would be safe to use exactly the + // same seed for Ed25519 and Dilithium here. However, in general, when + // combining any two signature schemes it might not be the case that this + // is safe. Setting a bad example here isn't worth the tiny gain in + // performance. + + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Read(seed1[:]) + _, _ = h.Read(seed2[:]) + dpk, dsk := mode2.NewKeyFromSeed(&seed1) + esk := ed25519.NewKeyFromSeed(seed2[:]) + + return &PublicKey{esk.Public().(ed25519.PublicKey), *dpk}, &PrivateKey{esk, *dsk} +} + +// SignTo signs the given message and writes the signature into signature. +// It will panic if signature is not of length at least SignatureSize. +func SignTo(sk *PrivateKey, msg []byte, signature []byte) { + mode2.SignTo( + &sk.d, + msg, + signature[:mode2.SignatureSize], + ) + esig := ed25519.Sign( + sk.e, + msg, + ) + copy(signature[mode2.SignatureSize:], esig[:]) +} + +// Verify checks whether the given signature by pk on msg is valid. +func Verify(pk *PublicKey, msg []byte, signature []byte) bool { + if !mode2.Verify( + &pk.d, + msg, + signature[:mode2.SignatureSize], + ) { + return false + } + if !ed25519.Verify( + pk.e, + msg, + signature[mode2.SignatureSize:], + ) { + return false + } + return true +} + +// Unpack unpacks pk to the public key encoded in buf. +func (pk *PublicKey) Unpack(buf *[PublicKeySize]byte) { + var tmp [mode2.PublicKeySize]byte + copy(tmp[:], buf[:mode2.PublicKeySize]) + pk.d.Unpack(&tmp) + pk.e = make([]byte, ed25519.PublicKeySize) + copy(pk.e, buf[mode2.PublicKeySize:]) +} + +// Unpack sets sk to the private key encoded in buf. +func (sk *PrivateKey) Unpack(buf *[PrivateKeySize]byte) { + var tmp [mode2.PrivateKeySize]byte + copy(tmp[:], buf[:mode2.PrivateKeySize]) + sk.d.Unpack(&tmp) + sk.e = ed25519.NewKeyFromSeed(buf[mode2.PrivateKeySize:]) +} + +// Pack packs the public key into buf. +func (pk *PublicKey) Pack(buf *[PublicKeySize]byte) { + var tmp [mode2.PublicKeySize]byte + pk.d.Pack(&tmp) + copy(buf[:mode2.PublicKeySize], tmp[:]) + copy(buf[mode2.PublicKeySize:], pk.e) +} + +// Pack packs the private key into buf. +func (sk *PrivateKey) Pack(buf *[PrivateKeySize]byte) { + var tmp [mode2.PrivateKeySize]byte + sk.d.Pack(&tmp) + copy(buf[:mode2.PrivateKeySize], tmp[:]) + copy(buf[mode2.PrivateKeySize:], sk.e.Seed()) +} + +// Bytes packs the public key. +func (pk *PublicKey) Bytes() []byte { + return append(pk.d.Bytes(), pk.e...) +} + +// Bytes packs the private key. +func (sk *PrivateKey) Bytes() []byte { + return append(sk.d.Bytes(), sk.e.Seed()...) +} + +// MarshalBinary packs the public key. +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + return pk.Bytes(), nil +} + +// MarshalBinary packs the private key. +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + return sk.Bytes(), nil +} + +// UnmarshalBinary the public key from data. +func (pk *PublicKey) UnmarshalBinary(data []byte) error { + if len(data) != PublicKeySize { + return errors.New("packed public key must be of eddilithium2.PublicKeySize bytes") + } + var buf [PublicKeySize]byte + copy(buf[:], data) + pk.Unpack(&buf) + return nil +} + +// UnmarshalBinary unpacks the private key from data. +func (sk *PrivateKey) UnmarshalBinary(data []byte) error { + if len(data) != PrivateKeySize { + return errors.New("packed private key must be of eddilithium2.PrivateKeySize bytes") + } + var buf [PrivateKeySize]byte + copy(buf[:], data) + sk.Unpack(&buf) + return nil +} + +func (sk *PrivateKey) Scheme() sign.Scheme { return sch } +func (pk *PublicKey) Scheme() sign.Scheme { return sch } + +func (sk *PrivateKey) Equal(other crypto.PrivateKey) bool { + castOther, ok := other.(*PrivateKey) + if !ok { + return false + } + return castOther.e.Equal(sk.e) && castOther.d.Equal(&sk.d) +} + +func (pk *PublicKey) Equal(other crypto.PublicKey) bool { + castOther, ok := other.(*PublicKey) + if !ok { + return false + } + return castOther.e.Equal(pk.e) && castOther.d.Equal(&pk.d) +} + +// Sign signs the given message. +// +// opts.HashFunc() must return zero, which can be achieved by passing +// crypto.Hash(0) for opts. rand is ignored. Will only return an error +// if opts.HashFunc() is non-zero. +// +// This function is used to make PrivateKey implement the crypto.Signer +// interface. The package-level SignTo function might be more convenient +// to use. +func (sk *PrivateKey) Sign( + rand io.Reader, msg []byte, opts crypto.SignerOpts, +) (signature []byte, err error) { + var sig [SignatureSize]byte + + if opts.HashFunc() != crypto.Hash(0) { + return nil, errors.New("eddilithium2: cannot sign hashed message") + } + + SignTo(sk, msg, sig[:]) + return sig[:], nil +} + +// Public computes the public key corresponding to this private key. +// +// Returns a *PublicKey. The type crypto.PublicKey is used to make +// PrivateKey implement the crypto.Signer interface. +func (sk *PrivateKey) Public() crypto.PublicKey { + return &PublicKey{ + sk.e.Public().(ed25519.PublicKey), + *sk.d.Public().(*mode2.PublicKey), + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/eddilithium2/signapi.go b/src/vendor/github.com/cloudflare/circl/sign/eddilithium2/signapi.go new file mode 100644 index 00000000000..0339243e4b7 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/eddilithium2/signapi.go @@ -0,0 +1,93 @@ +package eddilithium2 + +import ( + "crypto/rand" + "encoding/asn1" + + "github.com/cloudflare/circl/sign" +) + +var sch sign.Scheme = &scheme{} + +// Scheme returns a signature interface. +func Scheme() sign.Scheme { return sch } + +type scheme struct{} + +func (*scheme) Name() string { return "Ed25519-Dilithium2" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SignatureSize() int { return SignatureSize } +func (*scheme) SeedSize() int { return SeedSize } +func (*scheme) TLSIdentifier() uint { return 0xfe61 /* temp*/ } +func (*scheme) SupportsContext() bool { return false } +func (*scheme) Oid() asn1.ObjectIdentifier { + return asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 45, 9} +} + +func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) { + return GenerateKey(rand.Reader) +} + +func (*scheme) Sign( + sk sign.PrivateKey, + message []byte, + opts *sign.SignatureOpts, +) []byte { + priv, ok := sk.(*PrivateKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + if opts != nil && opts.Context != "" { + panic(sign.ErrContextNotSupported) + } + var sig [SignatureSize]byte + SignTo(priv, message, sig[:]) + return sig[:] +} + +func (*scheme) Verify( + pk sign.PublicKey, + message, signature []byte, + opts *sign.SignatureOpts, +) bool { + pub, ok := pk.(*PublicKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + if opts != nil && opts.Context != "" { + panic(sign.ErrContextNotSupported) + } + return Verify(pub, message, signature) +} + +func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { + if len(seed) != SeedSize { + panic(sign.ErrSeedSize) + } + var tmp [SeedSize]byte + copy(tmp[:], seed) + return NewKeyFromSeed(&tmp) +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { + if len(buf) != PublicKeySize { + return nil, sign.ErrPubKeySize + } + var tmp [PublicKeySize]byte + copy(tmp[:], buf) + var ret PublicKey + ret.Unpack(&tmp) + return &ret, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, sign.ErrPrivKeySize + } + var tmp [PrivateKeySize]byte + copy(tmp[:], buf) + var ret PrivateKey + ret.Unpack(&tmp) + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go b/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go new file mode 100644 index 00000000000..aa05c689c31 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go @@ -0,0 +1,234 @@ +// Package eddilithium3 implements the hybrid signature scheme Ed448-Dilithium3. +package eddilithium3 + +import ( + "crypto" + cryptoRand "crypto/rand" + "errors" + "io" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/sign" + "github.com/cloudflare/circl/sign/dilithium/mode3" + "github.com/cloudflare/circl/sign/ed448" +) + +const ( + // SeedSize is the length of the seed for NewKeyFromSeed + SeedSize = ed448.SeedSize // > mode3.SeedSize + + // PublicKeySize is the length in bytes of the packed public key. + PublicKeySize = mode3.PublicKeySize + ed448.PublicKeySize + + // PrivateKeySize is the length in bytes of the packed public key. + PrivateKeySize = mode3.PrivateKeySize + ed448.SeedSize + + // SignatureSize is the length in bytes of the signatures. + SignatureSize = mode3.SignatureSize + ed448.SignatureSize +) + +// PublicKey is the type of an EdDilithium3 public key. +type PublicKey struct { + e ed448.PublicKey + d mode3.PublicKey +} + +// PrivateKey is the type of an EdDilithium3 private key. +type PrivateKey struct { + e ed448.PrivateKey + d mode3.PrivateKey +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { + var seed [SeedSize]byte + if rand == nil { + rand = cryptoRand.Reader + } + _, err := io.ReadFull(rand, seed[:]) + if err != nil { + return nil, nil, err + } + + pk, sk := NewKeyFromSeed(&seed) + return pk, sk, nil +} + +// NewKeyFromSeed derives a public/private key pair using the given seed. +func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) { + var seed1 [32]byte + var seed2 [ed448.SeedSize]byte + + h := sha3.NewShake256() + _, _ = h.Write(seed[:]) + _, _ = h.Read(seed1[:]) + _, _ = h.Read(seed2[:]) + dpk, dsk := mode3.NewKeyFromSeed(&seed1) + esk := ed448.NewKeyFromSeed(seed2[:]) + + return &PublicKey{esk.Public().(ed448.PublicKey), *dpk}, &PrivateKey{esk, *dsk} +} + +// SignTo signs the given message and writes the signature into signature. +// It will panic if signature is not of length at least SignatureSize. +func SignTo(sk *PrivateKey, msg []byte, signature []byte) { + mode3.SignTo( + &sk.d, + msg, + signature[:mode3.SignatureSize], + ) + esig := ed448.Sign( + sk.e, + msg, + "", + ) + copy(signature[mode3.SignatureSize:], esig[:]) +} + +// Verify checks whether the given signature by pk on msg is valid. +func Verify(pk *PublicKey, msg []byte, signature []byte) bool { + if !mode3.Verify( + &pk.d, + msg, + signature[:mode3.SignatureSize], + ) { + return false + } + if !ed448.Verify( + pk.e, + msg, + signature[mode3.SignatureSize:], + "", + ) { + return false + } + return true +} + +// Unpack unpacks pk to the public key encoded in buf. +func (pk *PublicKey) Unpack(buf *[PublicKeySize]byte) { + var tmp [mode3.PublicKeySize]byte + copy(tmp[:], buf[:mode3.PublicKeySize]) + pk.d.Unpack(&tmp) + pk.e = make([]byte, ed448.PublicKeySize) + copy(pk.e, buf[mode3.PublicKeySize:]) +} + +// Unpack sets sk to the private key encoded in buf. +func (sk *PrivateKey) Unpack(buf *[PrivateKeySize]byte) { + var tmp [mode3.PrivateKeySize]byte + copy(tmp[:], buf[:mode3.PrivateKeySize]) + sk.d.Unpack(&tmp) + sk.e = ed448.NewKeyFromSeed(buf[mode3.PrivateKeySize:]) +} + +// Pack packs the public key into buf. +func (pk *PublicKey) Pack(buf *[PublicKeySize]byte) { + var tmp [mode3.PublicKeySize]byte + pk.d.Pack(&tmp) + copy(buf[:mode3.PublicKeySize], tmp[:]) + copy(buf[mode3.PublicKeySize:], pk.e) +} + +// Pack packs the private key into buf. +func (sk *PrivateKey) Pack(buf *[PrivateKeySize]byte) { + var tmp [mode3.PrivateKeySize]byte + sk.d.Pack(&tmp) + copy(buf[:mode3.PrivateKeySize], tmp[:]) + copy(buf[mode3.PrivateKeySize:], sk.e.Seed()) +} + +// Bytes packs the public key. +func (pk *PublicKey) Bytes() []byte { + return append(pk.d.Bytes(), pk.e...) +} + +// Bytes packs the private key. +func (sk *PrivateKey) Bytes() []byte { + return append(sk.d.Bytes(), sk.e.Seed()...) +} + +// MarshalBinary packs the public key. +func (pk *PublicKey) MarshalBinary() ([]byte, error) { + return pk.Bytes(), nil +} + +// MarshalBinary packs the private key. +func (sk *PrivateKey) MarshalBinary() ([]byte, error) { + return sk.Bytes(), nil +} + +// UnmarshalBinary the public key from data. +func (pk *PublicKey) UnmarshalBinary(data []byte) error { + if len(data) != PublicKeySize { + return errors.New("packed public key must be of eddilithium3.PublicKeySize bytes") + } + var buf [PublicKeySize]byte + copy(buf[:], data) + pk.Unpack(&buf) + return nil +} + +// UnmarshalBinary unpacks the private key from data. +func (sk *PrivateKey) UnmarshalBinary(data []byte) error { + if len(data) != PrivateKeySize { + return errors.New("packed private key must be of eddilithium3.PrivateKeySize bytes") + } + var buf [PrivateKeySize]byte + copy(buf[:], data) + sk.Unpack(&buf) + return nil +} + +func (sk *PrivateKey) Scheme() sign.Scheme { return sch } +func (pk *PublicKey) Scheme() sign.Scheme { return sch } + +func (sk *PrivateKey) Equal(other crypto.PrivateKey) bool { + castOther, ok := other.(*PrivateKey) + if !ok { + return false + } + return castOther.e.Equal(sk.e) && castOther.d.Equal(&sk.d) +} + +func (pk *PublicKey) Equal(other crypto.PublicKey) bool { + castOther, ok := other.(*PublicKey) + if !ok { + return false + } + return castOther.e.Equal(pk.e) && castOther.d.Equal(&pk.d) +} + +// Sign signs the given message. +// +// opts.HashFunc() must return zero, which can be achieved by passing +// crypto.Hash(0) for opts. rand is ignored. Will only return an error +// if opts.HashFunc() is non-zero. +// +// This function is used to make PrivateKey implement the crypto.Signer +// interface. The package-level SignTo function might be more convenient +// to use. +func (sk *PrivateKey) Sign( + rand io.Reader, msg []byte, opts crypto.SignerOpts, +) (signature []byte, err error) { + var sig [SignatureSize]byte + + if opts.HashFunc() != crypto.Hash(0) { + return nil, errors.New("eddilithium3: cannot sign hashed message") + } + + SignTo(sk, msg, sig[:]) + return sig[:], nil +} + +// Public computes the public key corresponding to this private key. +// +// Returns a *PublicKey. The type crypto.PublicKey is used to make +// PrivateKey implement the crypto.Signer interface. +func (sk *PrivateKey) Public() crypto.PublicKey { + return &PublicKey{ + sk.e.Public().(ed448.PublicKey), + *sk.d.Public().(*mode3.PublicKey), + } +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/signapi.go b/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/signapi.go new file mode 100644 index 00000000000..1c345cfb5a2 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/signapi.go @@ -0,0 +1,93 @@ +package eddilithium3 + +import ( + "crypto/rand" + "encoding/asn1" + + "github.com/cloudflare/circl/sign" +) + +var sch sign.Scheme = &scheme{} + +// Scheme returns a signature interface. +func Scheme() sign.Scheme { return sch } + +type scheme struct{} + +func (*scheme) Name() string { return "Ed448-Dilithium3" } +func (*scheme) PublicKeySize() int { return PublicKeySize } +func (*scheme) PrivateKeySize() int { return PrivateKeySize } +func (*scheme) SignatureSize() int { return SignatureSize } +func (*scheme) SeedSize() int { return SeedSize } +func (*scheme) TLSIdentifier() uint { return 0xfe62 /* temp */ } +func (*scheme) SupportsContext() bool { return false } +func (*scheme) Oid() asn1.ObjectIdentifier { + return asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 45, 10} +} + +func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) { + return GenerateKey(rand.Reader) +} + +func (*scheme) Sign( + sk sign.PrivateKey, + message []byte, + opts *sign.SignatureOpts, +) []byte { + priv, ok := sk.(*PrivateKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + if opts != nil && opts.Context != "" { + panic(sign.ErrContextNotSupported) + } + var sig [SignatureSize]byte + SignTo(priv, message, sig[:]) + return sig[:] +} + +func (*scheme) Verify( + pk sign.PublicKey, + message, signature []byte, + opts *sign.SignatureOpts, +) bool { + pub, ok := pk.(*PublicKey) + if !ok { + panic(sign.ErrTypeMismatch) + } + if opts != nil && opts.Context != "" { + panic(sign.ErrContextNotSupported) + } + return Verify(pub, message, signature) +} + +func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { + if len(seed) != SeedSize { + panic(sign.ErrSeedSize) + } + var tmp [SeedSize]byte + copy(tmp[:], seed) + return NewKeyFromSeed(&tmp) +} + +func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { + if len(buf) != PublicKeySize { + return nil, sign.ErrPubKeySize + } + var tmp [PublicKeySize]byte + copy(tmp[:], buf) + var ret PublicKey + ret.Unpack(&tmp) + return &ret, nil +} + +func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) { + if len(buf) != PrivateKeySize { + return nil, sign.ErrPrivKeySize + } + var tmp [PrivateKeySize]byte + copy(tmp[:], buf) + var ret PrivateKey + ret.Unpack(&tmp) + return &ret, nil +} diff --git a/src/vendor/github.com/cloudflare/circl/sign/schemes/schemes.go b/src/vendor/github.com/cloudflare/circl/sign/schemes/schemes.go new file mode 100644 index 00000000000..66ee612532d --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/schemes/schemes.go @@ -0,0 +1,46 @@ +// Package schemes contains a register of signature algorithms. +// +// Implemented schemes: +// +// Ed25519 +// Ed448 +// Ed25519-Dilithium2 +// Ed448-Dilithium3 +package schemes + +import ( + "strings" + + "github.com/cloudflare/circl/sign" + "github.com/cloudflare/circl/sign/ed25519" + "github.com/cloudflare/circl/sign/ed448" + "github.com/cloudflare/circl/sign/eddilithium2" + "github.com/cloudflare/circl/sign/eddilithium3" +) + +var allSchemes = [...]sign.Scheme{ + ed25519.Scheme(), + ed448.Scheme(), + eddilithium2.Scheme(), + eddilithium3.Scheme(), +} + +var allSchemeNames map[string]sign.Scheme + +func init() { + allSchemeNames = make(map[string]sign.Scheme) + for _, scheme := range allSchemes { + allSchemeNames[strings.ToLower(scheme.Name())] = scheme + } +} + +// ByName returns the scheme with the given name and nil if it is not +// supported. +// +// Names are case insensitive. +func ByName(name string) sign.Scheme { + return allSchemeNames[strings.ToLower(name)] +} + +// All returns all signature schemes supported. +func All() []sign.Scheme { a := allSchemes; return a[:] } diff --git a/src/vendor/github.com/cloudflare/circl/sign/sign.go b/src/vendor/github.com/cloudflare/circl/sign/sign.go new file mode 100644 index 00000000000..13b20fa4b04 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/sign.go @@ -0,0 +1,110 @@ +// Package sign provides unified interfaces for signature schemes. +// +// A register of schemes is available in the package +// +// github.com/cloudflare/circl/sign/schemes +package sign + +import ( + "crypto" + "encoding" + "errors" +) + +type SignatureOpts struct { + // If non-empty, includes the given context in the signature if supported + // and will cause an error during signing otherwise. + Context string +} + +// A public key is used to verify a signature set by the corresponding private +// key. +type PublicKey interface { + // Returns the signature scheme for this public key. + Scheme() Scheme + Equal(crypto.PublicKey) bool + encoding.BinaryMarshaler + crypto.PublicKey +} + +// A private key allows one to create signatures. +type PrivateKey interface { + // Returns the signature scheme for this private key. + Scheme() Scheme + Equal(crypto.PrivateKey) bool + // For compatibility with Go standard library + crypto.Signer + crypto.PrivateKey + encoding.BinaryMarshaler +} + +// A Scheme represents a specific instance of a signature scheme. +type Scheme interface { + // Name of the scheme. + Name() string + + // GenerateKey creates a new key-pair. + GenerateKey() (PublicKey, PrivateKey, error) + + // Creates a signature using the PrivateKey on the given message and + // returns the signature. opts are additional options which can be nil. + // + // Panics if key is nil or wrong type or opts context is not supported. + Sign(sk PrivateKey, message []byte, opts *SignatureOpts) []byte + + // Checks whether the given signature is a valid signature set by + // the private key corresponding to the given public key on the + // given message. opts are additional options which can be nil. + // + // Panics if key is nil or wrong type or opts context is not supported. + Verify(pk PublicKey, message []byte, signature []byte, opts *SignatureOpts) bool + + // Deterministically derives a keypair from a seed. If you're unsure, + // you're better off using GenerateKey(). + // + // Panics if seed is not of length SeedSize(). + DeriveKey(seed []byte) (PublicKey, PrivateKey) + + // Unmarshals a PublicKey from the provided buffer. + UnmarshalBinaryPublicKey([]byte) (PublicKey, error) + + // Unmarshals a PublicKey from the provided buffer. + UnmarshalBinaryPrivateKey([]byte) (PrivateKey, error) + + // Size of binary marshalled public keys. + PublicKeySize() int + + // Size of binary marshalled public keys. + PrivateKeySize() int + + // Size of signatures. + SignatureSize() int + + // Size of seeds. + SeedSize() int + + // Returns whether contexts are supported. + SupportsContext() bool +} + +var ( + // ErrTypeMismatch is the error used if types of, for instance, private + // and public keys don't match. + ErrTypeMismatch = errors.New("types mismatch") + + // ErrSeedSize is the error used if the provided seed is of the wrong + // size. + ErrSeedSize = errors.New("wrong seed size") + + // ErrPubKeySize is the error used if the provided public key is of + // the wrong size. + ErrPubKeySize = errors.New("wrong size for public key") + + // ErrPrivKeySize is the error used if the provided private key is of + // the wrong size. + ErrPrivKeySize = errors.New("wrong size for private key") + + // ErrContextNotSupported is the error used if a context is not + // supported. + ErrContextNotSupported = errors.New("context not supported") +) diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x.go b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x.go new file mode 100644 index 00000000000..20ac96f0068 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x.go @@ -0,0 +1,163 @@ +// Package keccakf1600 provides a two and four-way Keccak-f[1600] permutation in parallel. +// +// Keccak-f[1600] is the permutation underlying several algorithms such as +// Keccak, SHA3 and SHAKE. Running two or four permutations in parallel is +// useful in some scenarios like in hash-based signatures. +// +// # Limitations +// +// Note that not all the architectures support SIMD instructions. This package +// uses AVX2 instructions that are available in some AMD64 architectures +// and NEON instructions that are available in some ARM64 architectures. +// +// For those systems not supporting these, the package still provides the +// expected functionality by means of a generic and slow implementation. +// The recommendation is to beforehand verify IsEnabledX4() and IsEnabledX2() +// to determine if the current system supports the SIMD implementation. +package keccakf1600 + +import ( + "runtime" + "unsafe" + + "github.com/cloudflare/circl/internal/sha3" + "golang.org/x/sys/cpu" +) + +// StateX4 contains state for the four-way permutation including the four +// interleaved [25]uint64 buffers. Call Initialize() before use to initialize +// and get a pointer to the interleaved buffer. +type StateX4 struct { + // Go guarantees a to be aligned on 8 bytes, whereas we need it to be + // aligned on 32 bytes for bet performance. Thus we leave some headroom + // to be able to move the start of the state. + + // 4 x 25 uint64s for the interleaved states and three uint64s headroom + // to fix alignment. + a [103]uint64 + + // Offset into a that is 32 byte aligned. + offset int + + // If true, permute will use 12-round keccak instead of 24-round keccak + turbo bool +} + +// StateX2 contains state for the two-way permutation including the two +// interleaved [25]uint64 buffers. Call Initialize() before use to initialize +// and get a pointer to the interleaved buffer. +type StateX2 struct { + // Go guarantees a to be aligned on 8 bytes, whereas we need it to be + // aligned on 32 bytes for bet performance. Thus we leave some headroom + // to be able to move the start of the state. + + // 2 x 25 uint64s for the interleaved states and three uint64s headroom + // to fix alignment. + a [53]uint64 + + // Offset into a that is 32 byte aligned. + offset int + + // If true, permute will use 12-round keccak instead of 24-round keccak + turbo bool +} + +// IsEnabledX4 returns true if the architecture supports a four-way SIMD +// implementation provided in this package. +func IsEnabledX4() bool { return cpu.X86.HasAVX2 } + +// IsEnabledX2 returns true if the architecture supports a two-way SIMD +// implementation provided in this package. +func IsEnabledX2() bool { return enabledX2 } + +// Initialize the state and returns the buffer on which the four permutations +// will act: a uint64 slice of length 100. The first permutation will act +// on {a[0], a[4], ..., a[96]}, the second on {a[1], a[5], ..., a[97]}, etc. +// If turbo is true, applies 12-round variant instead of the usual 24. +func (s *StateX4) Initialize(turbo bool) []uint64 { + s.turbo = turbo + rp := unsafe.Pointer(&s.a[0]) + + // uint64s are always aligned by a multiple of 8. Compute the remainder + // of the address modulo 32 divided by 8. + rem := (int(uintptr(rp)&31) >> 3) + + if rem != 0 { + s.offset = 4 - rem + } + + // The slice we return will be aligned on 32 byte boundary. + return s.a[s.offset : s.offset+100] +} + +// Initialize the state and returns the buffer on which the two permutations +// will act: a uint64 slice of length 50. The first permutation will act +// on {a[0], a[2], ..., a[48]} and the second on {a[1], a[3], ..., a[49]}. +// If turbo is true, applies 12-round variant instead of the usual 24. +func (s *StateX2) Initialize(turbo bool) []uint64 { + s.turbo = turbo + rp := unsafe.Pointer(&s.a[0]) + + // uint64s are always aligned by a multiple of 8. Compute the remainder + // of the address modulo 32 divided by 8. + rem := (int(uintptr(rp)&31) >> 3) + + if rem != 0 { + s.offset = 4 - rem + } + + // The slice we return will be aligned on 32 byte boundary. + return s.a[s.offset : s.offset+50] +} + +// Permute performs the four parallel Keccak-f[1600]s interleaved on the slice +// returned from Initialize(). +func (s *StateX4) Permute() { + if IsEnabledX4() { + permuteSIMDx4(s.a[s.offset:], s.turbo) + } else { + permuteScalarX4(s.a[s.offset:], s.turbo) // A slower generic implementation. + } +} + +// Permute performs the two parallel Keccak-f[1600]s interleaved on the slice +// returned from Initialize(). +func (s *StateX2) Permute() { + if IsEnabledX2() { + permuteSIMDx2(s.a[s.offset:], s.turbo) + } else { + permuteScalarX2(s.a[s.offset:], s.turbo) // A slower generic implementation. + } +} + +func permuteScalarX4(a []uint64, turbo bool) { + var buf [25]uint64 + for i := 0; i < 4; i++ { + for j := 0; j < 25; j++ { + buf[j] = a[4*j+i] + } + sha3.KeccakF1600(&buf, turbo) + for j := 0; j < 25; j++ { + a[4*j+i] = buf[j] + } + } +} + +func permuteScalarX2(a []uint64, turbo bool) { + var buf [25]uint64 + for i := 0; i < 2; i++ { + for j := 0; j < 25; j++ { + buf[j] = a[2*j+i] + } + sha3.KeccakF1600(&buf, turbo) + for j := 0; j < 25; j++ { + a[2*j+i] = buf[j] + } + } +} + +var enabledX2 bool + +func init() { + enabledX2 = runtime.GOARCH == "arm64" && runtime.GOOS == "darwin" +} diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.go b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.go new file mode 100644 index 00000000000..0cb9692c327 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.go @@ -0,0 +1,13 @@ +//go:build arm64 && go1.16 && !purego +// +build arm64,go1.16,!purego + +package keccakf1600 + +import "github.com/cloudflare/circl/internal/sha3" + +func permuteSIMDx2(state []uint64, turbo bool) { f1600x2ARM(&state[0], &sha3.RC, turbo) } + +func permuteSIMDx4(state []uint64, turbo bool) { permuteScalarX4(state, turbo) } + +//go:noescape +func f1600x2ARM(state *uint64, rc *[24]uint64, turbo bool) diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.s b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.s new file mode 100644 index 00000000000..998aeca5b4c --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.s @@ -0,0 +1,136 @@ +// +build arm64,go1.16,!purego + +// Taken from https://github.com/bwesterb/armed-keccak + +#include "textflag.h" + +// func f1600x2ARM(state *uint64, rc *[24]uint64, turbo bool) +TEXT ·f1600x2ARM(SB), NOSPLIT, $0-17 + MOVD state+0(FP), R0 + MOVD rc+8(FP), R1 + MOVD R0, R2 + MOVD $24, R3 + + VLD1.P 64(R0), [ V0.B16, V1.B16, V2.B16, V3.B16] + VLD1.P 64(R0), [ V4.B16, V5.B16, V6.B16, V7.B16] + VLD1.P 64(R0), [ V8.B16, V9.B16, V10.B16, V11.B16] + VLD1.P 64(R0), [V12.B16, V13.B16, V14.B16, V15.B16] + VLD1.P 64(R0), [V16.B16, V17.B16, V18.B16, V19.B16] + VLD1.P 64(R0), [V20.B16, V21.B16, V22.B16, V23.B16] + VLD1.P (R0), [V24.B16] + + MOVBU turbo+16(FP), R4 + CBZ R4, loop + + SUB $12, R3, R3 + ADD $96, R1, R1 + +loop: + // Execute theta but without xorring into the state yet. + VEOR3 V10.B16, V5.B16, V0.B16, V25.B16 + VEOR3 V11.B16, V6.B16, V1.B16, V26.B16 + VEOR3 V12.B16, V7.B16, V2.B16, V27.B16 + VEOR3 V13.B16, V8.B16, V3.B16, V28.B16 + VEOR3 V14.B16, V9.B16, V4.B16, V29.B16 + + VEOR3 V20.B16, V15.B16, V25.B16, V25.B16 + VEOR3 V21.B16, V16.B16, V26.B16, V26.B16 + VEOR3 V22.B16, V17.B16, V27.B16, V27.B16 + VEOR3 V23.B16, V18.B16, V28.B16, V28.B16 + VEOR3 V24.B16, V19.B16, V29.B16, V29.B16 + + // Xor parities from step theta into the state at the same time as + // exeuting rho and pi. + VRAX1 V26.D2, V29.D2, V30.D2 + VRAX1 V29.D2, V27.D2, V29.D2 + VRAX1 V27.D2, V25.D2, V27.D2 + VRAX1 V25.D2, V28.D2, V25.D2 + VRAX1 V28.D2, V26.D2, V28.D2 + + VEOR V30.B16, V0.B16, V0.B16 + VMOV V1.B16, V31.B16 + + VXAR $20, V27.D2, V6.D2, V1.D2 + VXAR $44, V25.D2, V9.D2, V6.D2 + VXAR $3 , V28.D2, V22.D2, V9.D2 + VXAR $25, V25.D2, V14.D2, V22.D2 + VXAR $46, V30.D2, V20.D2, V14.D2 + VXAR $2 , V28.D2, V2.D2, V20.D2 + VXAR $21, V28.D2, V12.D2, V2.D2 + VXAR $39, V29.D2, V13.D2, V12.D2 + VXAR $56, V25.D2, V19.D2, V13.D2 + VXAR $8 , V29.D2, V23.D2, V19.D2 + VXAR $23, V30.D2, V15.D2, V23.D2 + VXAR $37, V25.D2, V4.D2, V15.D2 + VXAR $50, V25.D2, V24.D2, V4.D2 + VXAR $62, V27.D2, V21.D2, V24.D2 + VXAR $9 , V29.D2, V8.D2, V21.D2 + VXAR $19, V27.D2, V16.D2, V8.D2 + VXAR $28, V30.D2, V5.D2, V16.D2 + VXAR $36, V29.D2, V3.D2, V5.D2 + VXAR $43, V29.D2, V18.D2, V3.D2 + VXAR $49, V28.D2, V17.D2, V18.D2 + VXAR $54, V27.D2, V11.D2, V17.D2 + VXAR $58, V28.D2, V7.D2, V11.D2 + VXAR $61, V30.D2, V10.D2, V7.D2 + VXAR $63, V27.D2, V31.D2, V10.D2 + + // Chi + VBCAX V1.B16, V2.B16, V0.B16, V25.B16 + VBCAX V2.B16, V3.B16, V1.B16, V26.B16 + VBCAX V3.B16, V4.B16, V2.B16, V2.B16 + VBCAX V4.B16, V0.B16, V3.B16, V3.B16 + VBCAX V0.B16, V1.B16, V4.B16, V4.B16 + VMOV V25.B16, V0.B16 + VMOV V26.B16, V1.B16 + + VBCAX V6.B16, V7.B16, V5.B16, V25.B16 + VBCAX V7.B16, V8.B16, V6.B16, V26.B16 + VBCAX V8.B16, V9.B16, V7.B16, V7.B16 + VBCAX V9.B16, V5.B16, V8.B16, V8.B16 + VBCAX V5.B16, V6.B16, V9.B16, V9.B16 + VMOV V25.B16, V5.B16 + VMOV V26.B16, V6.B16 + + VBCAX V11.B16, V12.B16, V10.B16, V25.B16 + VBCAX V12.B16, V13.B16, V11.B16, V26.B16 + VBCAX V13.B16, V14.B16, V12.B16, V12.B16 + VBCAX V14.B16, V10.B16, V13.B16, V13.B16 + VBCAX V10.B16, V11.B16, V14.B16, V14.B16 + VMOV V25.B16, V10.B16 + VMOV V26.B16, V11.B16 + + VBCAX V16.B16, V17.B16, V15.B16, V25.B16 + VBCAX V17.B16, V18.B16, V16.B16, V26.B16 + VBCAX V18.B16, V19.B16, V17.B16, V17.B16 + VBCAX V19.B16, V15.B16, V18.B16, V18.B16 + VBCAX V15.B16, V16.B16, V19.B16, V19.B16 + VMOV V25.B16, V15.B16 + VMOV V26.B16, V16.B16 + + VBCAX V21.B16, V22.B16, V20.B16, V25.B16 + VBCAX V22.B16, V23.B16, V21.B16, V26.B16 + VBCAX V23.B16, V24.B16, V22.B16, V22.B16 + VBCAX V24.B16, V20.B16, V23.B16, V23.B16 + VBCAX V20.B16, V21.B16, V24.B16, V24.B16 + VMOV V25.B16, V20.B16 + VMOV V26.B16, V21.B16 + + // Iota + VLD1R.P 8(R1), [V25.D2] + VEOR V25.B16, V0.B16, V0.B16 + + SUBS $1, R3, R3 + CBNZ R3, loop + + MOVD R2, R0 + + VST1.P [ V0.B16, V1.B16, V2.B16, V3.B16], 64(R0) + VST1.P [ V4.B16, V5.B16, V6.B16, V7.B16], 64(R0) + VST1.P [ V8.B16, V9.B16, V10.B16, V11.B16], 64(R0) + VST1.P [V12.B16, V13.B16, V14.B16, V15.B16], 64(R0) + VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R0) + VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R0) + VST1.P [V24.B16], (R0) + + RET diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.go b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.go new file mode 100644 index 00000000000..bf5b865d0b6 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.go @@ -0,0 +1,10 @@ +//go:build amd64 && !purego +// +build amd64,!purego + +package keccakf1600 + +import "github.com/cloudflare/circl/internal/sha3" + +func permuteSIMDx4(state []uint64, turbo bool) { f1600x4AVX2(&state[0], &sha3.RC, turbo) } + +func permuteSIMDx2(state []uint64, turbo bool) { permuteScalarX2(state, turbo) } diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.s b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.s new file mode 100644 index 00000000000..67b64550c26 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.s @@ -0,0 +1,899 @@ +// Code generated by command: go run src.go -out ../../f1600x4_amd64.s -stubs ../../f1600x4stubs_amd64.go -pkg keccakf1600. DO NOT EDIT. + +//go:build amd64 && !purego + +#include "textflag.h" + +// func f1600x4AVX2(state *uint64, rc *[24]uint64, turbo bool) +// Requires: AVX, AVX2 +TEXT ·f1600x4AVX2(SB), NOSPLIT, $0-17 + MOVQ state+0(FP), AX + MOVQ rc+8(FP), CX + MOVQ $0x0000000000000006, DX + MOVBQZX turbo+16(FP), BX + TESTQ BX, BX + JZ loop + MOVQ $0x0000000000000003, DX + ADDQ $0x60, CX + +loop: + VMOVDQA (AX), Y0 + VMOVDQA 32(AX), Y1 + VMOVDQA 64(AX), Y2 + VMOVDQA 96(AX), Y3 + VMOVDQA 128(AX), Y4 + VPXOR 160(AX), Y0, Y0 + VPXOR 192(AX), Y1, Y1 + VPXOR 224(AX), Y2, Y2 + VPXOR 256(AX), Y3, Y3 + VPXOR 288(AX), Y4, Y4 + VPXOR 320(AX), Y0, Y0 + VPXOR 352(AX), Y1, Y1 + VPXOR 384(AX), Y2, Y2 + VPXOR 416(AX), Y3, Y3 + VPXOR 448(AX), Y4, Y4 + VPXOR 480(AX), Y0, Y0 + VPXOR 512(AX), Y1, Y1 + VPXOR 544(AX), Y2, Y2 + VPXOR 576(AX), Y3, Y3 + VPXOR 608(AX), Y4, Y4 + VPXOR 640(AX), Y0, Y0 + VPXOR 672(AX), Y1, Y1 + VPXOR 704(AX), Y2, Y2 + VPXOR 736(AX), Y3, Y3 + VPXOR 768(AX), Y4, Y4 + VPSLLQ $0x01, Y1, Y5 + VPSLLQ $0x01, Y2, Y6 + VPSLLQ $0x01, Y3, Y7 + VPSLLQ $0x01, Y4, Y8 + VPSLLQ $0x01, Y0, Y9 + VPSRLQ $0x3f, Y1, Y10 + VPSRLQ $0x3f, Y2, Y11 + VPSRLQ $0x3f, Y3, Y12 + VPSRLQ $0x3f, Y4, Y13 + VPSRLQ $0x3f, Y0, Y14 + VPOR Y5, Y10, Y10 + VPOR Y6, Y11, Y11 + VPOR Y7, Y12, Y12 + VPOR Y8, Y13, Y13 + VPOR Y9, Y14, Y14 + VPXOR Y10, Y4, Y10 + VPXOR Y11, Y0, Y11 + VPXOR Y12, Y1, Y12 + VPXOR Y13, Y2, Y13 + VPXOR Y14, Y3, Y14 + VPXOR (AX), Y10, Y0 + VPXOR 192(AX), Y11, Y1 + VPXOR 384(AX), Y12, Y2 + VPXOR 576(AX), Y13, Y3 + VPXOR 768(AX), Y14, Y4 + VPSLLQ $0x2c, Y1, Y6 + VPSLLQ $0x2b, Y2, Y7 + VPSLLQ $0x15, Y3, Y8 + VPSLLQ $0x0e, Y4, Y9 + VPSRLQ $0x14, Y1, Y1 + VPSRLQ $0x15, Y2, Y2 + VPSRLQ $0x2b, Y3, Y3 + VPSRLQ $0x32, Y4, Y4 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VPBROADCASTQ (CX), Y0 + VPXOR Y0, Y5, Y5 + VMOVDQA Y5, (AX) + VMOVDQA Y6, 192(AX) + VMOVDQA Y7, 384(AX) + VMOVDQA Y8, 576(AX) + VMOVDQA Y9, 768(AX) + VPXOR 96(AX), Y13, Y0 + VPXOR 288(AX), Y14, Y1 + VPXOR 320(AX), Y10, Y2 + VPXOR 512(AX), Y11, Y3 + VPXOR 704(AX), Y12, Y4 + VPSLLQ $0x1c, Y0, Y5 + VPSLLQ $0x14, Y1, Y6 + VPSLLQ $0x03, Y2, Y7 + VPSLLQ $0x2d, Y3, Y8 + VPSLLQ $0x3d, Y4, Y9 + VPSRLQ $0x24, Y0, Y0 + VPSRLQ $0x2c, Y1, Y1 + VPSRLQ $0x3d, Y2, Y2 + VPSRLQ $0x13, Y3, Y3 + VPSRLQ $0x03, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 320(AX) + VMOVDQA Y6, 512(AX) + VMOVDQA Y7, 704(AX) + VMOVDQA Y8, 96(AX) + VMOVDQA Y9, 288(AX) + VPXOR 32(AX), Y11, Y0 + VPXOR 224(AX), Y12, Y1 + VPXOR 416(AX), Y13, Y2 + VPXOR 608(AX), Y14, Y3 + VPXOR 640(AX), Y10, Y4 + VPSLLQ $0x01, Y0, Y5 + VPSLLQ $0x06, Y1, Y6 + VPSLLQ $0x19, Y2, Y7 + VPSLLQ $0x08, Y3, Y8 + VPSLLQ $0x12, Y4, Y9 + VPSRLQ $0x3f, Y0, Y0 + VPSRLQ $0x3a, Y1, Y1 + VPSRLQ $0x27, Y2, Y2 + VPSRLQ $0x38, Y3, Y3 + VPSRLQ $0x2e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 640(AX) + VMOVDQA Y6, 32(AX) + VMOVDQA Y7, 224(AX) + VMOVDQA Y8, 416(AX) + VMOVDQA Y9, 608(AX) + VPXOR 128(AX), Y14, Y0 + VPXOR 160(AX), Y10, Y1 + VPXOR 352(AX), Y11, Y2 + VPXOR 544(AX), Y12, Y3 + VPXOR 736(AX), Y13, Y4 + VPSLLQ $0x1b, Y0, Y5 + VPSLLQ $0x24, Y1, Y6 + VPSLLQ $0x0a, Y2, Y7 + VPSLLQ $0x0f, Y3, Y8 + VPSLLQ $0x38, Y4, Y9 + VPSRLQ $0x25, Y0, Y0 + VPSRLQ $0x1c, Y1, Y1 + VPSRLQ $0x36, Y2, Y2 + VPSRLQ $0x31, Y3, Y3 + VPSRLQ $0x08, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 160(AX) + VMOVDQA Y6, 352(AX) + VMOVDQA Y7, 544(AX) + VMOVDQA Y8, 736(AX) + VMOVDQA Y9, 128(AX) + VPXOR 64(AX), Y12, Y0 + VPXOR 256(AX), Y13, Y1 + VPXOR 448(AX), Y14, Y2 + VPXOR 480(AX), Y10, Y3 + VPXOR 672(AX), Y11, Y4 + VPSLLQ $0x3e, Y0, Y5 + VPSLLQ $0x37, Y1, Y6 + VPSLLQ $0x27, Y2, Y7 + VPSLLQ $0x29, Y3, Y8 + VPSLLQ $0x02, Y4, Y9 + VPSRLQ $0x02, Y0, Y0 + VPSRLQ $0x09, Y1, Y1 + VPSRLQ $0x19, Y2, Y2 + VPSRLQ $0x17, Y3, Y3 + VPSRLQ $0x3e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 480(AX) + VMOVDQA Y6, 672(AX) + VMOVDQA Y7, 64(AX) + VMOVDQA Y8, 256(AX) + VMOVDQA Y9, 448(AX) + VMOVDQA (AX), Y0 + VMOVDQA 32(AX), Y1 + VMOVDQA 64(AX), Y2 + VMOVDQA 96(AX), Y3 + VMOVDQA 128(AX), Y4 + VPXOR 160(AX), Y0, Y0 + VPXOR 192(AX), Y1, Y1 + VPXOR 224(AX), Y2, Y2 + VPXOR 256(AX), Y3, Y3 + VPXOR 288(AX), Y4, Y4 + VPXOR 320(AX), Y0, Y0 + VPXOR 352(AX), Y1, Y1 + VPXOR 384(AX), Y2, Y2 + VPXOR 416(AX), Y3, Y3 + VPXOR 448(AX), Y4, Y4 + VPXOR 480(AX), Y0, Y0 + VPXOR 512(AX), Y1, Y1 + VPXOR 544(AX), Y2, Y2 + VPXOR 576(AX), Y3, Y3 + VPXOR 608(AX), Y4, Y4 + VPXOR 640(AX), Y0, Y0 + VPXOR 672(AX), Y1, Y1 + VPXOR 704(AX), Y2, Y2 + VPXOR 736(AX), Y3, Y3 + VPXOR 768(AX), Y4, Y4 + VPSLLQ $0x01, Y1, Y5 + VPSLLQ $0x01, Y2, Y6 + VPSLLQ $0x01, Y3, Y7 + VPSLLQ $0x01, Y4, Y8 + VPSLLQ $0x01, Y0, Y9 + VPSRLQ $0x3f, Y1, Y10 + VPSRLQ $0x3f, Y2, Y11 + VPSRLQ $0x3f, Y3, Y12 + VPSRLQ $0x3f, Y4, Y13 + VPSRLQ $0x3f, Y0, Y14 + VPOR Y5, Y10, Y10 + VPOR Y6, Y11, Y11 + VPOR Y7, Y12, Y12 + VPOR Y8, Y13, Y13 + VPOR Y9, Y14, Y14 + VPXOR Y10, Y4, Y10 + VPXOR Y11, Y0, Y11 + VPXOR Y12, Y1, Y12 + VPXOR Y13, Y2, Y13 + VPXOR Y14, Y3, Y14 + VPXOR (AX), Y10, Y0 + VPXOR 512(AX), Y11, Y1 + VPXOR 224(AX), Y12, Y2 + VPXOR 736(AX), Y13, Y3 + VPXOR 448(AX), Y14, Y4 + VPSLLQ $0x2c, Y1, Y6 + VPSLLQ $0x2b, Y2, Y7 + VPSLLQ $0x15, Y3, Y8 + VPSLLQ $0x0e, Y4, Y9 + VPSRLQ $0x14, Y1, Y1 + VPSRLQ $0x15, Y2, Y2 + VPSRLQ $0x2b, Y3, Y3 + VPSRLQ $0x32, Y4, Y4 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VPBROADCASTQ 8(CX), Y0 + VPXOR Y0, Y5, Y5 + VMOVDQA Y5, (AX) + VMOVDQA Y6, 512(AX) + VMOVDQA Y7, 224(AX) + VMOVDQA Y8, 736(AX) + VMOVDQA Y9, 448(AX) + VPXOR 576(AX), Y13, Y0 + VPXOR 288(AX), Y14, Y1 + VPXOR 640(AX), Y10, Y2 + VPXOR 352(AX), Y11, Y3 + VPXOR 64(AX), Y12, Y4 + VPSLLQ $0x1c, Y0, Y5 + VPSLLQ $0x14, Y1, Y6 + VPSLLQ $0x03, Y2, Y7 + VPSLLQ $0x2d, Y3, Y8 + VPSLLQ $0x3d, Y4, Y9 + VPSRLQ $0x24, Y0, Y0 + VPSRLQ $0x2c, Y1, Y1 + VPSRLQ $0x3d, Y2, Y2 + VPSRLQ $0x13, Y3, Y3 + VPSRLQ $0x03, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 640(AX) + VMOVDQA Y6, 352(AX) + VMOVDQA Y7, 64(AX) + VMOVDQA Y8, 576(AX) + VMOVDQA Y9, 288(AX) + VPXOR 192(AX), Y11, Y0 + VPXOR 704(AX), Y12, Y1 + VPXOR 416(AX), Y13, Y2 + VPXOR 128(AX), Y14, Y3 + VPXOR 480(AX), Y10, Y4 + VPSLLQ $0x01, Y0, Y5 + VPSLLQ $0x06, Y1, Y6 + VPSLLQ $0x19, Y2, Y7 + VPSLLQ $0x08, Y3, Y8 + VPSLLQ $0x12, Y4, Y9 + VPSRLQ $0x3f, Y0, Y0 + VPSRLQ $0x3a, Y1, Y1 + VPSRLQ $0x27, Y2, Y2 + VPSRLQ $0x38, Y3, Y3 + VPSRLQ $0x2e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 480(AX) + VMOVDQA Y6, 192(AX) + VMOVDQA Y7, 704(AX) + VMOVDQA Y8, 416(AX) + VMOVDQA Y9, 128(AX) + VPXOR 768(AX), Y14, Y0 + VPXOR 320(AX), Y10, Y1 + VPXOR 32(AX), Y11, Y2 + VPXOR 544(AX), Y12, Y3 + VPXOR 256(AX), Y13, Y4 + VPSLLQ $0x1b, Y0, Y5 + VPSLLQ $0x24, Y1, Y6 + VPSLLQ $0x0a, Y2, Y7 + VPSLLQ $0x0f, Y3, Y8 + VPSLLQ $0x38, Y4, Y9 + VPSRLQ $0x25, Y0, Y0 + VPSRLQ $0x1c, Y1, Y1 + VPSRLQ $0x36, Y2, Y2 + VPSRLQ $0x31, Y3, Y3 + VPSRLQ $0x08, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 320(AX) + VMOVDQA Y6, 32(AX) + VMOVDQA Y7, 544(AX) + VMOVDQA Y8, 256(AX) + VMOVDQA Y9, 768(AX) + VPXOR 384(AX), Y12, Y0 + VPXOR 96(AX), Y13, Y1 + VPXOR 608(AX), Y14, Y2 + VPXOR 160(AX), Y10, Y3 + VPXOR 672(AX), Y11, Y4 + VPSLLQ $0x3e, Y0, Y5 + VPSLLQ $0x37, Y1, Y6 + VPSLLQ $0x27, Y2, Y7 + VPSLLQ $0x29, Y3, Y8 + VPSLLQ $0x02, Y4, Y9 + VPSRLQ $0x02, Y0, Y0 + VPSRLQ $0x09, Y1, Y1 + VPSRLQ $0x19, Y2, Y2 + VPSRLQ $0x17, Y3, Y3 + VPSRLQ $0x3e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 160(AX) + VMOVDQA Y6, 672(AX) + VMOVDQA Y7, 384(AX) + VMOVDQA Y8, 96(AX) + VMOVDQA Y9, 608(AX) + VMOVDQA (AX), Y0 + VMOVDQA 32(AX), Y1 + VMOVDQA 64(AX), Y2 + VMOVDQA 96(AX), Y3 + VMOVDQA 128(AX), Y4 + VPXOR 160(AX), Y0, Y0 + VPXOR 192(AX), Y1, Y1 + VPXOR 224(AX), Y2, Y2 + VPXOR 256(AX), Y3, Y3 + VPXOR 288(AX), Y4, Y4 + VPXOR 320(AX), Y0, Y0 + VPXOR 352(AX), Y1, Y1 + VPXOR 384(AX), Y2, Y2 + VPXOR 416(AX), Y3, Y3 + VPXOR 448(AX), Y4, Y4 + VPXOR 480(AX), Y0, Y0 + VPXOR 512(AX), Y1, Y1 + VPXOR 544(AX), Y2, Y2 + VPXOR 576(AX), Y3, Y3 + VPXOR 608(AX), Y4, Y4 + VPXOR 640(AX), Y0, Y0 + VPXOR 672(AX), Y1, Y1 + VPXOR 704(AX), Y2, Y2 + VPXOR 736(AX), Y3, Y3 + VPXOR 768(AX), Y4, Y4 + VPSLLQ $0x01, Y1, Y5 + VPSLLQ $0x01, Y2, Y6 + VPSLLQ $0x01, Y3, Y7 + VPSLLQ $0x01, Y4, Y8 + VPSLLQ $0x01, Y0, Y9 + VPSRLQ $0x3f, Y1, Y10 + VPSRLQ $0x3f, Y2, Y11 + VPSRLQ $0x3f, Y3, Y12 + VPSRLQ $0x3f, Y4, Y13 + VPSRLQ $0x3f, Y0, Y14 + VPOR Y5, Y10, Y10 + VPOR Y6, Y11, Y11 + VPOR Y7, Y12, Y12 + VPOR Y8, Y13, Y13 + VPOR Y9, Y14, Y14 + VPXOR Y10, Y4, Y10 + VPXOR Y11, Y0, Y11 + VPXOR Y12, Y1, Y12 + VPXOR Y13, Y2, Y13 + VPXOR Y14, Y3, Y14 + VPXOR (AX), Y10, Y0 + VPXOR 352(AX), Y11, Y1 + VPXOR 704(AX), Y12, Y2 + VPXOR 256(AX), Y13, Y3 + VPXOR 608(AX), Y14, Y4 + VPSLLQ $0x2c, Y1, Y6 + VPSLLQ $0x2b, Y2, Y7 + VPSLLQ $0x15, Y3, Y8 + VPSLLQ $0x0e, Y4, Y9 + VPSRLQ $0x14, Y1, Y1 + VPSRLQ $0x15, Y2, Y2 + VPSRLQ $0x2b, Y3, Y3 + VPSRLQ $0x32, Y4, Y4 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VPBROADCASTQ 16(CX), Y0 + VPXOR Y0, Y5, Y5 + VMOVDQA Y5, (AX) + VMOVDQA Y6, 352(AX) + VMOVDQA Y7, 704(AX) + VMOVDQA Y8, 256(AX) + VMOVDQA Y9, 608(AX) + VPXOR 736(AX), Y13, Y0 + VPXOR 288(AX), Y14, Y1 + VPXOR 480(AX), Y10, Y2 + VPXOR 32(AX), Y11, Y3 + VPXOR 384(AX), Y12, Y4 + VPSLLQ $0x1c, Y0, Y5 + VPSLLQ $0x14, Y1, Y6 + VPSLLQ $0x03, Y2, Y7 + VPSLLQ $0x2d, Y3, Y8 + VPSLLQ $0x3d, Y4, Y9 + VPSRLQ $0x24, Y0, Y0 + VPSRLQ $0x2c, Y1, Y1 + VPSRLQ $0x3d, Y2, Y2 + VPSRLQ $0x13, Y3, Y3 + VPSRLQ $0x03, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 480(AX) + VMOVDQA Y6, 32(AX) + VMOVDQA Y7, 384(AX) + VMOVDQA Y8, 736(AX) + VMOVDQA Y9, 288(AX) + VPXOR 512(AX), Y11, Y0 + VPXOR 64(AX), Y12, Y1 + VPXOR 416(AX), Y13, Y2 + VPXOR 768(AX), Y14, Y3 + VPXOR 160(AX), Y10, Y4 + VPSLLQ $0x01, Y0, Y5 + VPSLLQ $0x06, Y1, Y6 + VPSLLQ $0x19, Y2, Y7 + VPSLLQ $0x08, Y3, Y8 + VPSLLQ $0x12, Y4, Y9 + VPSRLQ $0x3f, Y0, Y0 + VPSRLQ $0x3a, Y1, Y1 + VPSRLQ $0x27, Y2, Y2 + VPSRLQ $0x38, Y3, Y3 + VPSRLQ $0x2e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 160(AX) + VMOVDQA Y6, 512(AX) + VMOVDQA Y7, 64(AX) + VMOVDQA Y8, 416(AX) + VMOVDQA Y9, 768(AX) + VPXOR 448(AX), Y14, Y0 + VPXOR 640(AX), Y10, Y1 + VPXOR 192(AX), Y11, Y2 + VPXOR 544(AX), Y12, Y3 + VPXOR 96(AX), Y13, Y4 + VPSLLQ $0x1b, Y0, Y5 + VPSLLQ $0x24, Y1, Y6 + VPSLLQ $0x0a, Y2, Y7 + VPSLLQ $0x0f, Y3, Y8 + VPSLLQ $0x38, Y4, Y9 + VPSRLQ $0x25, Y0, Y0 + VPSRLQ $0x1c, Y1, Y1 + VPSRLQ $0x36, Y2, Y2 + VPSRLQ $0x31, Y3, Y3 + VPSRLQ $0x08, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 640(AX) + VMOVDQA Y6, 192(AX) + VMOVDQA Y7, 544(AX) + VMOVDQA Y8, 96(AX) + VMOVDQA Y9, 448(AX) + VPXOR 224(AX), Y12, Y0 + VPXOR 576(AX), Y13, Y1 + VPXOR 128(AX), Y14, Y2 + VPXOR 320(AX), Y10, Y3 + VPXOR 672(AX), Y11, Y4 + VPSLLQ $0x3e, Y0, Y5 + VPSLLQ $0x37, Y1, Y6 + VPSLLQ $0x27, Y2, Y7 + VPSLLQ $0x29, Y3, Y8 + VPSLLQ $0x02, Y4, Y9 + VPSRLQ $0x02, Y0, Y0 + VPSRLQ $0x09, Y1, Y1 + VPSRLQ $0x19, Y2, Y2 + VPSRLQ $0x17, Y3, Y3 + VPSRLQ $0x3e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 320(AX) + VMOVDQA Y6, 672(AX) + VMOVDQA Y7, 224(AX) + VMOVDQA Y8, 576(AX) + VMOVDQA Y9, 128(AX) + VMOVDQA (AX), Y0 + VMOVDQA 32(AX), Y1 + VMOVDQA 64(AX), Y2 + VMOVDQA 96(AX), Y3 + VMOVDQA 128(AX), Y4 + VPXOR 160(AX), Y0, Y0 + VPXOR 192(AX), Y1, Y1 + VPXOR 224(AX), Y2, Y2 + VPXOR 256(AX), Y3, Y3 + VPXOR 288(AX), Y4, Y4 + VPXOR 320(AX), Y0, Y0 + VPXOR 352(AX), Y1, Y1 + VPXOR 384(AX), Y2, Y2 + VPXOR 416(AX), Y3, Y3 + VPXOR 448(AX), Y4, Y4 + VPXOR 480(AX), Y0, Y0 + VPXOR 512(AX), Y1, Y1 + VPXOR 544(AX), Y2, Y2 + VPXOR 576(AX), Y3, Y3 + VPXOR 608(AX), Y4, Y4 + VPXOR 640(AX), Y0, Y0 + VPXOR 672(AX), Y1, Y1 + VPXOR 704(AX), Y2, Y2 + VPXOR 736(AX), Y3, Y3 + VPXOR 768(AX), Y4, Y4 + VPSLLQ $0x01, Y1, Y5 + VPSLLQ $0x01, Y2, Y6 + VPSLLQ $0x01, Y3, Y7 + VPSLLQ $0x01, Y4, Y8 + VPSLLQ $0x01, Y0, Y9 + VPSRLQ $0x3f, Y1, Y10 + VPSRLQ $0x3f, Y2, Y11 + VPSRLQ $0x3f, Y3, Y12 + VPSRLQ $0x3f, Y4, Y13 + VPSRLQ $0x3f, Y0, Y14 + VPOR Y5, Y10, Y10 + VPOR Y6, Y11, Y11 + VPOR Y7, Y12, Y12 + VPOR Y8, Y13, Y13 + VPOR Y9, Y14, Y14 + VPXOR Y10, Y4, Y10 + VPXOR Y11, Y0, Y11 + VPXOR Y12, Y1, Y12 + VPXOR Y13, Y2, Y13 + VPXOR Y14, Y3, Y14 + VPXOR (AX), Y10, Y0 + VPXOR 32(AX), Y11, Y1 + VPXOR 64(AX), Y12, Y2 + VPXOR 96(AX), Y13, Y3 + VPXOR 128(AX), Y14, Y4 + VPSLLQ $0x2c, Y1, Y6 + VPSLLQ $0x2b, Y2, Y7 + VPSLLQ $0x15, Y3, Y8 + VPSLLQ $0x0e, Y4, Y9 + VPSRLQ $0x14, Y1, Y1 + VPSRLQ $0x15, Y2, Y2 + VPSRLQ $0x2b, Y3, Y3 + VPSRLQ $0x32, Y4, Y4 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VPBROADCASTQ 24(CX), Y0 + VPXOR Y0, Y5, Y5 + VMOVDQA Y5, (AX) + VMOVDQA Y6, 32(AX) + VMOVDQA Y7, 64(AX) + VMOVDQA Y8, 96(AX) + VMOVDQA Y9, 128(AX) + VPXOR 256(AX), Y13, Y0 + VPXOR 288(AX), Y14, Y1 + VPXOR 160(AX), Y10, Y2 + VPXOR 192(AX), Y11, Y3 + VPXOR 224(AX), Y12, Y4 + VPSLLQ $0x1c, Y0, Y5 + VPSLLQ $0x14, Y1, Y6 + VPSLLQ $0x03, Y2, Y7 + VPSLLQ $0x2d, Y3, Y8 + VPSLLQ $0x3d, Y4, Y9 + VPSRLQ $0x24, Y0, Y0 + VPSRLQ $0x2c, Y1, Y1 + VPSRLQ $0x3d, Y2, Y2 + VPSRLQ $0x13, Y3, Y3 + VPSRLQ $0x03, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 160(AX) + VMOVDQA Y6, 192(AX) + VMOVDQA Y7, 224(AX) + VMOVDQA Y8, 256(AX) + VMOVDQA Y9, 288(AX) + VPXOR 352(AX), Y11, Y0 + VPXOR 384(AX), Y12, Y1 + VPXOR 416(AX), Y13, Y2 + VPXOR 448(AX), Y14, Y3 + VPXOR 320(AX), Y10, Y4 + VPSLLQ $0x01, Y0, Y5 + VPSLLQ $0x06, Y1, Y6 + VPSLLQ $0x19, Y2, Y7 + VPSLLQ $0x08, Y3, Y8 + VPSLLQ $0x12, Y4, Y9 + VPSRLQ $0x3f, Y0, Y0 + VPSRLQ $0x3a, Y1, Y1 + VPSRLQ $0x27, Y2, Y2 + VPSRLQ $0x38, Y3, Y3 + VPSRLQ $0x2e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 320(AX) + VMOVDQA Y6, 352(AX) + VMOVDQA Y7, 384(AX) + VMOVDQA Y8, 416(AX) + VMOVDQA Y9, 448(AX) + VPXOR 608(AX), Y14, Y0 + VPXOR 480(AX), Y10, Y1 + VPXOR 512(AX), Y11, Y2 + VPXOR 544(AX), Y12, Y3 + VPXOR 576(AX), Y13, Y4 + VPSLLQ $0x1b, Y0, Y5 + VPSLLQ $0x24, Y1, Y6 + VPSLLQ $0x0a, Y2, Y7 + VPSLLQ $0x0f, Y3, Y8 + VPSLLQ $0x38, Y4, Y9 + VPSRLQ $0x25, Y0, Y0 + VPSRLQ $0x1c, Y1, Y1 + VPSRLQ $0x36, Y2, Y2 + VPSRLQ $0x31, Y3, Y3 + VPSRLQ $0x08, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 480(AX) + VMOVDQA Y6, 512(AX) + VMOVDQA Y7, 544(AX) + VMOVDQA Y8, 576(AX) + VMOVDQA Y9, 608(AX) + VPXOR 704(AX), Y12, Y0 + VPXOR 736(AX), Y13, Y1 + VPXOR 768(AX), Y14, Y2 + VPXOR 640(AX), Y10, Y3 + VPXOR 672(AX), Y11, Y4 + VPSLLQ $0x3e, Y0, Y5 + VPSLLQ $0x37, Y1, Y6 + VPSLLQ $0x27, Y2, Y7 + VPSLLQ $0x29, Y3, Y8 + VPSLLQ $0x02, Y4, Y9 + VPSRLQ $0x02, Y0, Y0 + VPSRLQ $0x09, Y1, Y1 + VPSRLQ $0x19, Y2, Y2 + VPSRLQ $0x17, Y3, Y3 + VPSRLQ $0x3e, Y4, Y4 + VPOR Y5, Y0, Y0 + VPOR Y6, Y1, Y1 + VPOR Y7, Y2, Y2 + VPOR Y8, Y3, Y3 + VPOR Y9, Y4, Y4 + VPANDN Y2, Y1, Y5 + VPANDN Y3, Y2, Y6 + VPANDN Y4, Y3, Y7 + VPANDN Y0, Y4, Y8 + VPANDN Y1, Y0, Y9 + VPXOR Y0, Y5, Y5 + VPXOR Y1, Y6, Y6 + VPXOR Y2, Y7, Y7 + VPXOR Y3, Y8, Y8 + VPXOR Y4, Y9, Y9 + VMOVDQA Y5, 640(AX) + VMOVDQA Y6, 672(AX) + VMOVDQA Y7, 704(AX) + VMOVDQA Y8, 736(AX) + VMOVDQA Y9, 768(AX) + ADDQ $0x20, CX + SUBQ $0x00000001, DX + JNZ loop + RET diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4stubs_amd64.go b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4stubs_amd64.go new file mode 100644 index 00000000000..102fdd04d16 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4stubs_amd64.go @@ -0,0 +1,8 @@ +// Code generated by command: go run src.go -out ../../f1600x4_amd64.s -stubs ../../f1600x4stubs_amd64.go -pkg keccakf1600. DO NOT EDIT. + +//go:build amd64 && !purego + +package keccakf1600 + +//go:noescape +func f1600x4AVX2(state *uint64, rc *[24]uint64, turbo bool) diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go new file mode 100644 index 00000000000..0da75e9b776 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go @@ -0,0 +1,8 @@ +//go:build (!amd64 && !arm64) || (arm64 && !go1.16) || purego +// +build !amd64,!arm64 arm64,!go1.16 purego + +package keccakf1600 + +func permuteSIMDx2(state []uint64, turbo bool) { permuteScalarX2(state, turbo) } + +func permuteSIMDx4(state []uint64, turbo bool) { permuteScalarX4(state, turbo) } diff --git a/src/vendor/github.com/cloudflare/circl/xof/k12/k12.go b/src/vendor/github.com/cloudflare/circl/xof/k12/k12.go new file mode 100644 index 00000000000..bbd33d117d0 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/xof/k12/k12.go @@ -0,0 +1,400 @@ +// k12 implements the KangarooTwelve XOF. +// +// KangarooTwelve is being standardised at the CFRG working group +// of the IRTF. This package implements draft 10. +// +// https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/10/ +package k12 + +import ( + "encoding/binary" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/simd/keccakf1600" +) + +const chunkSize = 8192 // aka B + +// KangarooTwelve splits the message into chunks of 8192 bytes each. +// The first chunk is absorbed directly in a TurboSHAKE128 instance, which +// we call the stalk. The subsequent chunks aren't absorbed directly, but +// instead their hash is absorbed: they're like leafs on a stalk. +// If we have a fast TurboSHAKE128 available, we buffer chunks until we have +// enough to do the parallel TurboSHAKE128. If not, we absorb directly into +// a separate TurboSHAKE128 state. + +type State struct { + initialTodo int // Bytes left to absorb for the first chunk. + + stalk sha3.State + + context []byte // context string "C" provided by the user + + // buffer of incoming data so we can do parallel TurboSHAKE128: + // nil when we haven't absorbed the first chunk yet; + // empty if we have, but we do not have a fast parallel TurboSHAKE128; + // and chunkSize*lanes in length if we have. + buf []byte + + offset int // offset in buf or bytes written to leaf + + // Number of chunk hashes ("CV_i") absorbed into the stalk. + chunk uint + + // TurboSHAKE128 instance to compute the leaf in case we don't have + // a fast parallel TurboSHAKE128, viz when lanes == 1. + leaf *sha3.State + + lanes uint8 // number of TurboSHAKE128s to compute in parallel +} + +// NewDraft10 creates a new instance of Kangaroo12 draft version -10. +func NewDraft10(c []byte) State { + var lanes byte = 1 + + if keccakf1600.IsEnabledX4() { + lanes = 4 + } else if keccakf1600.IsEnabledX2() { + lanes = 2 + } + + return newDraft10(c, lanes) +} + +func newDraft10(c []byte, lanes byte) State { + return State{ + initialTodo: chunkSize, + stalk: sha3.NewTurboShake128(0x07), + context: c, + lanes: lanes, + } +} + +func (s *State) Reset() { + s.initialTodo = chunkSize + s.stalk.Reset() + s.stalk.SwitchDS(0x07) + s.buf = nil + s.offset = 0 + s.chunk = 0 +} + +func (s *State) Clone() State { + stalk := s.stalk.Clone().(*sha3.State) + ret := State{ + initialTodo: s.initialTodo, + stalk: *stalk, + context: s.context, + offset: s.offset, + chunk: s.chunk, + lanes: s.lanes, + } + + if s.leaf != nil { + ret.leaf = s.leaf.Clone().(*sha3.State) + } + + if s.buf != nil { + ret.buf = make([]byte, len(s.buf)) + copy(ret.buf, s.buf) + } + + return ret +} + +func Draft10Sum(hash []byte, msg []byte, c []byte) { + // TODO Tweak number of lanes depending on the length of the message + s := NewDraft10(c) + _, _ = s.Write(msg) + _, _ = s.Read(hash) +} + +func (s *State) Write(p []byte) (int, error) { + written := len(p) + + // The first chunk is written directly to the stalk. + if s.initialTodo > 0 { + taken := s.initialTodo + if len(p) < taken { + taken = len(p) + } + headP := p[:taken] + _, _ = s.stalk.Write(headP) + s.initialTodo -= taken + p = p[taken:] + } + + if len(p) == 0 { + return written, nil + } + + // If this is the first bit of data written after the initial chunk, + // we're out of the fast-path and allocate some buffers. + if s.buf == nil { + if s.lanes != 1 { + s.buf = make([]byte, int(s.lanes)*chunkSize) + } else { + // We create the buffer to signal we're past the first chunk, + // but do not use it. + s.buf = make([]byte, 0) + h := sha3.NewTurboShake128(0x0B) + s.leaf = &h + } + _, _ = s.stalk.Write([]byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + s.stalk.SwitchDS(0x06) + } + + // If we're just using one lane, we don't need to cache in a buffer + // for parallel hashing. Instead, we feed directly to TurboSHAKE. + if s.lanes == 1 { + for len(p) > 0 { + // Write to current leaf. + to := chunkSize - s.offset + if len(p) < to { + to = len(p) + } + _, _ = s.leaf.Write(p[:to]) + p = p[to:] + s.offset += to + + // Did we fill the chunk? + if s.offset == chunkSize { + var cv [32]byte + _, _ = s.leaf.Read(cv[:]) + _, _ = s.stalk.Write(cv[:]) + s.leaf.Reset() + s.offset = 0 + s.chunk++ + } + } + + return written, nil + } + + // If we can't fill all our lanes or the buffer isn't empty, we write the + // data to the buffer. + if s.offset != 0 || len(p) < len(s.buf) { + to := len(s.buf) - s.offset + if len(p) < to { + to = len(p) + } + p2 := p[:to] + p = p[to:] + copy(s.buf[s.offset:], p2) + s.offset += to + } + + // Absorb the buffer if we filled it + if s.offset == len(s.buf) { + s.writeX(s.buf) + s.offset = 0 + } + + // Note that at this point we may assume that s.offset = 0 if len(p) != 0 + if len(p) != 0 && s.offset != 0 { + panic("shouldn't happen") + } + + // Absorb a bunch of chunks at the same time. + if len(p) >= int(s.lanes)*chunkSize { + p = s.writeX(p) + } + + // Put the remainder in the buffer. + if len(p) > 0 { + copy(s.buf, p) + s.offset = len(p) + } + + return written, nil +} + +// Absorb a multiple of a multiple of lanes * chunkSize. +// Returns the remainder. +func (s *State) writeX(p []byte) []byte { + switch s.lanes { + case 4: + return s.writeX4(p) + default: + return s.writeX2(p) + } +} + +func (s *State) writeX4(p []byte) []byte { + for len(p) >= 4*chunkSize { + var x4 keccakf1600.StateX4 + a := x4.Initialize(true) + + for offset := 0; offset < 48*168; offset += 168 { + for i := 0; i < 21; i++ { + a[i*4] ^= binary.LittleEndian.Uint64( + p[8*i+offset:], + ) + a[i*4+1] ^= binary.LittleEndian.Uint64( + p[chunkSize+8*i+offset:], + ) + a[i*4+2] ^= binary.LittleEndian.Uint64( + p[chunkSize*2+8*i+offset:], + ) + a[i*4+3] ^= binary.LittleEndian.Uint64( + p[chunkSize*3+8*i+offset:], + ) + } + + x4.Permute() + } + + for i := 0; i < 16; i++ { + a[i*4] ^= binary.LittleEndian.Uint64( + p[8*i+48*168:], + ) + a[i*4+1] ^= binary.LittleEndian.Uint64( + p[chunkSize+8*i+48*168:], + ) + a[i*4+2] ^= binary.LittleEndian.Uint64( + p[chunkSize*2+8*i+48*168:], + ) + a[i*4+3] ^= binary.LittleEndian.Uint64( + p[chunkSize*3+8*i+48*168:], + ) + } + + a[16*4] ^= 0x0b + a[16*4+1] ^= 0x0b + a[16*4+2] ^= 0x0b + a[16*4+3] ^= 0x0b + a[20*4] ^= 0x80 << 56 + a[20*4+1] ^= 0x80 << 56 + a[20*4+2] ^= 0x80 << 56 + a[20*4+3] ^= 0x80 << 56 + + x4.Permute() + + var buf [32 * 4]byte + for i := 0; i < 4; i++ { + binary.LittleEndian.PutUint64(buf[8*i:], a[4*i]) + binary.LittleEndian.PutUint64(buf[32+8*i:], a[4*i+1]) + binary.LittleEndian.PutUint64(buf[32*2+8*i:], a[4*i+2]) + binary.LittleEndian.PutUint64(buf[32*3+8*i:], a[4*i+3]) + } + + _, _ = s.stalk.Write(buf[:]) + p = p[chunkSize*4:] + s.chunk += 4 + } + + return p +} + +func (s *State) writeX2(p []byte) []byte { + // TODO On M2 Pro, 1/3 of the time is spent on this function + // and LittleEndian.Uint64 excluding the actual permutation. + // Rewriting in assembler might be worthwhile. + for len(p) >= 2*chunkSize { + var x2 keccakf1600.StateX2 + a := x2.Initialize(true) + + for offset := 0; offset < 48*168; offset += 168 { + for i := 0; i < 21; i++ { + a[i*2] ^= binary.LittleEndian.Uint64( + p[8*i+offset:], + ) + a[i*2+1] ^= binary.LittleEndian.Uint64( + p[chunkSize+8*i+offset:], + ) + } + + x2.Permute() + } + + for i := 0; i < 16; i++ { + a[i*2] ^= binary.LittleEndian.Uint64( + p[8*i+48*168:], + ) + a[i*2+1] ^= binary.LittleEndian.Uint64( + p[chunkSize+8*i+48*168:], + ) + } + + a[16*2] ^= 0x0b + a[16*2+1] ^= 0x0b + a[20*2] ^= 0x80 << 56 + a[20*2+1] ^= 0x80 << 56 + + x2.Permute() + + var buf [32 * 2]byte + for i := 0; i < 4; i++ { + binary.LittleEndian.PutUint64(buf[8*i:], a[2*i]) + binary.LittleEndian.PutUint64(buf[32+8*i:], a[2*i+1]) + } + + _, _ = s.stalk.Write(buf[:]) + p = p[chunkSize*2:] + s.chunk += 2 + } + + return p +} + +func (s *State) Read(p []byte) (int, error) { + if s.stalk.IsAbsorbing() { + // Write context string C + _, _ = s.Write(s.context) + + // Write length_encode( |C| ) + var buf [9]byte + binary.BigEndian.PutUint64(buf[:8], uint64(len(s.context))) + + // Find first non-zero digit in big endian encoding of context length + i := 0 + for buf[i] == 0 && i < 8 { + i++ + } + + buf[8] = byte(8 - i) // number of bytes to represent |C| + _, _ = s.Write(buf[i:]) + + // We need to write the chunk number if we're past the first chunk. + if s.buf != nil { + // Write last remaining chunk(s) + var cv [32]byte + if s.lanes == 1 { + if s.offset != 0 { + _, _ = s.leaf.Read(cv[:]) + _, _ = s.stalk.Write(cv[:]) + s.chunk++ + } + } else { + remainingBuf := s.buf[:s.offset] + for len(remainingBuf) > 0 { + h := sha3.NewTurboShake128(0x0B) + to := chunkSize + if len(remainingBuf) < to { + to = len(remainingBuf) + } + _, _ = h.Write(remainingBuf[:to]) + _, _ = h.Read(cv[:]) + _, _ = s.stalk.Write(cv[:]) + s.chunk++ + remainingBuf = remainingBuf[to:] + } + } + + // Write length_encode( chunk ) + binary.BigEndian.PutUint64(buf[:8], uint64(s.chunk)) + + // Find first non-zero digit in big endian encoding of number of chunks + i = 0 + for buf[i] == 0 && i < 8 { + i++ + } + + buf[8] = byte(8 - i) // number of bytes to represent number of chunks. + _, _ = s.stalk.Write(buf[i:]) + _, _ = s.stalk.Write([]byte{0xff, 0xff}) + } + } + + return s.stalk.Read(p) +} diff --git a/src/vendor/github.com/cloudflare/circl/xof/xof.go b/src/vendor/github.com/cloudflare/circl/xof/xof.go new file mode 100644 index 00000000000..33485cac570 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/xof/xof.go @@ -0,0 +1,85 @@ +// Package xof provides an interface for eXtendable-Output Functions. +// +// # Available Functions +// +// SHAKE functions are defined in FIPS-202, see https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf. +// BLAKE2Xb and BLAKE2Xs are defined in https://www.blake2.net/blake2x.pdf. +package xof + +import ( + "io" + + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/xof/k12" + + "golang.org/x/crypto/blake2b" + "golang.org/x/crypto/blake2s" +) + +// XOF defines the interface to hash functions that support arbitrary-length output. +type XOF interface { + // Write absorbs more data into the XOF's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the XOF. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset restores the XOF to its initial state and discards all data appended by Write. + Reset() +} + +type ID uint + +const ( + SHAKE128 ID = iota + 1 + SHAKE256 + BLAKE2XB + BLAKE2XS + K12D10 +) + +func (x ID) New() XOF { + switch x { + case SHAKE128: + s := sha3.NewShake128() + return shakeBody{&s} + case SHAKE256: + s := sha3.NewShake256() + return shakeBody{&s} + case BLAKE2XB: + x, _ := blake2b.NewXOF(blake2b.OutputLengthUnknown, nil) + return blake2xb{x} + case BLAKE2XS: + x, _ := blake2s.NewXOF(blake2s.OutputLengthUnknown, nil) + return blake2xs{x} + case K12D10: + x := k12.NewDraft10([]byte{}) + return k12d10{&x} + default: + panic("crypto: requested unavailable XOF function") + } +} + +type shakeBody struct{ sha3.ShakeHash } + +func (s shakeBody) Clone() XOF { return shakeBody{s.ShakeHash.Clone()} } + +type blake2xb struct{ blake2b.XOF } + +func (s blake2xb) Clone() XOF { return blake2xb{s.XOF.Clone()} } + +type blake2xs struct{ blake2s.XOF } + +func (s blake2xs) Clone() XOF { return blake2xs{s.XOF.Clone()} } + +type k12d10 struct{ *k12.State } + +func (s k12d10) Clone() XOF { + x := s.State.Clone() + return k12d10{&x} +} diff --git a/src/vendor/golang.org/x/crypto/blake2b/blake2b.go b/src/vendor/golang.org/x/crypto/blake2b/blake2b.go new file mode 100644 index 00000000000..d2e98d4295b --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/blake2b.go @@ -0,0 +1,291 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 +// and the extendable output function (XOF) BLAKE2Xb. +// +// BLAKE2b is optimized for 64-bit platforms—including NEON-enabled ARMs—and +// produces digests of any size between 1 and 64 bytes. +// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf +// and for BLAKE2Xb see https://blake2.net/blake2x.pdf +// +// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). +// If you need a secret-key MAC (message authentication code), use the New512 +// function with a non-nil key. +// +// BLAKE2X is a construction to compute hash values larger than 64 bytes. It +// can produce hash values between 0 and 4 GiB. +package blake2b + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2b in bytes. + BlockSize = 128 + // The hash size of BLAKE2b-512 in bytes. + Size = 64 + // The hash size of BLAKE2b-384 in bytes. + Size384 = 48 + // The hash size of BLAKE2b-256 in bytes. + Size256 = 32 +) + +var ( + useAVX2 bool + useAVX bool + useSSE4 bool +) + +var ( + errKeySize = errors.New("blake2b: invalid key size") + errHashSize = errors.New("blake2b: invalid hash size") +) + +var iv = [8]uint64{ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, +} + +// Sum512 returns the BLAKE2b-512 checksum of the data. +func Sum512(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// Sum384 returns the BLAKE2b-384 checksum of the data. +func Sum384(data []byte) [Size384]byte { + var sum [Size]byte + var sum384 [Size384]byte + checkSum(&sum, Size384, data) + copy(sum384[:], sum[:Size384]) + return sum384 +} + +// Sum256 returns the BLAKE2b-256 checksum of the data. +func Sum256(data []byte) [Size256]byte { + var sum [Size]byte + var sum256 [Size256]byte + checkSum(&sum, Size256, data) + copy(sum256[:], sum[:Size256]) + return sum256 +} + +// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } + +// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil +// key turns the hash into a MAC. The key must be between zero and 64 bytes long. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } + +// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. +// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. +// The hash size can be a value between 1 and 64 but it is highly recommended to use +// values equal or greater than: +// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). +// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. +func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } + +func newDigest(hashSize int, key []byte) (*digest, error) { + if hashSize < 1 || hashSize > Size { + return nil, errHashSize + } + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + h := iv + h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) + var c [2]uint64 + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint64(BlockSize - offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h[:(hashSize+7)/8] { + binary.LittleEndian.PutUint64(sum[8*i:], v) + } +} + +type digest struct { + h [8]uint64 + c [2]uint64 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +const ( + magic = "b2b" + marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2b: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint64(b, d.h[i]) + } + b = appendUint64(b, d.c[0]) + b = appendUint64(b, d.c[1]) + // Maximum value for size is 64 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2b: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2b: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint64(b) + } + b, d.c[0] = consumeUint64(b) + b, d.c[1] = consumeUint64(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + if len(p) > 0 { + d.offset += copy(d.block[:], p) + } + + return +} + +func (d *digest) Sum(sum []byte) []byte { + var hash [Size]byte + d.finalize(&hash) + return append(sum, hash[:d.size]...) +} + +func (d *digest) finalize(hash *[Size]byte) { + var block [BlockSize]byte + copy(block[:], d.block[:d.offset]) + remaining := uint64(BlockSize - d.offset) + + c := d.c + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + h := d.h + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h { + binary.LittleEndian.PutUint64(hash[8*i:], v) + } +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.BigEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + x := binary.BigEndian.Uint64(b) + return b[8:], x +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go new file mode 100644 index 00000000000..199c21d27aa --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go @@ -0,0 +1,37 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && gc && !purego + +package blake2b + +import "golang.org/x/sys/cpu" + +func init() { + useAVX2 = cpu.X86.HasAVX2 + useAVX = cpu.X86.HasAVX + useSSE4 = cpu.X86.HasSSE41 +} + +//go:noescape +func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + switch { + case useAVX2: + hashBlocksAVX2(h, c, flag, blocks) + case useAVX: + hashBlocksAVX(h, c, flag, blocks) + case useSSE4: + hashBlocksSSE4(h, c, flag, blocks) + default: + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s new file mode 100644 index 00000000000..9ae8206c201 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s @@ -0,0 +1,744 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && gc && !purego + +#include "textflag.h" + +DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 + +#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 +#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 +#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e +#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 +#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 + +#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ + VPADDQ m0, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m1, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y1_Y1; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y3_Y3; \ + VPADDQ m2, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m3, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y3_Y3; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y1_Y1 + +#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E +#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 +#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E +#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 +#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E + +#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n +#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n +#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n +#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n +#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n + +#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 +#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 +#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 +#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 +#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 + +#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 + +#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 +#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 + +// load msg: Y12 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y12, Y12 + +// load msg: Y13 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ + VMOVQ_SI_X13(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X13(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y13, Y13 + +// load msg: Y14 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ + VMOVQ_SI_X14(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X14(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y14, Y14 + +// load msg: Y15 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ + VMOVQ_SI_X15(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X15(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X11(6*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ + LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ + LOAD_MSG_AVX2_Y15(9, 11, 13, 15) + +#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ + LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ + LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ + VMOVQ_SI_X11(11*8); \ + VPSHUFD $0x4E, 0*8(SI), X14; \ + VPINSRQ_1_SI_X11(5*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(12, 2, 7, 3) + +#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ + VMOVQ_SI_X11(5*8); \ + VMOVDQU 11*8(SI), X12; \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + VMOVQ_SI_X13(8*8); \ + VMOVQ_SI_X11(2*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X11(13*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ + LOAD_MSG_AVX2_Y15(14, 6, 1, 4) + +#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ + LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ + LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ + LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ + VMOVQ_SI_X15(6*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X15(10*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ + LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X13(7*8); \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ + LOAD_MSG_AVX2_Y15(1, 12, 8, 13) + +#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ + LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ + LOAD_MSG_AVX2_Y15(13, 5, 14, 9) + +#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ + LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ + LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ + VMOVQ_SI_X14_0; \ + VPSHUFD $0x4E, 8*8(SI), X11; \ + VPINSRQ_1_SI_X14(6*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(7, 3, 2, 11) + +#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ + LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ + LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ + LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ + VMOVQ_SI_X15_0; \ + VMOVQ_SI_X11(6*8); \ + VPINSRQ_1_SI_X15(4*8); \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ + VMOVQ_SI_X12(6*8); \ + VMOVQ_SI_X11(11*8); \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ + VMOVQ_SI_X11(1*8); \ + VMOVDQU 12*8(SI), X14; \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + VMOVQ_SI_X15(2*8); \ + VMOVDQU 4*8(SI), X11; \ + VPINSRQ_1_SI_X15(7*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ + LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ + VMOVQ_SI_X13(2*8); \ + VPSHUFD $0x4E, 5*8(SI), X11; \ + VPINSRQ_1_SI_X13(4*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ + VMOVQ_SI_X15(11*8); \ + VMOVQ_SI_X11(12*8); \ + VPINSRQ_1_SI_X15(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y15, Y15 + +// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, DX + ADDQ $31, DX + ANDQ $~31, DX + + MOVQ CX, 16(DX) + XORQ CX, CX + MOVQ CX, 24(DX) + + VMOVDQU ·AVX2_c40<>(SB), Y4 + VMOVDQU ·AVX2_c48<>(SB), Y5 + + VMOVDQU 0(AX), Y8 + VMOVDQU 32(AX), Y9 + VMOVDQU ·AVX2_iv0<>(SB), Y6 + VMOVDQU ·AVX2_iv1<>(SB), Y7 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + MOVQ R9, 8(DX) + +loop: + ADDQ $128, R8 + MOVQ R8, 0(DX) + CMPQ R8, $128 + JGE noinc + INCQ R9 + MOVQ R9, 8(DX) + +noinc: + VMOVDQA Y8, Y0 + VMOVDQA Y9, Y1 + VMOVDQA Y6, Y2 + VPXOR 0(DX), Y7, Y3 + + LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() + VMOVDQA Y12, 32(DX) + VMOVDQA Y13, 64(DX) + VMOVDQA Y14, 96(DX) + VMOVDQA Y15, 128(DX) + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() + VMOVDQA Y12, 160(DX) + VMOVDQA Y13, 192(DX) + VMOVDQA Y14, 224(DX) + VMOVDQA Y15, 256(DX) + + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + ROUND_AVX2(32(DX), 64(DX), 96(DX), 128(DX), Y10, Y4, Y5) + ROUND_AVX2(160(DX), 192(DX), 224(DX), 256(DX), Y10, Y4, Y5) + + VPXOR Y0, Y8, Y8 + VPXOR Y1, Y9, Y9 + VPXOR Y2, Y8, Y8 + VPXOR Y3, Y9, Y9 + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + + VMOVDQU Y8, 0(AX) + VMOVDQU Y9, 32(AX) + VZEROUPPER + + RET + +#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA +#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB +#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF +#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD +#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE + +#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF +#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF + +#define SHUFFLE_AVX() \ + VMOVDQA X6, X13; \ + VMOVDQA X2, X14; \ + VMOVDQA X4, X6; \ + VPUNPCKLQDQ_X13_X13_X15; \ + VMOVDQA X5, X4; \ + VMOVDQA X6, X5; \ + VPUNPCKHQDQ_X15_X7_X6; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X13_X7; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VPUNPCKHQDQ_X15_X2_X2; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X3_X3; \ + +#define SHUFFLE_AVX_INV() \ + VMOVDQA X2, X13; \ + VMOVDQA X4, X14; \ + VPUNPCKLQDQ_X2_X2_X15; \ + VMOVDQA X5, X4; \ + VPUNPCKHQDQ_X15_X3_X2; \ + VMOVDQA X14, X5; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VMOVDQA X6, X14; \ + VPUNPCKHQDQ_X15_X13_X3; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X6_X6; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X7_X7; \ + +#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + VPADDQ m0, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m1, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFD $-79, v6, v6; \ + VPSHUFD $-79, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPSHUFB c40, v2, v2; \ + VPSHUFB c40, v3, v3; \ + VPADDQ m2, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m3, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFB c48, v6, v6; \ + VPSHUFB c48, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPADDQ v2, v2, t0; \ + VPSRLQ $63, v2, v2; \ + VPXOR t0, v2, v2; \ + VPADDQ v3, v3, t0; \ + VPSRLQ $63, v3, v3; \ + VPXOR t0, v3, v3 + +// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) +// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 +#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X13(i2*8); \ + VMOVQ_SI_X14(i4*8); \ + VMOVQ_SI_X15(i6*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X13(i3*8); \ + VPINSRQ_1_SI_X14(i5*8); \ + VPINSRQ_1_SI_X15(i7*8) + +// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) +#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(1*8); \ + VMOVQ_SI_X15(5*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X13(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(7*8) + +// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) +#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ + VPSHUFD $0x4E, 0*8(SI), X12; \ + VMOVQ_SI_X13(11*8); \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(7*8); \ + VPINSRQ_1_SI_X13(5*8); \ + VPINSRQ_1_SI_X14(2*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) +#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ + VMOVDQU 11*8(SI), X12; \ + VMOVQ_SI_X13(5*8); \ + VMOVQ_SI_X14(8*8); \ + VMOVQ_SI_X15(2*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14_0; \ + VPINSRQ_1_SI_X15(13*8) + +// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) +#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(6*8); \ + VMOVQ_SI_X15_0; \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) +#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ + VMOVQ_SI_X12(9*8); \ + VMOVQ_SI_X13(2*8); \ + VMOVQ_SI_X14_0; \ + VMOVQ_SI_X15(4*8); \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VPINSRQ_1_SI_X15(15*8) + +// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) +#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(11*8); \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X13(8*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) +#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ + MOVQ 0*8(SI), X12; \ + VPSHUFD $0x4E, 8*8(SI), X13; \ + MOVQ 7*8(SI), X14; \ + MOVQ 2*8(SI), X15; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(11*8) + +// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) +#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ + MOVQ 6*8(SI), X12; \ + MOVQ 11*8(SI), X13; \ + MOVQ 15*8(SI), X14; \ + MOVQ 3*8(SI), X15; \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X14(9*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) +#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ + MOVQ 5*8(SI), X12; \ + MOVQ 8*8(SI), X13; \ + MOVQ 0*8(SI), X14; \ + MOVQ 6*8(SI), X15; \ + VPINSRQ_1_SI_X12(15*8); \ + VPINSRQ_1_SI_X13(2*8); \ + VPINSRQ_1_SI_X14(4*8); \ + VPINSRQ_1_SI_X15(10*8) + +// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) +#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ + VMOVDQU 12*8(SI), X12; \ + MOVQ 1*8(SI), X13; \ + MOVQ 2*8(SI), X14; \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VMOVDQU 4*8(SI), X15 + +// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) +#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ + MOVQ 15*8(SI), X12; \ + MOVQ 3*8(SI), X13; \ + MOVQ 11*8(SI), X14; \ + MOVQ 12*8(SI), X15; \ + VPINSRQ_1_SI_X12(9*8); \ + VPINSRQ_1_SI_X13(13*8); \ + VPINSRQ_1_SI_X14(14*8); \ + VPINSRQ_1_SI_X15_0 + +// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, R10 + ADDQ $15, R10 + ANDQ $~15, R10 + + VMOVDQU ·AVX_c40<>(SB), X0 + VMOVDQU ·AVX_c48<>(SB), X1 + VMOVDQA X0, X8 + VMOVDQA X1, X9 + + VMOVDQU ·AVX_iv3<>(SB), X0 + VMOVDQA X0, 0(R10) + XORQ CX, 0(R10) // 0(R10) = ·AVX_iv3 ^ (CX || 0) + + VMOVDQU 0(AX), X10 + VMOVDQU 16(AX), X11 + VMOVDQU 32(AX), X2 + VMOVDQU 48(AX), X3 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $128, R8 + CMPQ R8, $128 + JGE noinc + INCQ R9 + +noinc: + VMOVQ_R8_X15 + VPINSRQ_1_R9_X15 + + VMOVDQA X10, X0 + VMOVDQA X11, X1 + VMOVDQU ·AVX_iv0<>(SB), X4 + VMOVDQU ·AVX_iv1<>(SB), X5 + VMOVDQU ·AVX_iv2<>(SB), X6 + + VPXOR X15, X6, X6 + VMOVDQA 0(R10), X7 + + LOAD_MSG_AVX_0_2_4_6_1_3_5_7() + VMOVDQA X12, 16(R10) + VMOVDQA X13, 32(R10) + VMOVDQA X14, 48(R10) + VMOVDQA X15, 64(R10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) + VMOVDQA X12, 80(R10) + VMOVDQA X13, 96(R10) + VMOVDQA X14, 112(R10) + VMOVDQA X15, 128(R10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) + VMOVDQA X12, 144(R10) + VMOVDQA X13, 160(R10) + VMOVDQA X14, 176(R10) + VMOVDQA X15, 192(R10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_1_0_11_5_12_2_7_3() + VMOVDQA X12, 208(R10) + VMOVDQA X13, 224(R10) + VMOVDQA X14, 240(R10) + VMOVDQA X15, 256(R10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_11_12_5_15_8_0_2_13() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_2_5_4_15_6_10_0_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_9_5_2_10_0_7_4_15() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_2_6_0_8_12_10_11_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_0_6_9_8_7_3_2_11() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_5_15_8_2_0_4_6_10() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_6_14_11_0_15_9_3_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_12_13_1_10_2_7_4_5() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_15_9_3_13_11_14_12_0() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X15, X8, X9) + SHUFFLE_AVX_INV() + + VMOVDQU 32(AX), X14 + VMOVDQU 48(AX), X15 + VPXOR X0, X10, X10 + VPXOR X1, X11, X11 + VPXOR X2, X14, X14 + VPXOR X3, X15, X15 + VPXOR X4, X10, X10 + VPXOR X5, X11, X11 + VPXOR X6, X14, X2 + VPXOR X7, X15, X3 + VMOVDQU X2, 32(AX) + VMOVDQU X3, 48(AX) + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + VMOVDQU X10, 0(AX) + VMOVDQU X11, 16(AX) + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + VZEROUPPER + + RET diff --git a/src/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/src/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s new file mode 100644 index 00000000000..adfac00c15c --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s @@ -0,0 +1,278 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && gc && !purego + +#include "textflag.h" + +DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 + +#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v6, t1; \ + PUNPCKLQDQ v6, t2; \ + PUNPCKHQDQ v7, v6; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ v7, t2; \ + MOVO t1, v7; \ + MOVO v2, t1; \ + PUNPCKHQDQ t2, v7; \ + PUNPCKLQDQ v3, t2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v3 + +#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v2, t1; \ + PUNPCKLQDQ v2, t2; \ + PUNPCKHQDQ v3, v2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ v3, t2; \ + MOVO t1, v3; \ + MOVO v6, t1; \ + PUNPCKHQDQ t2, v3; \ + PUNPCKLQDQ v7, t2; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v7 + +#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + PADDQ m0, v0; \ + PADDQ m1, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFD $0xB1, v6, v6; \ + PSHUFD $0xB1, v7, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + PSHUFB c40, v2; \ + PSHUFB c40, v3; \ + PADDQ m2, v0; \ + PADDQ m3, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFB c48, v6; \ + PSHUFB c48, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + MOVOU v2, t0; \ + PADDQ v2, t0; \ + PSRLQ $63, v2; \ + PXOR t0, v2; \ + MOVOU v3, t0; \ + PADDQ v3, t0; \ + PSRLQ $63, v3; \ + PXOR t0, v3 + +#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \ + MOVQ i0*8(src), m0; \ + PINSRQ $1, i1*8(src), m0; \ + MOVQ i2*8(src), m1; \ + PINSRQ $1, i3*8(src), m1; \ + MOVQ i4*8(src), m2; \ + PINSRQ $1, i5*8(src), m2; \ + MOVQ i6*8(src), m3; \ + PINSRQ $1, i7*8(src), m3 + +// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, R10 + ADDQ $15, R10 + ANDQ $~15, R10 + + MOVOU ·iv3<>(SB), X0 + MOVO X0, 0(R10) + XORQ CX, 0(R10) // 0(R10) = ·iv3 ^ (CX || 0) + + MOVOU ·c40<>(SB), X13 + MOVOU ·c48<>(SB), X14 + + MOVOU 0(AX), X12 + MOVOU 16(AX), X15 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $128, R8 + CMPQ R8, $128 + JGE noinc + INCQ R9 + +noinc: + MOVQ R8, X8 + PINSRQ $1, R9, X8 + + MOVO X12, X0 + MOVO X15, X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU ·iv0<>(SB), X4 + MOVOU ·iv1<>(SB), X5 + MOVOU ·iv2<>(SB), X6 + + PXOR X8, X6 + MOVO 0(R10), X7 + + LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) + MOVO X8, 16(R10) + MOVO X9, 32(R10) + MOVO X10, 48(R10) + MOVO X11, 64(R10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) + MOVO X8, 80(R10) + MOVO X9, 96(R10) + MOVO X10, 112(R10) + MOVO X11, 128(R10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) + MOVO X8, 144(R10) + MOVO X9, 160(R10) + MOVO X10, 176(R10) + MOVO X11, 192(R10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) + MOVO X8, 208(R10) + MOVO X9, 224(R10) + MOVO X10, 240(R10) + MOVO X11, 256(R10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + MOVOU 32(AX), X10 + MOVOU 48(AX), X11 + PXOR X0, X12 + PXOR X1, X15 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X15 + PXOR X6, X10 + PXOR X7, X11 + MOVOU X10, 32(AX) + MOVOU X11, 48(AX) + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + MOVOU X12, 0(AX) + MOVOU X15, 16(AX) + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + + RET diff --git a/src/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go b/src/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go new file mode 100644 index 00000000000..3168a8aa3c8 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go @@ -0,0 +1,182 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "encoding/binary" + "math/bits" +) + +// the precomputed values for BLAKE2b +// there are 12 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [12][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second +} + +func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + + for j := range precomputed { + s := &(precomputed[j]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -32) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -24) + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -32) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -24) + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -32) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -24) + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -32) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -24) + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft64(v12, -16) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft64(v4, -63) + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft64(v13, -16) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft64(v5, -63) + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft64(v14, -16) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft64(v6, -63) + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft64(v15, -16) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft64(v7, -63) + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -32) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -24) + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -32) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -24) + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -32) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -24) + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -32) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -24) + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft64(v15, -16) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft64(v5, -63) + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft64(v12, -16) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft64(v6, -63) + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft64(v13, -16) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft64(v7, -63) + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft64(v14, -16) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft64(v4, -63) + + } + + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 + } + c[0], c[1] = c0, c1 +} diff --git a/src/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go b/src/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go new file mode 100644 index 00000000000..6e28668cd19 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go @@ -0,0 +1,11 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 || purego || !gc + +package blake2b + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + hashBlocksGeneric(h, c, flag, blocks) +} diff --git a/src/vendor/golang.org/x/crypto/blake2b/blake2x.go b/src/vendor/golang.org/x/crypto/blake2b/blake2x.go new file mode 100644 index 00000000000..52c414db0e6 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/blake2x.go @@ -0,0 +1,177 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "encoding/binary" + "errors" + "io" +) + +// XOF defines the interface to hash functions that +// support arbitrary-length output. +type XOF interface { + // Write absorbs more data into the hash's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the hash. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset resets the XOF to its initial state. + Reset() +} + +// OutputLengthUnknown can be used as the size argument to NewXOF to indicate +// the length of the output is not known in advance. +const OutputLengthUnknown = 0 + +// magicUnknownOutputLength is a magic value for the output size that indicates +// an unknown number of output bytes. +const magicUnknownOutputLength = (1 << 32) - 1 + +// maxOutputLength is the absolute maximum number of bytes to produce when the +// number of output bytes is unknown. +const maxOutputLength = (1 << 32) * 64 + +// NewXOF creates a new variable-output-length hash. The hash either produce a +// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes +// (size == OutputLengthUnknown). In the latter case, an absolute limit of +// 256GiB applies. +// +// A non-nil key turns the hash into a MAC. The key must between +// zero and 32 bytes long. +func NewXOF(size uint32, key []byte) (XOF, error) { + if len(key) > Size { + return nil, errKeySize + } + if size == magicUnknownOutputLength { + // 2^32-1 indicates an unknown number of bytes and thus isn't a + // valid length. + return nil, errors.New("blake2b: XOF length too large") + } + if size == OutputLengthUnknown { + size = magicUnknownOutputLength + } + x := &xof{ + d: digest{ + size: Size, + keyLen: len(key), + }, + length: size, + } + copy(x.d.key[:], key) + x.Reset() + return x, nil +} + +type xof struct { + d digest + length uint32 + remaining uint64 + cfg, root, block [Size]byte + offset int + nodeOffset uint32 + readMode bool +} + +func (x *xof) Write(p []byte) (n int, err error) { + if x.readMode { + panic("blake2b: write to XOF after read") + } + return x.d.Write(p) +} + +func (x *xof) Clone() XOF { + clone := *x + return &clone +} + +func (x *xof) Reset() { + x.cfg[0] = byte(Size) + binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length + binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length + x.cfg[17] = byte(Size) // inner hash size + + x.d.Reset() + x.d.h[1] ^= uint64(x.length) << 32 + + x.remaining = uint64(x.length) + if x.remaining == magicUnknownOutputLength { + x.remaining = maxOutputLength + } + x.offset, x.nodeOffset = 0, 0 + x.readMode = false +} + +func (x *xof) Read(p []byte) (n int, err error) { + if !x.readMode { + x.d.finalize(&x.root) + x.readMode = true + } + + if x.remaining == 0 { + return 0, io.EOF + } + + n = len(p) + if uint64(n) > x.remaining { + n = int(x.remaining) + p = p[:n] + } + + if x.offset > 0 { + blockRemaining := Size - x.offset + if n < blockRemaining { + x.offset += copy(p, x.block[x.offset:]) + x.remaining -= uint64(n) + return + } + copy(p, x.block[x.offset:]) + p = p[blockRemaining:] + x.offset = 0 + x.remaining -= uint64(blockRemaining) + } + + for len(p) >= Size { + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + copy(p, x.block[:]) + p = p[Size:] + x.remaining -= uint64(Size) + } + + if todo := len(p); todo > 0 { + if x.remaining < uint64(Size) { + x.cfg[0] = byte(x.remaining) + } + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + x.offset = copy(p, x.block[:todo]) + x.remaining -= uint64(todo) + } + return +} + +func (d *digest) initConfig(cfg *[Size]byte) { + d.offset, d.c[0], d.c[1] = 0, 0, 0 + for i := range d.h { + d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) + } +} diff --git a/src/vendor/golang.org/x/crypto/blake2b/register.go b/src/vendor/golang.org/x/crypto/blake2b/register.go new file mode 100644 index 00000000000..54e446e1d2c --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2b/register.go @@ -0,0 +1,30 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "crypto" + "hash" +) + +func init() { + newHash256 := func() hash.Hash { + h, _ := New256(nil) + return h + } + newHash384 := func() hash.Hash { + h, _ := New384(nil) + return h + } + + newHash512 := func() hash.Hash { + h, _ := New512(nil) + return h + } + + crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) + crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) + crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) +} diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2s.go b/src/vendor/golang.org/x/crypto/blake2s/blake2s.go new file mode 100644 index 00000000000..e3f46aab3a1 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2s.go @@ -0,0 +1,246 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blake2s implements the BLAKE2s hash algorithm defined by RFC 7693 +// and the extendable output function (XOF) BLAKE2Xs. +// +// BLAKE2s is optimized for 8- to 32-bit platforms and produces digests of any +// size between 1 and 32 bytes. +// For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf +// and for BLAKE2Xs see https://blake2.net/blake2x.pdf +// +// If you aren't sure which function you need, use BLAKE2s (Sum256 or New256). +// If you need a secret-key MAC (message authentication code), use the New256 +// function with a non-nil key. +// +// BLAKE2X is a construction to compute hash values larger than 32 bytes. It +// can produce hash values between 0 and 65535 bytes. +package blake2s // import "golang.org/x/crypto/blake2s" + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2s in bytes. + BlockSize = 64 + + // The hash size of BLAKE2s-256 in bytes. + Size = 32 + + // The hash size of BLAKE2s-128 in bytes. + Size128 = 16 +) + +var errKeySize = errors.New("blake2s: invalid key size") + +var iv = [8]uint32{ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, +} + +// Sum256 returns the BLAKE2s-256 checksum of the data. +func Sum256(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 32 bytes long. +// When the key is nil, the returned hash.Hash implements BinaryMarshaler +// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a +// non-empty key. Note that a 128-bit digest is too small to be secure as a +// cryptographic hash and should only be used as a MAC, thus the key argument +// is not optional. +func New128(key []byte) (hash.Hash, error) { + if len(key) == 0 { + return nil, errors.New("blake2s: a key is required for a 128-bit hash") + } + return newDigest(Size128, key) +} + +func newDigest(hashSize int, key []byte) (*digest, error) { + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + var ( + h [8]uint32 + c [2]uint32 + ) + + h = iv + h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24) + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint32(BlockSize - offset) + + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) + + for i, v := range h { + binary.LittleEndian.PutUint32(sum[4*i:], v) + } +} + +type digest struct { + h [8]uint32 + c [2]uint32 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +const ( + magic = "b2s" + marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1 +) + +func (d *digest) MarshalBinary() ([]byte, error) { + if d.keyLen != 0 { + return nil, errors.New("crypto/blake2s: cannot marshal MACs") + } + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + for i := 0; i < 8; i++ { + b = appendUint32(b, d.h[i]) + } + b = appendUint32(b, d.c[0]) + b = appendUint32(b, d.c[1]) + // Maximum value for size is 32 + b = append(b, byte(d.size)) + b = append(b, d.block[:]...) + b = append(b, byte(d.offset)) + return b, nil +} + +func (d *digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("crypto/blake2s: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("crypto/blake2s: invalid hash state size") + } + b = b[len(magic):] + for i := 0; i < 8; i++ { + b, d.h[i] = consumeUint32(b) + } + b, d.c[0] = consumeUint32(b) + b, d.c[1] = consumeUint32(b) + d.size = int(b[0]) + b = b[1:] + copy(d.block[:], b[:BlockSize]) + b = b[BlockSize:] + d.offset = int(b[0]) + return nil +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + d.offset += copy(d.block[:], p) + return +} + +func (d *digest) Sum(sum []byte) []byte { + var hash [Size]byte + d.finalize(&hash) + return append(sum, hash[:d.size]...) +} + +func (d *digest) finalize(hash *[Size]byte) { + var block [BlockSize]byte + h := d.h + c := d.c + + copy(block[:], d.block[:d.offset]) + remaining := uint32(BlockSize - d.offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) + for i, v := range h { + binary.LittleEndian.PutUint32(hash[4*i:], v) + } +} + +func appendUint32(b []byte, x uint32) []byte { + var a [4]byte + binary.BigEndian.PutUint32(a[:], x) + return append(b, a[:]...) +} + +func consumeUint32(b []byte) ([]byte, uint32) { + x := binary.BigEndian.Uint32(b) + return b[4:], x +} diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2s_386.go b/src/vendor/golang.org/x/crypto/blake2s/blake2s_386.go new file mode 100644 index 00000000000..97f629617e9 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2s_386.go @@ -0,0 +1,32 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build 386 && gc && !purego + +package blake2s + +import "golang.org/x/sys/cpu" + +var ( + useSSE4 = false + useSSSE3 = cpu.X86.HasSSSE3 + useSSE2 = cpu.X86.HasSSE2 +) + +//go:noescape +func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +//go:noescape +func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + switch { + case useSSSE3: + hashBlocksSSSE3(h, c, flag, blocks) + case useSSE2: + hashBlocksSSE2(h, c, flag, blocks) + default: + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2s_386.s b/src/vendor/golang.org/x/crypto/blake2s/blake2s_386.s new file mode 100644 index 00000000000..919c026541c --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2s_386.s @@ -0,0 +1,429 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build 386 && gc && !purego + +#include "textflag.h" + +DATA iv0<>+0x00(SB)/4, $0x6a09e667 +DATA iv0<>+0x04(SB)/4, $0xbb67ae85 +DATA iv0<>+0x08(SB)/4, $0x3c6ef372 +DATA iv0<>+0x0c(SB)/4, $0xa54ff53a +GLOBL iv0<>(SB), (NOPTR+RODATA), $16 + +DATA iv1<>+0x00(SB)/4, $0x510e527f +DATA iv1<>+0x04(SB)/4, $0x9b05688c +DATA iv1<>+0x08(SB)/4, $0x1f83d9ab +DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 +GLOBL iv1<>(SB), (NOPTR+RODATA), $16 + +DATA rol16<>+0x00(SB)/8, $0x0504070601000302 +DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A +GLOBL rol16<>(SB), (NOPTR+RODATA), $16 + +DATA rol8<>+0x00(SB)/8, $0x0407060500030201 +DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 +GLOBL rol8<>(SB), (NOPTR+RODATA), $16 + +DATA counter<>+0x00(SB)/8, $0x40 +DATA counter<>+0x08(SB)/8, $0x0 +GLOBL counter<>(SB), (NOPTR+RODATA), $16 + +#define ROTL_SSE2(n, t, v) \ + MOVO v, t; \ + PSLLL $n, t; \ + PSRLL $(32-n), v; \ + PXOR t, v + +#define ROTL_SSSE3(c, v) \ + PSHUFB c, v + +#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + +#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + +#define PRECOMPUTE(dst, off, src, t) \ + MOVL 0*4(src), t; \ + MOVL t, 0*4+off+0(dst); \ + MOVL t, 9*4+off+64(dst); \ + MOVL t, 5*4+off+128(dst); \ + MOVL t, 14*4+off+192(dst); \ + MOVL t, 4*4+off+256(dst); \ + MOVL t, 2*4+off+320(dst); \ + MOVL t, 8*4+off+384(dst); \ + MOVL t, 12*4+off+448(dst); \ + MOVL t, 3*4+off+512(dst); \ + MOVL t, 15*4+off+576(dst); \ + MOVL 1*4(src), t; \ + MOVL t, 4*4+off+0(dst); \ + MOVL t, 8*4+off+64(dst); \ + MOVL t, 14*4+off+128(dst); \ + MOVL t, 5*4+off+192(dst); \ + MOVL t, 12*4+off+256(dst); \ + MOVL t, 11*4+off+320(dst); \ + MOVL t, 1*4+off+384(dst); \ + MOVL t, 6*4+off+448(dst); \ + MOVL t, 10*4+off+512(dst); \ + MOVL t, 3*4+off+576(dst); \ + MOVL 2*4(src), t; \ + MOVL t, 1*4+off+0(dst); \ + MOVL t, 13*4+off+64(dst); \ + MOVL t, 6*4+off+128(dst); \ + MOVL t, 8*4+off+192(dst); \ + MOVL t, 2*4+off+256(dst); \ + MOVL t, 0*4+off+320(dst); \ + MOVL t, 14*4+off+384(dst); \ + MOVL t, 11*4+off+448(dst); \ + MOVL t, 12*4+off+512(dst); \ + MOVL t, 4*4+off+576(dst); \ + MOVL 3*4(src), t; \ + MOVL t, 5*4+off+0(dst); \ + MOVL t, 15*4+off+64(dst); \ + MOVL t, 9*4+off+128(dst); \ + MOVL t, 1*4+off+192(dst); \ + MOVL t, 11*4+off+256(dst); \ + MOVL t, 7*4+off+320(dst); \ + MOVL t, 13*4+off+384(dst); \ + MOVL t, 3*4+off+448(dst); \ + MOVL t, 6*4+off+512(dst); \ + MOVL t, 10*4+off+576(dst); \ + MOVL 4*4(src), t; \ + MOVL t, 2*4+off+0(dst); \ + MOVL t, 1*4+off+64(dst); \ + MOVL t, 15*4+off+128(dst); \ + MOVL t, 10*4+off+192(dst); \ + MOVL t, 6*4+off+256(dst); \ + MOVL t, 8*4+off+320(dst); \ + MOVL t, 3*4+off+384(dst); \ + MOVL t, 13*4+off+448(dst); \ + MOVL t, 14*4+off+512(dst); \ + MOVL t, 5*4+off+576(dst); \ + MOVL 5*4(src), t; \ + MOVL t, 6*4+off+0(dst); \ + MOVL t, 11*4+off+64(dst); \ + MOVL t, 2*4+off+128(dst); \ + MOVL t, 9*4+off+192(dst); \ + MOVL t, 1*4+off+256(dst); \ + MOVL t, 13*4+off+320(dst); \ + MOVL t, 4*4+off+384(dst); \ + MOVL t, 8*4+off+448(dst); \ + MOVL t, 15*4+off+512(dst); \ + MOVL t, 7*4+off+576(dst); \ + MOVL 6*4(src), t; \ + MOVL t, 3*4+off+0(dst); \ + MOVL t, 7*4+off+64(dst); \ + MOVL t, 13*4+off+128(dst); \ + MOVL t, 12*4+off+192(dst); \ + MOVL t, 10*4+off+256(dst); \ + MOVL t, 1*4+off+320(dst); \ + MOVL t, 9*4+off+384(dst); \ + MOVL t, 14*4+off+448(dst); \ + MOVL t, 0*4+off+512(dst); \ + MOVL t, 6*4+off+576(dst); \ + MOVL 7*4(src), t; \ + MOVL t, 7*4+off+0(dst); \ + MOVL t, 14*4+off+64(dst); \ + MOVL t, 10*4+off+128(dst); \ + MOVL t, 0*4+off+192(dst); \ + MOVL t, 5*4+off+256(dst); \ + MOVL t, 9*4+off+320(dst); \ + MOVL t, 12*4+off+384(dst); \ + MOVL t, 1*4+off+448(dst); \ + MOVL t, 13*4+off+512(dst); \ + MOVL t, 2*4+off+576(dst); \ + MOVL 8*4(src), t; \ + MOVL t, 8*4+off+0(dst); \ + MOVL t, 5*4+off+64(dst); \ + MOVL t, 4*4+off+128(dst); \ + MOVL t, 15*4+off+192(dst); \ + MOVL t, 14*4+off+256(dst); \ + MOVL t, 3*4+off+320(dst); \ + MOVL t, 11*4+off+384(dst); \ + MOVL t, 10*4+off+448(dst); \ + MOVL t, 7*4+off+512(dst); \ + MOVL t, 1*4+off+576(dst); \ + MOVL 9*4(src), t; \ + MOVL t, 12*4+off+0(dst); \ + MOVL t, 2*4+off+64(dst); \ + MOVL t, 11*4+off+128(dst); \ + MOVL t, 4*4+off+192(dst); \ + MOVL t, 0*4+off+256(dst); \ + MOVL t, 15*4+off+320(dst); \ + MOVL t, 10*4+off+384(dst); \ + MOVL t, 7*4+off+448(dst); \ + MOVL t, 5*4+off+512(dst); \ + MOVL t, 9*4+off+576(dst); \ + MOVL 10*4(src), t; \ + MOVL t, 9*4+off+0(dst); \ + MOVL t, 4*4+off+64(dst); \ + MOVL t, 8*4+off+128(dst); \ + MOVL t, 13*4+off+192(dst); \ + MOVL t, 3*4+off+256(dst); \ + MOVL t, 5*4+off+320(dst); \ + MOVL t, 7*4+off+384(dst); \ + MOVL t, 15*4+off+448(dst); \ + MOVL t, 11*4+off+512(dst); \ + MOVL t, 0*4+off+576(dst); \ + MOVL 11*4(src), t; \ + MOVL t, 13*4+off+0(dst); \ + MOVL t, 10*4+off+64(dst); \ + MOVL t, 0*4+off+128(dst); \ + MOVL t, 3*4+off+192(dst); \ + MOVL t, 9*4+off+256(dst); \ + MOVL t, 6*4+off+320(dst); \ + MOVL t, 15*4+off+384(dst); \ + MOVL t, 4*4+off+448(dst); \ + MOVL t, 2*4+off+512(dst); \ + MOVL t, 12*4+off+576(dst); \ + MOVL 12*4(src), t; \ + MOVL t, 10*4+off+0(dst); \ + MOVL t, 12*4+off+64(dst); \ + MOVL t, 1*4+off+128(dst); \ + MOVL t, 6*4+off+192(dst); \ + MOVL t, 13*4+off+256(dst); \ + MOVL t, 4*4+off+320(dst); \ + MOVL t, 0*4+off+384(dst); \ + MOVL t, 2*4+off+448(dst); \ + MOVL t, 8*4+off+512(dst); \ + MOVL t, 14*4+off+576(dst); \ + MOVL 13*4(src), t; \ + MOVL t, 14*4+off+0(dst); \ + MOVL t, 3*4+off+64(dst); \ + MOVL t, 7*4+off+128(dst); \ + MOVL t, 2*4+off+192(dst); \ + MOVL t, 15*4+off+256(dst); \ + MOVL t, 12*4+off+320(dst); \ + MOVL t, 6*4+off+384(dst); \ + MOVL t, 0*4+off+448(dst); \ + MOVL t, 9*4+off+512(dst); \ + MOVL t, 11*4+off+576(dst); \ + MOVL 14*4(src), t; \ + MOVL t, 11*4+off+0(dst); \ + MOVL t, 0*4+off+64(dst); \ + MOVL t, 12*4+off+128(dst); \ + MOVL t, 7*4+off+192(dst); \ + MOVL t, 8*4+off+256(dst); \ + MOVL t, 14*4+off+320(dst); \ + MOVL t, 2*4+off+384(dst); \ + MOVL t, 5*4+off+448(dst); \ + MOVL t, 1*4+off+512(dst); \ + MOVL t, 13*4+off+576(dst); \ + MOVL 15*4(src), t; \ + MOVL t, 15*4+off+0(dst); \ + MOVL t, 6*4+off+64(dst); \ + MOVL t, 3*4+off+128(dst); \ + MOVL t, 11*4+off+192(dst); \ + MOVL t, 7*4+off+256(dst); \ + MOVL t, 10*4+off+320(dst); \ + MOVL t, 5*4+off+384(dst); \ + MOVL t, 9*4+off+448(dst); \ + MOVL t, 4*4+off+512(dst); \ + MOVL t, 8*4+off+576(dst) + +// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSE2(SB), 0, $672-24 // frame = 656 + 16 byte alignment + MOVL h+0(FP), AX + MOVL c+4(FP), BX + MOVL flag+8(FP), CX + MOVL blocks_base+12(FP), SI + MOVL blocks_len+16(FP), DX + + MOVL SP, DI + ADDL $15, DI + ANDL $~15, DI + + MOVL CX, 8(DI) + MOVL 0(BX), CX + MOVL CX, 0(DI) + MOVL 4(BX), CX + MOVL CX, 4(DI) + XORL CX, CX + MOVL CX, 12(DI) + + MOVOU 0(AX), X0 + MOVOU 16(AX), X1 + MOVOU counter<>(SB), X2 + +loop: + MOVO X0, X4 + MOVO X1, X5 + MOVOU iv0<>(SB), X6 + MOVOU iv1<>(SB), X7 + + MOVO 0(DI), X3 + PADDQ X2, X3 + PXOR X3, X7 + MOVO X3, 0(DI) + + PRECOMPUTE(DI, 16, SI, CX) + ROUND_SSE2(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3) + + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X0 + PXOR X7, X1 + + LEAL 64(SI), SI + SUBL $64, DX + JNE loop + + MOVL 0(DI), CX + MOVL CX, 0(BX) + MOVL 4(DI), CX + MOVL CX, 4(BX) + + MOVOU X0, 0(AX) + MOVOU X1, 16(AX) + + RET + +// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSSE3(SB), 0, $704-24 // frame = 688 + 16 byte alignment + MOVL h+0(FP), AX + MOVL c+4(FP), BX + MOVL flag+8(FP), CX + MOVL blocks_base+12(FP), SI + MOVL blocks_len+16(FP), DX + + MOVL SP, DI + ADDL $15, DI + ANDL $~15, DI + + MOVL CX, 8(DI) + MOVL 0(BX), CX + MOVL CX, 0(DI) + MOVL 4(BX), CX + MOVL CX, 4(DI) + XORL CX, CX + MOVL CX, 12(DI) + + MOVOU 0(AX), X0 + MOVOU 16(AX), X1 + MOVOU counter<>(SB), X2 + +loop: + MOVO X0, 656(DI) + MOVO X1, 672(DI) + MOVO X0, X4 + MOVO X1, X5 + MOVOU iv0<>(SB), X6 + MOVOU iv1<>(SB), X7 + + MOVO 0(DI), X3 + PADDQ X2, X3 + PXOR X3, X7 + MOVO X3, 0(DI) + + MOVOU rol16<>(SB), X0 + MOVOU rol8<>(SB), X1 + + PRECOMPUTE(DI, 16, SI, CX) + ROUND_SSSE3(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3, X0, X1) + + MOVO 656(DI), X0 + MOVO 672(DI), X1 + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X0 + PXOR X7, X1 + + LEAL 64(SI), SI + SUBL $64, DX + JNE loop + + MOVL 0(DI), CX + MOVL CX, 0(BX) + MOVL 4(DI), CX + MOVL CX, 4(BX) + + MOVOU X0, 0(AX) + MOVOU X1, 16(AX) + + RET diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go b/src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go new file mode 100644 index 00000000000..8a7310254e8 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go @@ -0,0 +1,37 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && gc && !purego + +package blake2s + +import "golang.org/x/sys/cpu" + +var ( + useSSE4 = cpu.X86.HasSSE41 + useSSSE3 = cpu.X86.HasSSSE3 + useSSE2 = cpu.X86.HasSSE2 +) + +//go:noescape +func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +//go:noescape +func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +//go:noescape +func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + switch { + case useSSE4: + hashBlocksSSE4(h, c, flag, blocks) + case useSSSE3: + hashBlocksSSSE3(h, c, flag, blocks) + case useSSE2: + hashBlocksSSE2(h, c, flag, blocks) + default: + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s b/src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s new file mode 100644 index 00000000000..fe4b818a33a --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s @@ -0,0 +1,432 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && gc && !purego + +#include "textflag.h" + +DATA iv0<>+0x00(SB)/4, $0x6a09e667 +DATA iv0<>+0x04(SB)/4, $0xbb67ae85 +DATA iv0<>+0x08(SB)/4, $0x3c6ef372 +DATA iv0<>+0x0c(SB)/4, $0xa54ff53a +GLOBL iv0<>(SB), (NOPTR+RODATA), $16 + +DATA iv1<>+0x00(SB)/4, $0x510e527f +DATA iv1<>+0x04(SB)/4, $0x9b05688c +DATA iv1<>+0x08(SB)/4, $0x1f83d9ab +DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 +GLOBL iv1<>(SB), (NOPTR+RODATA), $16 + +DATA rol16<>+0x00(SB)/8, $0x0504070601000302 +DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A +GLOBL rol16<>(SB), (NOPTR+RODATA), $16 + +DATA rol8<>+0x00(SB)/8, $0x0407060500030201 +DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 +GLOBL rol8<>(SB), (NOPTR+RODATA), $16 + +DATA counter<>+0x00(SB)/8, $0x40 +DATA counter<>+0x08(SB)/8, $0x0 +GLOBL counter<>(SB), (NOPTR+RODATA), $16 + +#define ROTL_SSE2(n, t, v) \ + MOVO v, t; \ + PSLLL $n, t; \ + PSRLL $(32-n), v; \ + PXOR t, v + +#define ROTL_SSSE3(c, v) \ + PSHUFB c, v + +#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + +#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + + +#define LOAD_MSG_SSE4(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \ + MOVL i0*4(src), m0; \ + PINSRD $1, i1*4(src), m0; \ + PINSRD $2, i2*4(src), m0; \ + PINSRD $3, i3*4(src), m0; \ + MOVL i4*4(src), m1; \ + PINSRD $1, i5*4(src), m1; \ + PINSRD $2, i6*4(src), m1; \ + PINSRD $3, i7*4(src), m1; \ + MOVL i8*4(src), m2; \ + PINSRD $1, i9*4(src), m2; \ + PINSRD $2, i10*4(src), m2; \ + PINSRD $3, i11*4(src), m2; \ + MOVL i12*4(src), m3; \ + PINSRD $1, i13*4(src), m3; \ + PINSRD $2, i14*4(src), m3; \ + PINSRD $3, i15*4(src), m3 + +#define PRECOMPUTE_MSG(dst, off, src, R8, R9, R10, R11, R12, R13, R14, R15) \ + MOVQ 0*4(src), R8; \ + MOVQ 2*4(src), R9; \ + MOVQ 4*4(src), R10; \ + MOVQ 6*4(src), R11; \ + MOVQ 8*4(src), R12; \ + MOVQ 10*4(src), R13; \ + MOVQ 12*4(src), R14; \ + MOVQ 14*4(src), R15; \ + \ + MOVL R8, 0*4+off+0(dst); \ + MOVL R8, 9*4+off+64(dst); \ + MOVL R8, 5*4+off+128(dst); \ + MOVL R8, 14*4+off+192(dst); \ + MOVL R8, 4*4+off+256(dst); \ + MOVL R8, 2*4+off+320(dst); \ + MOVL R8, 8*4+off+384(dst); \ + MOVL R8, 12*4+off+448(dst); \ + MOVL R8, 3*4+off+512(dst); \ + MOVL R8, 15*4+off+576(dst); \ + SHRQ $32, R8; \ + MOVL R8, 4*4+off+0(dst); \ + MOVL R8, 8*4+off+64(dst); \ + MOVL R8, 14*4+off+128(dst); \ + MOVL R8, 5*4+off+192(dst); \ + MOVL R8, 12*4+off+256(dst); \ + MOVL R8, 11*4+off+320(dst); \ + MOVL R8, 1*4+off+384(dst); \ + MOVL R8, 6*4+off+448(dst); \ + MOVL R8, 10*4+off+512(dst); \ + MOVL R8, 3*4+off+576(dst); \ + \ + MOVL R9, 1*4+off+0(dst); \ + MOVL R9, 13*4+off+64(dst); \ + MOVL R9, 6*4+off+128(dst); \ + MOVL R9, 8*4+off+192(dst); \ + MOVL R9, 2*4+off+256(dst); \ + MOVL R9, 0*4+off+320(dst); \ + MOVL R9, 14*4+off+384(dst); \ + MOVL R9, 11*4+off+448(dst); \ + MOVL R9, 12*4+off+512(dst); \ + MOVL R9, 4*4+off+576(dst); \ + SHRQ $32, R9; \ + MOVL R9, 5*4+off+0(dst); \ + MOVL R9, 15*4+off+64(dst); \ + MOVL R9, 9*4+off+128(dst); \ + MOVL R9, 1*4+off+192(dst); \ + MOVL R9, 11*4+off+256(dst); \ + MOVL R9, 7*4+off+320(dst); \ + MOVL R9, 13*4+off+384(dst); \ + MOVL R9, 3*4+off+448(dst); \ + MOVL R9, 6*4+off+512(dst); \ + MOVL R9, 10*4+off+576(dst); \ + \ + MOVL R10, 2*4+off+0(dst); \ + MOVL R10, 1*4+off+64(dst); \ + MOVL R10, 15*4+off+128(dst); \ + MOVL R10, 10*4+off+192(dst); \ + MOVL R10, 6*4+off+256(dst); \ + MOVL R10, 8*4+off+320(dst); \ + MOVL R10, 3*4+off+384(dst); \ + MOVL R10, 13*4+off+448(dst); \ + MOVL R10, 14*4+off+512(dst); \ + MOVL R10, 5*4+off+576(dst); \ + SHRQ $32, R10; \ + MOVL R10, 6*4+off+0(dst); \ + MOVL R10, 11*4+off+64(dst); \ + MOVL R10, 2*4+off+128(dst); \ + MOVL R10, 9*4+off+192(dst); \ + MOVL R10, 1*4+off+256(dst); \ + MOVL R10, 13*4+off+320(dst); \ + MOVL R10, 4*4+off+384(dst); \ + MOVL R10, 8*4+off+448(dst); \ + MOVL R10, 15*4+off+512(dst); \ + MOVL R10, 7*4+off+576(dst); \ + \ + MOVL R11, 3*4+off+0(dst); \ + MOVL R11, 7*4+off+64(dst); \ + MOVL R11, 13*4+off+128(dst); \ + MOVL R11, 12*4+off+192(dst); \ + MOVL R11, 10*4+off+256(dst); \ + MOVL R11, 1*4+off+320(dst); \ + MOVL R11, 9*4+off+384(dst); \ + MOVL R11, 14*4+off+448(dst); \ + MOVL R11, 0*4+off+512(dst); \ + MOVL R11, 6*4+off+576(dst); \ + SHRQ $32, R11; \ + MOVL R11, 7*4+off+0(dst); \ + MOVL R11, 14*4+off+64(dst); \ + MOVL R11, 10*4+off+128(dst); \ + MOVL R11, 0*4+off+192(dst); \ + MOVL R11, 5*4+off+256(dst); \ + MOVL R11, 9*4+off+320(dst); \ + MOVL R11, 12*4+off+384(dst); \ + MOVL R11, 1*4+off+448(dst); \ + MOVL R11, 13*4+off+512(dst); \ + MOVL R11, 2*4+off+576(dst); \ + \ + MOVL R12, 8*4+off+0(dst); \ + MOVL R12, 5*4+off+64(dst); \ + MOVL R12, 4*4+off+128(dst); \ + MOVL R12, 15*4+off+192(dst); \ + MOVL R12, 14*4+off+256(dst); \ + MOVL R12, 3*4+off+320(dst); \ + MOVL R12, 11*4+off+384(dst); \ + MOVL R12, 10*4+off+448(dst); \ + MOVL R12, 7*4+off+512(dst); \ + MOVL R12, 1*4+off+576(dst); \ + SHRQ $32, R12; \ + MOVL R12, 12*4+off+0(dst); \ + MOVL R12, 2*4+off+64(dst); \ + MOVL R12, 11*4+off+128(dst); \ + MOVL R12, 4*4+off+192(dst); \ + MOVL R12, 0*4+off+256(dst); \ + MOVL R12, 15*4+off+320(dst); \ + MOVL R12, 10*4+off+384(dst); \ + MOVL R12, 7*4+off+448(dst); \ + MOVL R12, 5*4+off+512(dst); \ + MOVL R12, 9*4+off+576(dst); \ + \ + MOVL R13, 9*4+off+0(dst); \ + MOVL R13, 4*4+off+64(dst); \ + MOVL R13, 8*4+off+128(dst); \ + MOVL R13, 13*4+off+192(dst); \ + MOVL R13, 3*4+off+256(dst); \ + MOVL R13, 5*4+off+320(dst); \ + MOVL R13, 7*4+off+384(dst); \ + MOVL R13, 15*4+off+448(dst); \ + MOVL R13, 11*4+off+512(dst); \ + MOVL R13, 0*4+off+576(dst); \ + SHRQ $32, R13; \ + MOVL R13, 13*4+off+0(dst); \ + MOVL R13, 10*4+off+64(dst); \ + MOVL R13, 0*4+off+128(dst); \ + MOVL R13, 3*4+off+192(dst); \ + MOVL R13, 9*4+off+256(dst); \ + MOVL R13, 6*4+off+320(dst); \ + MOVL R13, 15*4+off+384(dst); \ + MOVL R13, 4*4+off+448(dst); \ + MOVL R13, 2*4+off+512(dst); \ + MOVL R13, 12*4+off+576(dst); \ + \ + MOVL R14, 10*4+off+0(dst); \ + MOVL R14, 12*4+off+64(dst); \ + MOVL R14, 1*4+off+128(dst); \ + MOVL R14, 6*4+off+192(dst); \ + MOVL R14, 13*4+off+256(dst); \ + MOVL R14, 4*4+off+320(dst); \ + MOVL R14, 0*4+off+384(dst); \ + MOVL R14, 2*4+off+448(dst); \ + MOVL R14, 8*4+off+512(dst); \ + MOVL R14, 14*4+off+576(dst); \ + SHRQ $32, R14; \ + MOVL R14, 14*4+off+0(dst); \ + MOVL R14, 3*4+off+64(dst); \ + MOVL R14, 7*4+off+128(dst); \ + MOVL R14, 2*4+off+192(dst); \ + MOVL R14, 15*4+off+256(dst); \ + MOVL R14, 12*4+off+320(dst); \ + MOVL R14, 6*4+off+384(dst); \ + MOVL R14, 0*4+off+448(dst); \ + MOVL R14, 9*4+off+512(dst); \ + MOVL R14, 11*4+off+576(dst); \ + \ + MOVL R15, 11*4+off+0(dst); \ + MOVL R15, 0*4+off+64(dst); \ + MOVL R15, 12*4+off+128(dst); \ + MOVL R15, 7*4+off+192(dst); \ + MOVL R15, 8*4+off+256(dst); \ + MOVL R15, 14*4+off+320(dst); \ + MOVL R15, 2*4+off+384(dst); \ + MOVL R15, 5*4+off+448(dst); \ + MOVL R15, 1*4+off+512(dst); \ + MOVL R15, 13*4+off+576(dst); \ + SHRQ $32, R15; \ + MOVL R15, 15*4+off+0(dst); \ + MOVL R15, 6*4+off+64(dst); \ + MOVL R15, 3*4+off+128(dst); \ + MOVL R15, 11*4+off+192(dst); \ + MOVL R15, 7*4+off+256(dst); \ + MOVL R15, 10*4+off+320(dst); \ + MOVL R15, 5*4+off+384(dst); \ + MOVL R15, 9*4+off+448(dst); \ + MOVL R15, 4*4+off+512(dst); \ + MOVL R15, 8*4+off+576(dst) + +#define BLAKE2s_SSE2() \ + PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ + ROUND_SSE2(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8) + +#define BLAKE2s_SSSE3() \ + PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ + ROUND_SSSE3(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8, X13, X14) + +#define BLAKE2s_SSE4() \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + +#define HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_FUNC) \ + MOVQ h, AX; \ + MOVQ c, BX; \ + MOVL flag, CX; \ + MOVQ blocks_base, SI; \ + MOVQ blocks_len, DX; \ + \ + MOVQ SP, BP; \ + ADDQ $15, BP; \ + ANDQ $~15, BP; \ + \ + MOVQ 0(BX), R9; \ + MOVQ R9, 0(BP); \ + MOVQ CX, 8(BP); \ + \ + MOVOU 0(AX), X0; \ + MOVOU 16(AX), X1; \ + MOVOU iv0<>(SB), X2; \ + MOVOU iv1<>(SB), X3 \ + \ + MOVOU counter<>(SB), X12; \ + MOVOU rol16<>(SB), X13; \ + MOVOU rol8<>(SB), X14; \ + MOVO 0(BP), X15; \ + \ + loop: \ + MOVO X0, X4; \ + MOVO X1, X5; \ + MOVO X2, X6; \ + MOVO X3, X7; \ + \ + PADDQ X12, X15; \ + PXOR X15, X7; \ + \ + BLAKE2s_FUNC(); \ + \ + PXOR X4, X0; \ + PXOR X5, X1; \ + PXOR X6, X0; \ + PXOR X7, X1; \ + \ + LEAQ 64(SI), SI; \ + SUBQ $64, DX; \ + JNE loop; \ + \ + MOVO X15, 0(BP); \ + MOVQ 0(BP), R9; \ + MOVQ R9, 0(BX); \ + \ + MOVOU X0, 0(AX); \ + MOVOU X1, 16(AX) + +// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSE2(SB), 0, $672-48 // frame = 656 + 16 byte alignment + HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE2) + RET + +// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment + HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSSE3) + RET + +// func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment + HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) + RET diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go b/src/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go new file mode 100644 index 00000000000..24a1ff22adc --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go @@ -0,0 +1,178 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2s + +import ( + "math/bits" +) + +// the precomputed values for BLAKE2s +// there are 10 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [10][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, +} + +func hashBlocksGeneric(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + var m [16]uint32 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for j := range m { + m[j] = uint32(blocks[i]) | uint32(blocks[i+1])<<8 | uint32(blocks[i+2])<<16 | uint32(blocks[i+3])<<24 + i += 4 + } + + for k := range precomputed { + s := &(precomputed[k]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft32(v12, -16) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft32(v4, -12) + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft32(v13, -16) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft32(v5, -12) + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft32(v14, -16) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft32(v6, -12) + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft32(v15, -16) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft32(v7, -12) + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = bits.RotateLeft32(v12, -8) + v8 += v12 + v4 ^= v8 + v4 = bits.RotateLeft32(v4, -7) + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = bits.RotateLeft32(v13, -8) + v9 += v13 + v5 ^= v9 + v5 = bits.RotateLeft32(v5, -7) + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = bits.RotateLeft32(v14, -8) + v10 += v14 + v6 ^= v10 + v6 = bits.RotateLeft32(v6, -7) + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = bits.RotateLeft32(v15, -8) + v11 += v15 + v7 ^= v11 + v7 = bits.RotateLeft32(v7, -7) + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft32(v15, -16) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft32(v5, -12) + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft32(v12, -16) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft32(v6, -12) + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft32(v13, -16) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft32(v7, -12) + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft32(v14, -16) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft32(v4, -12) + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = bits.RotateLeft32(v15, -8) + v10 += v15 + v5 ^= v10 + v5 = bits.RotateLeft32(v5, -7) + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = bits.RotateLeft32(v12, -8) + v11 += v12 + v6 ^= v11 + v6 = bits.RotateLeft32(v6, -7) + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = bits.RotateLeft32(v13, -8) + v8 += v13 + v7 ^= v8 + v7 = bits.RotateLeft32(v7, -7) + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = bits.RotateLeft32(v14, -8) + v9 += v14 + v4 ^= v9 + v4 = bits.RotateLeft32(v4, -7) + } + + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 + } + c[0], c[1] = c0, c1 +} diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go b/src/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go new file mode 100644 index 00000000000..38ce8e283fa --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go @@ -0,0 +1,17 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !386) || !gc || purego + +package blake2s + +var ( + useSSE4 = false + useSSSE3 = false + useSSE2 = false +) + +func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + hashBlocksGeneric(h, c, flag, blocks) +} diff --git a/src/vendor/golang.org/x/crypto/blake2s/blake2x.go b/src/vendor/golang.org/x/crypto/blake2s/blake2x.go new file mode 100644 index 00000000000..828749ff01d --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/blake2x.go @@ -0,0 +1,178 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2s + +import ( + "encoding/binary" + "errors" + "io" +) + +// XOF defines the interface to hash functions that +// support arbitrary-length output. +type XOF interface { + // Write absorbs more data into the hash's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the hash. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset resets the XOF to its initial state. + Reset() +} + +// OutputLengthUnknown can be used as the size argument to NewXOF to indicate +// the length of the output is not known in advance. +const OutputLengthUnknown = 0 + +// magicUnknownOutputLength is a magic value for the output size that indicates +// an unknown number of output bytes. +const magicUnknownOutputLength = 65535 + +// maxOutputLength is the absolute maximum number of bytes to produce when the +// number of output bytes is unknown. +const maxOutputLength = (1 << 32) * 32 + +// NewXOF creates a new variable-output-length hash. The hash either produce a +// known number of bytes (1 <= size < 65535), or an unknown number of bytes +// (size == OutputLengthUnknown). In the latter case, an absolute limit of +// 128GiB applies. +// +// A non-nil key turns the hash into a MAC. The key must between +// zero and 32 bytes long. +func NewXOF(size uint16, key []byte) (XOF, error) { + if len(key) > Size { + return nil, errKeySize + } + if size == magicUnknownOutputLength { + // 2^16-1 indicates an unknown number of bytes and thus isn't a + // valid length. + return nil, errors.New("blake2s: XOF length too large") + } + if size == OutputLengthUnknown { + size = magicUnknownOutputLength + } + x := &xof{ + d: digest{ + size: Size, + keyLen: len(key), + }, + length: size, + } + copy(x.d.key[:], key) + x.Reset() + return x, nil +} + +type xof struct { + d digest + length uint16 + remaining uint64 + cfg, root, block [Size]byte + offset int + nodeOffset uint32 + readMode bool +} + +func (x *xof) Write(p []byte) (n int, err error) { + if x.readMode { + panic("blake2s: write to XOF after read") + } + return x.d.Write(p) +} + +func (x *xof) Clone() XOF { + clone := *x + return &clone +} + +func (x *xof) Reset() { + x.cfg[0] = byte(Size) + binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length + binary.LittleEndian.PutUint16(x.cfg[12:], x.length) // XOF length + x.cfg[15] = byte(Size) // inner hash size + + x.d.Reset() + x.d.h[3] ^= uint32(x.length) + + x.remaining = uint64(x.length) + if x.remaining == magicUnknownOutputLength { + x.remaining = maxOutputLength + } + x.offset, x.nodeOffset = 0, 0 + x.readMode = false +} + +func (x *xof) Read(p []byte) (n int, err error) { + if !x.readMode { + x.d.finalize(&x.root) + x.readMode = true + } + + if x.remaining == 0 { + return 0, io.EOF + } + + n = len(p) + if uint64(n) > x.remaining { + n = int(x.remaining) + p = p[:n] + } + + if x.offset > 0 { + blockRemaining := Size - x.offset + if n < blockRemaining { + x.offset += copy(p, x.block[x.offset:]) + x.remaining -= uint64(n) + return + } + copy(p, x.block[x.offset:]) + p = p[blockRemaining:] + x.offset = 0 + x.remaining -= uint64(blockRemaining) + } + + for len(p) >= Size { + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + copy(p, x.block[:]) + p = p[Size:] + x.remaining -= uint64(Size) + } + + if todo := len(p); todo > 0 { + if x.remaining < uint64(Size) { + x.cfg[0] = byte(x.remaining) + } + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + x.offset = copy(p, x.block[:todo]) + x.remaining -= uint64(todo) + } + + return +} + +func (d *digest) initConfig(cfg *[Size]byte) { + d.offset, d.c[0], d.c[1] = 0, 0, 0 + for i := range d.h { + d.h[i] = iv[i] ^ binary.LittleEndian.Uint32(cfg[i*4:]) + } +} diff --git a/src/vendor/golang.org/x/crypto/blake2s/register.go b/src/vendor/golang.org/x/crypto/blake2s/register.go new file mode 100644 index 00000000000..3156148a422 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/blake2s/register.go @@ -0,0 +1,21 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.9 + +package blake2s + +import ( + "crypto" + "hash" +) + +func init() { + newHash256 := func() hash.Hash { + h, _ := New256(nil) + return h + } + + crypto.RegisterHash(crypto.BLAKE2s_256, newHash256) +} diff --git a/src/vendor/golang.org/x/crypto/sha3/doc.go b/src/vendor/golang.org/x/crypto/sha3/doc.go new file mode 100644 index 00000000000..decd8cf9bf7 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/doc.go @@ -0,0 +1,62 @@ +// Copyright 2014 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 sha3 implements the SHA-3 fixed-output-length hash functions and +// the SHAKE variable-output-length hash functions defined by FIPS-202. +// +// Both types of hash function use the "sponge" construction and the Keccak +// permutation. For a detailed specification see http://keccak.noekeon.org/ +// +// # Guidance +// +// If you aren't sure what function you need, use SHAKE256 with at least 64 +// bytes of output. The SHAKE instances are faster than the SHA3 instances; +// the latter have to allocate memory to conform to the hash.Hash interface. +// +// If you need a secret-key MAC (message authentication code), prepend the +// secret key to the input, hash with SHAKE256 and read at least 32 bytes of +// output. +// +// # Security strengths +// +// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security +// strength against preimage attacks of x bits. Since they only produce "x" +// bits of output, their collision-resistance is only "x/2" bits. +// +// The SHAKE-256 and -128 functions have a generic security strength of 256 and +// 128 bits against all attacks, provided that at least 2x bits of their output +// is used. Requesting more than 64 or 32 bytes of output, respectively, does +// not increase the collision-resistance of the SHAKE functions. +// +// # The sponge construction +// +// A sponge builds a pseudo-random function from a public pseudo-random +// permutation, by applying the permutation to a state of "rate + capacity" +// bytes, but hiding "capacity" of the bytes. +// +// A sponge starts out with a zero state. To hash an input using a sponge, up +// to "rate" bytes of the input are XORed into the sponge's state. The sponge +// is then "full" and the permutation is applied to "empty" it. This process is +// repeated until all the input has been "absorbed". The input is then padded. +// The digest is "squeezed" from the sponge in the same way, except that output +// is copied out instead of input being XORed in. +// +// A sponge is parameterized by its generic security strength, which is equal +// to half its capacity; capacity + rate is equal to the permutation's width. +// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means +// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. +// +// # Recommendations +// +// The SHAKE functions are recommended for most new uses. They can produce +// output of arbitrary length. SHAKE256, with an output length of at least +// 64 bytes, provides 256-bit security against all attacks. The Keccak team +// recommends it for most applications upgrading from SHA2-512. (NIST chose a +// much stronger, but much slower, sponge instance for SHA3-512.) +// +// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. +// They produce output of the same length, with the same security strengths +// against all attacks. This means, in particular, that SHA3-256 only has +// 128-bit collision resistance, because its output length is 32 bytes. +package sha3 // import "golang.org/x/crypto/sha3" diff --git a/src/vendor/golang.org/x/crypto/sha3/hashes.go b/src/vendor/golang.org/x/crypto/sha3/hashes.go new file mode 100644 index 00000000000..0d8043fd2a1 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/hashes.go @@ -0,0 +1,97 @@ +// Copyright 2014 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 sha3 + +// This file provides functions for creating instances of the SHA-3 +// and SHAKE hash functions, as well as utility functions for hashing +// bytes. + +import ( + "hash" +) + +// New224 creates a new SHA3-224 hash. +// Its generic security strength is 224 bits against preimage attacks, +// and 112 bits against collision attacks. +func New224() hash.Hash { + if h := new224Asm(); h != nil { + return h + } + return &state{rate: 144, outputLen: 28, dsbyte: 0x06} +} + +// New256 creates a new SHA3-256 hash. +// Its generic security strength is 256 bits against preimage attacks, +// and 128 bits against collision attacks. +func New256() hash.Hash { + if h := new256Asm(); h != nil { + return h + } + return &state{rate: 136, outputLen: 32, dsbyte: 0x06} +} + +// New384 creates a new SHA3-384 hash. +// Its generic security strength is 384 bits against preimage attacks, +// and 192 bits against collision attacks. +func New384() hash.Hash { + if h := new384Asm(); h != nil { + return h + } + return &state{rate: 104, outputLen: 48, dsbyte: 0x06} +} + +// New512 creates a new SHA3-512 hash. +// Its generic security strength is 512 bits against preimage attacks, +// and 256 bits against collision attacks. +func New512() hash.Hash { + if h := new512Asm(); h != nil { + return h + } + return &state{rate: 72, outputLen: 64, dsbyte: 0x06} +} + +// NewLegacyKeccak256 creates a new Keccak-256 hash. +// +// Only use this function if you require compatibility with an existing cryptosystem +// that uses non-standard padding. All other users should use New256 instead. +func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } + +// NewLegacyKeccak512 creates a new Keccak-512 hash. +// +// Only use this function if you require compatibility with an existing cryptosystem +// that uses non-standard padding. All other users should use New512 instead. +func NewLegacyKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } + +// Sum224 returns the SHA3-224 digest of the data. +func Sum224(data []byte) (digest [28]byte) { + h := New224() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum256 returns the SHA3-256 digest of the data. +func Sum256(data []byte) (digest [32]byte) { + h := New256() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum384 returns the SHA3-384 digest of the data. +func Sum384(data []byte) (digest [48]byte) { + h := New384() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum512 returns the SHA3-512 digest of the data. +func Sum512(data []byte) (digest [64]byte) { + h := New512() + h.Write(data) + h.Sum(digest[:0]) + return +} diff --git a/src/vendor/golang.org/x/crypto/sha3/hashes_generic.go b/src/vendor/golang.org/x/crypto/sha3/hashes_generic.go new file mode 100644 index 00000000000..fe8c84793c0 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/hashes_generic.go @@ -0,0 +1,27 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !gc || purego || !s390x + +package sha3 + +import ( + "hash" +) + +// new224Asm returns an assembly implementation of SHA3-224 if available, +// otherwise it returns nil. +func new224Asm() hash.Hash { return nil } + +// new256Asm returns an assembly implementation of SHA3-256 if available, +// otherwise it returns nil. +func new256Asm() hash.Hash { return nil } + +// new384Asm returns an assembly implementation of SHA3-384 if available, +// otherwise it returns nil. +func new384Asm() hash.Hash { return nil } + +// new512Asm returns an assembly implementation of SHA3-512 if available, +// otherwise it returns nil. +func new512Asm() hash.Hash { return nil } diff --git a/src/vendor/golang.org/x/crypto/sha3/keccakf.go b/src/vendor/golang.org/x/crypto/sha3/keccakf.go new file mode 100644 index 00000000000..ce48b1dd3ed --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/keccakf.go @@ -0,0 +1,414 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 || purego || !gc + +package sha3 + +import "math/bits" + +// rc stores the round constants for use in the ι step. +var rc = [24]uint64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +} + +// keccakF1600 applies the Keccak permutation to a 1600b-wide +// state represented as a slice of 25 uint64s. +func keccakF1600(a *[25]uint64) { + // Implementation translated from Keccak-inplace.c + // in the keccak reference code. + var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 + + for i := 0; i < 24; i += 4 { + // Combines the 5 steps in each round into 2 steps. + // Unrolls 4 rounds per loop and spreads some steps across rounds. + + // Round 1 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[6] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[12] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[18] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[24] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] + a[6] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[16] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[22] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[3] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[10] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[1] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[7] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[19] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[20] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[11] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[23] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[4] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[5] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[2] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[8] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[14] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[15] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + // Round 2 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[16] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[7] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[23] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[14] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] + a[16] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[11] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[2] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[18] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[20] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[6] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[22] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[4] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[15] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[1] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[8] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[24] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[10] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[12] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[3] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[19] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[5] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + // Round 3 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[11] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[22] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[8] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[19] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] + a[11] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[1] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[12] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[23] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[15] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[16] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[2] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[24] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[5] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[6] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[3] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[14] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[20] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[7] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[18] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[4] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[10] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + // Round 4 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[1] ^ d1 + bc1 = bits.RotateLeft64(t, 44) + t = a[2] ^ d2 + bc2 = bits.RotateLeft64(t, 43) + t = a[3] ^ d3 + bc3 = bits.RotateLeft64(t, 21) + t = a[4] ^ d4 + bc4 = bits.RotateLeft64(t, 14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] + a[1] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc2 = bits.RotateLeft64(t, 3) + t = a[6] ^ d1 + bc3 = bits.RotateLeft64(t, 45) + t = a[7] ^ d2 + bc4 = bits.RotateLeft64(t, 61) + t = a[8] ^ d3 + bc0 = bits.RotateLeft64(t, 28) + t = a[9] ^ d4 + bc1 = bits.RotateLeft64(t, 20) + a[5] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc4 = bits.RotateLeft64(t, 18) + t = a[11] ^ d1 + bc0 = bits.RotateLeft64(t, 1) + t = a[12] ^ d2 + bc1 = bits.RotateLeft64(t, 6) + t = a[13] ^ d3 + bc2 = bits.RotateLeft64(t, 25) + t = a[14] ^ d4 + bc3 = bits.RotateLeft64(t, 8) + a[10] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc1 = bits.RotateLeft64(t, 36) + t = a[16] ^ d1 + bc2 = bits.RotateLeft64(t, 10) + t = a[17] ^ d2 + bc3 = bits.RotateLeft64(t, 15) + t = a[18] ^ d3 + bc4 = bits.RotateLeft64(t, 56) + t = a[19] ^ d4 + bc0 = bits.RotateLeft64(t, 27) + a[15] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc3 = bits.RotateLeft64(t, 41) + t = a[21] ^ d1 + bc4 = bits.RotateLeft64(t, 2) + t = a[22] ^ d2 + bc0 = bits.RotateLeft64(t, 62) + t = a[23] ^ d3 + bc1 = bits.RotateLeft64(t, 55) + t = a[24] ^ d4 + bc2 = bits.RotateLeft64(t, 39) + a[20] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + } +} diff --git a/src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go b/src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go new file mode 100644 index 00000000000..b908696be58 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go @@ -0,0 +1,13 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && !purego && gc + +package sha3 + +// This function is implemented in keccakf_amd64.s. + +//go:noescape + +func keccakF1600(a *[25]uint64) diff --git a/src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s b/src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s new file mode 100644 index 00000000000..1f539388619 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s @@ -0,0 +1,390 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build amd64 && !purego && gc + +// This code was translated into a form compatible with 6a from the public +// domain sources at https://github.com/gvanas/KeccakCodePackage + +// Offsets in state +#define _ba (0*8) +#define _be (1*8) +#define _bi (2*8) +#define _bo (3*8) +#define _bu (4*8) +#define _ga (5*8) +#define _ge (6*8) +#define _gi (7*8) +#define _go (8*8) +#define _gu (9*8) +#define _ka (10*8) +#define _ke (11*8) +#define _ki (12*8) +#define _ko (13*8) +#define _ku (14*8) +#define _ma (15*8) +#define _me (16*8) +#define _mi (17*8) +#define _mo (18*8) +#define _mu (19*8) +#define _sa (20*8) +#define _se (21*8) +#define _si (22*8) +#define _so (23*8) +#define _su (24*8) + +// Temporary registers +#define rT1 AX + +// Round vars +#define rpState DI +#define rpStack SP + +#define rDa BX +#define rDe CX +#define rDi DX +#define rDo R8 +#define rDu R9 + +#define rBa R10 +#define rBe R11 +#define rBi R12 +#define rBo R13 +#define rBu R14 + +#define rCa SI +#define rCe BP +#define rCi rBi +#define rCo rBo +#define rCu R15 + +#define MOVQ_RBI_RCE MOVQ rBi, rCe +#define XORQ_RT1_RCA XORQ rT1, rCa +#define XORQ_RT1_RCE XORQ rT1, rCe +#define XORQ_RBA_RCU XORQ rBa, rCu +#define XORQ_RBE_RCU XORQ rBe, rCu +#define XORQ_RDU_RCU XORQ rDu, rCu +#define XORQ_RDA_RCA XORQ rDa, rCa +#define XORQ_RDE_RCE XORQ rDe, rCe + +#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ + /* Prepare round */ \ + MOVQ rCe, rDa; \ + ROLQ $1, rDa; \ + \ + MOVQ _bi(iState), rCi; \ + XORQ _gi(iState), rDi; \ + XORQ rCu, rDa; \ + XORQ _ki(iState), rCi; \ + XORQ _mi(iState), rDi; \ + XORQ rDi, rCi; \ + \ + MOVQ rCi, rDe; \ + ROLQ $1, rDe; \ + \ + MOVQ _bo(iState), rCo; \ + XORQ _go(iState), rDo; \ + XORQ rCa, rDe; \ + XORQ _ko(iState), rCo; \ + XORQ _mo(iState), rDo; \ + XORQ rDo, rCo; \ + \ + MOVQ rCo, rDi; \ + ROLQ $1, rDi; \ + \ + MOVQ rCu, rDo; \ + XORQ rCe, rDi; \ + ROLQ $1, rDo; \ + \ + MOVQ rCa, rDu; \ + XORQ rCi, rDo; \ + ROLQ $1, rDu; \ + \ + /* Result b */ \ + MOVQ _ba(iState), rBa; \ + MOVQ _ge(iState), rBe; \ + XORQ rCo, rDu; \ + MOVQ _ki(iState), rBi; \ + MOVQ _mo(iState), rBo; \ + MOVQ _su(iState), rBu; \ + XORQ rDe, rBe; \ + ROLQ $44, rBe; \ + XORQ rDi, rBi; \ + XORQ rDa, rBa; \ + ROLQ $43, rBi; \ + \ + MOVQ rBe, rCa; \ + MOVQ rc, rT1; \ + ORQ rBi, rCa; \ + XORQ rBa, rT1; \ + XORQ rT1, rCa; \ + MOVQ rCa, _ba(oState); \ + \ + XORQ rDu, rBu; \ + ROLQ $14, rBu; \ + MOVQ rBa, rCu; \ + ANDQ rBe, rCu; \ + XORQ rBu, rCu; \ + MOVQ rCu, _bu(oState); \ + \ + XORQ rDo, rBo; \ + ROLQ $21, rBo; \ + MOVQ rBo, rT1; \ + ANDQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _bi(oState); \ + \ + NOTQ rBi; \ + ORQ rBa, rBu; \ + ORQ rBo, rBi; \ + XORQ rBo, rBu; \ + XORQ rBe, rBi; \ + MOVQ rBu, _bo(oState); \ + MOVQ rBi, _be(oState); \ + B_RBI_RCE; \ + \ + /* Result g */ \ + MOVQ _gu(iState), rBe; \ + XORQ rDu, rBe; \ + MOVQ _ka(iState), rBi; \ + ROLQ $20, rBe; \ + XORQ rDa, rBi; \ + ROLQ $3, rBi; \ + MOVQ _bo(iState), rBa; \ + MOVQ rBe, rT1; \ + ORQ rBi, rT1; \ + XORQ rDo, rBa; \ + MOVQ _me(iState), rBo; \ + MOVQ _si(iState), rBu; \ + ROLQ $28, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ga(oState); \ + G_RT1_RCA; \ + \ + XORQ rDe, rBo; \ + ROLQ $45, rBo; \ + MOVQ rBi, rT1; \ + ANDQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _ge(oState); \ + G_RT1_RCE; \ + \ + XORQ rDi, rBu; \ + ROLQ $61, rBu; \ + MOVQ rBu, rT1; \ + ORQ rBa, rT1; \ + XORQ rBo, rT1; \ + MOVQ rT1, _go(oState); \ + \ + ANDQ rBe, rBa; \ + XORQ rBu, rBa; \ + MOVQ rBa, _gu(oState); \ + NOTQ rBu; \ + G_RBA_RCU; \ + \ + ORQ rBu, rBo; \ + XORQ rBi, rBo; \ + MOVQ rBo, _gi(oState); \ + \ + /* Result k */ \ + MOVQ _be(iState), rBa; \ + MOVQ _gi(iState), rBe; \ + MOVQ _ko(iState), rBi; \ + MOVQ _mu(iState), rBo; \ + MOVQ _sa(iState), rBu; \ + XORQ rDi, rBe; \ + ROLQ $6, rBe; \ + XORQ rDo, rBi; \ + ROLQ $25, rBi; \ + MOVQ rBe, rT1; \ + ORQ rBi, rT1; \ + XORQ rDe, rBa; \ + ROLQ $1, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ka(oState); \ + K_RT1_RCA; \ + \ + XORQ rDu, rBo; \ + ROLQ $8, rBo; \ + MOVQ rBi, rT1; \ + ANDQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _ke(oState); \ + K_RT1_RCE; \ + \ + XORQ rDa, rBu; \ + ROLQ $18, rBu; \ + NOTQ rBo; \ + MOVQ rBo, rT1; \ + ANDQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _ki(oState); \ + \ + MOVQ rBu, rT1; \ + ORQ rBa, rT1; \ + XORQ rBo, rT1; \ + MOVQ rT1, _ko(oState); \ + \ + ANDQ rBe, rBa; \ + XORQ rBu, rBa; \ + MOVQ rBa, _ku(oState); \ + K_RBA_RCU; \ + \ + /* Result m */ \ + MOVQ _ga(iState), rBe; \ + XORQ rDa, rBe; \ + MOVQ _ke(iState), rBi; \ + ROLQ $36, rBe; \ + XORQ rDe, rBi; \ + MOVQ _bu(iState), rBa; \ + ROLQ $10, rBi; \ + MOVQ rBe, rT1; \ + MOVQ _mi(iState), rBo; \ + ANDQ rBi, rT1; \ + XORQ rDu, rBa; \ + MOVQ _so(iState), rBu; \ + ROLQ $27, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ma(oState); \ + M_RT1_RCA; \ + \ + XORQ rDi, rBo; \ + ROLQ $15, rBo; \ + MOVQ rBi, rT1; \ + ORQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _me(oState); \ + M_RT1_RCE; \ + \ + XORQ rDo, rBu; \ + ROLQ $56, rBu; \ + NOTQ rBo; \ + MOVQ rBo, rT1; \ + ORQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _mi(oState); \ + \ + ORQ rBa, rBe; \ + XORQ rBu, rBe; \ + MOVQ rBe, _mu(oState); \ + \ + ANDQ rBa, rBu; \ + XORQ rBo, rBu; \ + MOVQ rBu, _mo(oState); \ + M_RBE_RCU; \ + \ + /* Result s */ \ + MOVQ _bi(iState), rBa; \ + MOVQ _go(iState), rBe; \ + MOVQ _ku(iState), rBi; \ + XORQ rDi, rBa; \ + MOVQ _ma(iState), rBo; \ + ROLQ $62, rBa; \ + XORQ rDo, rBe; \ + MOVQ _se(iState), rBu; \ + ROLQ $55, rBe; \ + \ + XORQ rDu, rBi; \ + MOVQ rBa, rDu; \ + XORQ rDe, rBu; \ + ROLQ $2, rBu; \ + ANDQ rBe, rDu; \ + XORQ rBu, rDu; \ + MOVQ rDu, _su(oState); \ + \ + ROLQ $39, rBi; \ + S_RDU_RCU; \ + NOTQ rBe; \ + XORQ rDa, rBo; \ + MOVQ rBe, rDa; \ + ANDQ rBi, rDa; \ + XORQ rBa, rDa; \ + MOVQ rDa, _sa(oState); \ + S_RDA_RCA; \ + \ + ROLQ $41, rBo; \ + MOVQ rBi, rDe; \ + ORQ rBo, rDe; \ + XORQ rBe, rDe; \ + MOVQ rDe, _se(oState); \ + S_RDE_RCE; \ + \ + MOVQ rBo, rDi; \ + MOVQ rBu, rDo; \ + ANDQ rBu, rDi; \ + ORQ rBa, rDo; \ + XORQ rBi, rDi; \ + XORQ rBo, rDo; \ + MOVQ rDi, _si(oState); \ + MOVQ rDo, _so(oState) \ + +// func keccakF1600(a *[25]uint64) +TEXT ·keccakF1600(SB), 0, $200-8 + MOVQ a+0(FP), rpState + + // Convert the user state into an internal state + NOTQ _be(rpState) + NOTQ _bi(rpState) + NOTQ _go(rpState) + NOTQ _ki(rpState) + NOTQ _mi(rpState) + NOTQ _sa(rpState) + + // Execute the KeccakF permutation + MOVQ _ba(rpState), rCa + MOVQ _be(rpState), rCe + MOVQ _bu(rpState), rCu + + XORQ _ga(rpState), rCa + XORQ _ge(rpState), rCe + XORQ _gu(rpState), rCu + + XORQ _ka(rpState), rCa + XORQ _ke(rpState), rCe + XORQ _ku(rpState), rCu + + XORQ _ma(rpState), rCa + XORQ _me(rpState), rCe + XORQ _mu(rpState), rCu + + XORQ _sa(rpState), rCa + XORQ _se(rpState), rCe + MOVQ _si(rpState), rDi + MOVQ _so(rpState), rDo + XORQ _su(rpState), rCu + + mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) + + // Revert the internal state to the user state + NOTQ _be(rpState) + NOTQ _bi(rpState) + NOTQ _go(rpState) + NOTQ _ki(rpState) + NOTQ _mi(rpState) + NOTQ _sa(rpState) + + RET diff --git a/src/vendor/golang.org/x/crypto/sha3/register.go b/src/vendor/golang.org/x/crypto/sha3/register.go new file mode 100644 index 00000000000..addfd5049bb --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/register.go @@ -0,0 +1,18 @@ +// Copyright 2014 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 go1.4 + +package sha3 + +import ( + "crypto" +) + +func init() { + crypto.RegisterHash(crypto.SHA3_224, New224) + crypto.RegisterHash(crypto.SHA3_256, New256) + crypto.RegisterHash(crypto.SHA3_384, New384) + crypto.RegisterHash(crypto.SHA3_512, New512) +} diff --git a/src/vendor/golang.org/x/crypto/sha3/sha3.go b/src/vendor/golang.org/x/crypto/sha3/sha3.go new file mode 100644 index 00000000000..4884d172a49 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/sha3.go @@ -0,0 +1,197 @@ +// Copyright 2014 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 sha3 + +// spongeDirection indicates the direction bytes are flowing through the sponge. +type spongeDirection int + +const ( + // spongeAbsorbing indicates that the sponge is absorbing input. + spongeAbsorbing spongeDirection = iota + // spongeSqueezing indicates that the sponge is being squeezed. + spongeSqueezing +) + +const ( + // maxRate is the maximum size of the internal buffer. SHAKE-256 + // currently needs the largest buffer. + maxRate = 168 +) + +type state struct { + // Generic sponge components. + a [25]uint64 // main state of the hash + buf []byte // points into storage + rate int // the number of bytes of state to use + + // dsbyte contains the "domain separation" bits and the first bit of + // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the + // SHA-3 and SHAKE functions by appending bitstrings to the message. + // Using a little-endian bit-ordering convention, these are "01" for SHA-3 + // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the + // padding rule from section 5.1 is applied to pad the message to a multiple + // of the rate, which involves adding a "1" bit, zero or more "0" bits, and + // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, + // giving 00000110b (0x06) and 00011111b (0x1f). + // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf + // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and + // Extendable-Output Functions (May 2014)" + dsbyte byte + + storage storageBuf + + // Specific to SHA-3 and SHAKE. + outputLen int // the default output size in bytes + state spongeDirection // whether the sponge is absorbing or squeezing +} + +// BlockSize returns the rate of sponge underlying this hash function. +func (d *state) BlockSize() int { return d.rate } + +// Size returns the output size of the hash function in bytes. +func (d *state) Size() int { return d.outputLen } + +// Reset clears the internal state by zeroing the sponge state and +// the byte buffer, and setting Sponge.state to absorbing. +func (d *state) Reset() { + // Zero the permutation's state. + for i := range d.a { + d.a[i] = 0 + } + d.state = spongeAbsorbing + d.buf = d.storage.asBytes()[:0] +} + +func (d *state) clone() *state { + ret := *d + if ret.state == spongeAbsorbing { + ret.buf = ret.storage.asBytes()[:len(ret.buf)] + } else { + ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate] + } + + return &ret +} + +// permute applies the KeccakF-1600 permutation. It handles +// any input-output buffering. +func (d *state) permute() { + switch d.state { + case spongeAbsorbing: + // If we're absorbing, we need to xor the input into the state + // before applying the permutation. + xorIn(d, d.buf) + d.buf = d.storage.asBytes()[:0] + keccakF1600(&d.a) + case spongeSqueezing: + // If we're squeezing, we need to apply the permutation before + // copying more output. + keccakF1600(&d.a) + d.buf = d.storage.asBytes()[:d.rate] + copyOut(d, d.buf) + } +} + +// pads appends the domain separation bits in dsbyte, applies +// the multi-bitrate 10..1 padding rule, and permutes the state. +func (d *state) padAndPermute(dsbyte byte) { + if d.buf == nil { + d.buf = d.storage.asBytes()[:0] + } + // Pad with this instance's domain-separator bits. We know that there's + // at least one byte of space in d.buf because, if it were full, + // permute would have been called to empty it. dsbyte also contains the + // first one bit for the padding. See the comment in the state struct. + d.buf = append(d.buf, dsbyte) + zerosStart := len(d.buf) + d.buf = d.storage.asBytes()[:d.rate] + for i := zerosStart; i < d.rate; i++ { + d.buf[i] = 0 + } + // This adds the final one bit for the padding. Because of the way that + // bits are numbered from the LSB upwards, the final bit is the MSB of + // the last byte. + d.buf[d.rate-1] ^= 0x80 + // Apply the permutation + d.permute() + d.state = spongeSqueezing + d.buf = d.storage.asBytes()[:d.rate] + copyOut(d, d.buf) +} + +// Write absorbs more data into the hash's state. It panics if any +// output has already been read. +func (d *state) Write(p []byte) (written int, err error) { + if d.state != spongeAbsorbing { + panic("sha3: Write after Read") + } + if d.buf == nil { + d.buf = d.storage.asBytes()[:0] + } + written = len(p) + + for len(p) > 0 { + if len(d.buf) == 0 && len(p) >= d.rate { + // The fast path; absorb a full "rate" bytes of input and apply the permutation. + xorIn(d, p[:d.rate]) + p = p[d.rate:] + keccakF1600(&d.a) + } else { + // The slow path; buffer the input until we can fill the sponge, and then xor it in. + todo := d.rate - len(d.buf) + if todo > len(p) { + todo = len(p) + } + d.buf = append(d.buf, p[:todo]...) + p = p[todo:] + + // If the sponge is full, apply the permutation. + if len(d.buf) == d.rate { + d.permute() + } + } + } + + return +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (d *state) Read(out []byte) (n int, err error) { + // If we're still absorbing, pad and apply the permutation. + if d.state == spongeAbsorbing { + d.padAndPermute(d.dsbyte) + } + + n = len(out) + + // Now, do the squeezing. + for len(out) > 0 { + n := copy(out, d.buf) + d.buf = d.buf[n:] + out = out[n:] + + // Apply the permutation if we've squeezed the sponge dry. + if len(d.buf) == 0 { + d.permute() + } + } + + return +} + +// Sum applies padding to the hash state and then squeezes out the desired +// number of output bytes. It panics if any output has already been read. +func (d *state) Sum(in []byte) []byte { + if d.state != spongeAbsorbing { + panic("sha3: Sum after Read") + } + + // Make a copy of the original hash so that caller can keep writing + // and summing. + dup := d.clone() + hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation + dup.Read(hash) + return append(in, hash...) +} diff --git a/src/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/src/vendor/golang.org/x/crypto/sha3/sha3_s390x.go new file mode 100644 index 00000000000..d861bca5286 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/sha3_s390x.go @@ -0,0 +1,288 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego + +package sha3 + +// This file contains code for using the 'compute intermediate +// message digest' (KIMD) and 'compute last message digest' (KLMD) +// instructions to compute SHA-3 and SHAKE hashes on IBM Z. + +import ( + "hash" + + "golang.org/x/sys/cpu" +) + +// codes represent 7-bit KIMD/KLMD function codes as defined in +// the Principles of Operation. +type code uint64 + +const ( + // function codes for KIMD/KLMD + sha3_224 code = 32 + sha3_256 = 33 + sha3_384 = 34 + sha3_512 = 35 + shake_128 = 36 + shake_256 = 37 + nopad = 0x100 +) + +// kimd is a wrapper for the 'compute intermediate message digest' instruction. +// src must be a multiple of the rate for the given function code. +// +//go:noescape +func kimd(function code, chain *[200]byte, src []byte) + +// klmd is a wrapper for the 'compute last message digest' instruction. +// src padding is handled by the instruction. +// +//go:noescape +func klmd(function code, chain *[200]byte, dst, src []byte) + +type asmState struct { + a [200]byte // 1600 bit state + buf []byte // care must be taken to ensure cap(buf) is a multiple of rate + rate int // equivalent to block size + storage [3072]byte // underlying storage for buf + outputLen int // output length for full security + function code // KIMD/KLMD function code + state spongeDirection // whether the sponge is absorbing or squeezing +} + +func newAsmState(function code) *asmState { + var s asmState + s.function = function + switch function { + case sha3_224: + s.rate = 144 + s.outputLen = 28 + case sha3_256: + s.rate = 136 + s.outputLen = 32 + case sha3_384: + s.rate = 104 + s.outputLen = 48 + case sha3_512: + s.rate = 72 + s.outputLen = 64 + case shake_128: + s.rate = 168 + s.outputLen = 32 + case shake_256: + s.rate = 136 + s.outputLen = 64 + default: + panic("sha3: unrecognized function code") + } + + // limit s.buf size to a multiple of s.rate + s.resetBuf() + return &s +} + +func (s *asmState) clone() *asmState { + c := *s + c.buf = c.storage[:len(s.buf):cap(s.buf)] + return &c +} + +// copyIntoBuf copies b into buf. It will panic if there is not enough space to +// store all of b. +func (s *asmState) copyIntoBuf(b []byte) { + bufLen := len(s.buf) + s.buf = s.buf[:len(s.buf)+len(b)] + copy(s.buf[bufLen:], b) +} + +// resetBuf points buf at storage, sets the length to 0 and sets cap to be a +// multiple of the rate. +func (s *asmState) resetBuf() { + max := (cap(s.storage) / s.rate) * s.rate + s.buf = s.storage[:0:max] +} + +// Write (via the embedded io.Writer interface) adds more data to the running hash. +// It never returns an error. +func (s *asmState) Write(b []byte) (int, error) { + if s.state != spongeAbsorbing { + panic("sha3: Write after Read") + } + length := len(b) + for len(b) > 0 { + if len(s.buf) == 0 && len(b) >= cap(s.buf) { + // Hash the data directly and push any remaining bytes + // into the buffer. + remainder := len(b) % s.rate + kimd(s.function, &s.a, b[:len(b)-remainder]) + if remainder != 0 { + s.copyIntoBuf(b[len(b)-remainder:]) + } + return length, nil + } + + if len(s.buf) == cap(s.buf) { + // flush the buffer + kimd(s.function, &s.a, s.buf) + s.buf = s.buf[:0] + } + + // copy as much as we can into the buffer + n := len(b) + if len(b) > cap(s.buf)-len(s.buf) { + n = cap(s.buf) - len(s.buf) + } + s.copyIntoBuf(b[:n]) + b = b[n:] + } + return length, nil +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (s *asmState) Read(out []byte) (n int, err error) { + n = len(out) + + // need to pad if we were absorbing + if s.state == spongeAbsorbing { + s.state = spongeSqueezing + + // write hash directly into out if possible + if len(out)%s.rate == 0 { + klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 + s.buf = s.buf[:0] + return + } + + // write hash into buffer + max := cap(s.buf) + if max > len(out) { + max = (len(out)/s.rate)*s.rate + s.rate + } + klmd(s.function, &s.a, s.buf[:max], s.buf) + s.buf = s.buf[:max] + } + + for len(out) > 0 { + // flush the buffer + if len(s.buf) != 0 { + c := copy(out, s.buf) + out = out[c:] + s.buf = s.buf[c:] + continue + } + + // write hash directly into out if possible + if len(out)%s.rate == 0 { + klmd(s.function|nopad, &s.a, out, nil) + return + } + + // write hash into buffer + s.resetBuf() + if cap(s.buf) > len(out) { + s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] + } + klmd(s.function|nopad, &s.a, s.buf, nil) + } + return +} + +// Sum appends the current hash to b and returns the resulting slice. +// It does not change the underlying hash state. +func (s *asmState) Sum(b []byte) []byte { + if s.state != spongeAbsorbing { + panic("sha3: Sum after Read") + } + + // Copy the state to preserve the original. + a := s.a + + // Hash the buffer. Note that we don't clear it because we + // aren't updating the state. + klmd(s.function, &a, nil, s.buf) + return append(b, a[:s.outputLen]...) +} + +// Reset resets the Hash to its initial state. +func (s *asmState) Reset() { + for i := range s.a { + s.a[i] = 0 + } + s.resetBuf() + s.state = spongeAbsorbing +} + +// Size returns the number of bytes Sum will return. +func (s *asmState) Size() int { + return s.outputLen +} + +// BlockSize returns the hash's underlying block size. +// The Write method must be able to accept any amount +// of data, but it may operate more efficiently if all writes +// are a multiple of the block size. +func (s *asmState) BlockSize() int { + return s.rate +} + +// Clone returns a copy of the ShakeHash in its current state. +func (s *asmState) Clone() ShakeHash { + return s.clone() +} + +// new224Asm returns an assembly implementation of SHA3-224 if available, +// otherwise it returns nil. +func new224Asm() hash.Hash { + if cpu.S390X.HasSHA3 { + return newAsmState(sha3_224) + } + return nil +} + +// new256Asm returns an assembly implementation of SHA3-256 if available, +// otherwise it returns nil. +func new256Asm() hash.Hash { + if cpu.S390X.HasSHA3 { + return newAsmState(sha3_256) + } + return nil +} + +// new384Asm returns an assembly implementation of SHA3-384 if available, +// otherwise it returns nil. +func new384Asm() hash.Hash { + if cpu.S390X.HasSHA3 { + return newAsmState(sha3_384) + } + return nil +} + +// new512Asm returns an assembly implementation of SHA3-512 if available, +// otherwise it returns nil. +func new512Asm() hash.Hash { + if cpu.S390X.HasSHA3 { + return newAsmState(sha3_512) + } + return nil +} + +// newShake128Asm returns an assembly implementation of SHAKE-128 if available, +// otherwise it returns nil. +func newShake128Asm() ShakeHash { + if cpu.S390X.HasSHA3 { + return newAsmState(shake_128) + } + return nil +} + +// newShake256Asm returns an assembly implementation of SHAKE-256 if available, +// otherwise it returns nil. +func newShake256Asm() ShakeHash { + if cpu.S390X.HasSHA3 { + return newAsmState(shake_256) + } + return nil +} diff --git a/src/vendor/golang.org/x/crypto/sha3/sha3_s390x.s b/src/vendor/golang.org/x/crypto/sha3/sha3_s390x.s new file mode 100644 index 00000000000..826b862c779 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/sha3_s390x.s @@ -0,0 +1,33 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego + +#include "textflag.h" + +// func kimd(function code, chain *[200]byte, src []byte) +TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 + MOVD function+0(FP), R0 + MOVD chain+8(FP), R1 + LMG src+16(FP), R2, R3 // R2=base, R3=len + +continue: + WORD $0xB93E0002 // KIMD --, R2 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET + +// func klmd(function code, chain *[200]byte, dst, src []byte) +TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 + // TODO: SHAKE support + MOVD function+0(FP), R0 + MOVD chain+8(FP), R1 + LMG dst+16(FP), R2, R3 // R2=base, R3=len + LMG src+40(FP), R4, R5 // R4=base, R5=len + +continue: + WORD $0xB93F0024 // KLMD R2, R4 + BVS continue // continue if interrupted + MOVD $0, R0 // reset R0 for pre-go1.8 compilers + RET diff --git a/src/vendor/golang.org/x/crypto/sha3/shake.go b/src/vendor/golang.org/x/crypto/sha3/shake.go new file mode 100644 index 00000000000..bb69984027f --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/shake.go @@ -0,0 +1,172 @@ +// Copyright 2014 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 sha3 + +// This file defines the ShakeHash interface, and provides +// functions for creating SHAKE and cSHAKE instances, as well as utility +// functions for hashing bytes to arbitrary-length output. +// +// +// SHAKE implementation is based on FIPS PUB 202 [1] +// cSHAKE implementations is based on NIST SP 800-185 [2] +// +// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf +// [2] https://doi.org/10.6028/NIST.SP.800-185 + +import ( + "encoding/binary" + "hash" + "io" +) + +// ShakeHash defines the interface to hash functions that support +// arbitrary-length output. When used as a plain [hash.Hash], it +// produces minimum-length outputs that provide full-strength generic +// security. +type ShakeHash interface { + hash.Hash + + // Read reads more output from the hash; reading affects the hash's + // state. (ShakeHash.Read is thus very different from Hash.Sum) + // It never returns an error, but subsequent calls to Write or Sum + // will panic. + io.Reader + + // Clone returns a copy of the ShakeHash in its current state. + Clone() ShakeHash +} + +// cSHAKE specific context +type cshakeState struct { + *state // SHA-3 state context and Read/Write operations + + // initBlock is the cSHAKE specific initialization set of bytes. It is initialized + // by newCShake function and stores concatenation of N followed by S, encoded + // by the method specified in 3.3 of [1]. + // It is stored here in order for Reset() to be able to put context into + // initial state. + initBlock []byte +} + +// Consts for configuring initial SHA-3 state +const ( + dsbyteShake = 0x1f + dsbyteCShake = 0x04 + rate128 = 168 + rate256 = 136 +) + +func bytepad(input []byte, w int) []byte { + // leftEncode always returns max 9 bytes + buf := make([]byte, 0, 9+len(input)+w) + buf = append(buf, leftEncode(uint64(w))...) + buf = append(buf, input...) + padlen := w - (len(buf) % w) + return append(buf, make([]byte, padlen)...) +} + +func leftEncode(value uint64) []byte { + var b [9]byte + binary.BigEndian.PutUint64(b[1:], value) + // Trim all but last leading zero bytes + i := byte(1) + for i < 8 && b[i] == 0 { + i++ + } + // Prepend number of encoded bytes + b[i-1] = 9 - i + return b[i-1:] +} + +func newCShake(N, S []byte, rate, outputLen int, dsbyte byte) ShakeHash { + c := cshakeState{state: &state{rate: rate, outputLen: outputLen, dsbyte: dsbyte}} + + // leftEncode returns max 9 bytes + c.initBlock = make([]byte, 0, 9*2+len(N)+len(S)) + c.initBlock = append(c.initBlock, leftEncode(uint64(len(N)*8))...) + c.initBlock = append(c.initBlock, N...) + c.initBlock = append(c.initBlock, leftEncode(uint64(len(S)*8))...) + c.initBlock = append(c.initBlock, S...) + c.Write(bytepad(c.initBlock, c.rate)) + return &c +} + +// Reset resets the hash to initial state. +func (c *cshakeState) Reset() { + c.state.Reset() + c.Write(bytepad(c.initBlock, c.rate)) +} + +// Clone returns copy of a cSHAKE context within its current state. +func (c *cshakeState) Clone() ShakeHash { + b := make([]byte, len(c.initBlock)) + copy(b, c.initBlock) + return &cshakeState{state: c.clone(), initBlock: b} +} + +// Clone returns copy of SHAKE context within its current state. +func (c *state) Clone() ShakeHash { + return c.clone() +} + +// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. +// Its generic security strength is 128 bits against all attacks if at +// least 32 bytes of its output are used. +func NewShake128() ShakeHash { + if h := newShake128Asm(); h != nil { + return h + } + return &state{rate: rate128, outputLen: 32, dsbyte: dsbyteShake} +} + +// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. +// Its generic security strength is 256 bits against all attacks if +// at least 64 bytes of its output are used. +func NewShake256() ShakeHash { + if h := newShake256Asm(); h != nil { + return h + } + return &state{rate: rate256, outputLen: 64, dsbyte: dsbyteShake} +} + +// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash, +// a customizable variant of SHAKE128. +// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is +// desired. S is a customization byte string used for domain separation - two cSHAKE +// computations on same input with different S yield unrelated outputs. +// When N and S are both empty, this is equivalent to NewShake128. +func NewCShake128(N, S []byte) ShakeHash { + if len(N) == 0 && len(S) == 0 { + return NewShake128() + } + return newCShake(N, S, rate128, 32, dsbyteCShake) +} + +// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash, +// a customizable variant of SHAKE256. +// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is +// desired. S is a customization byte string used for domain separation - two cSHAKE +// computations on same input with different S yield unrelated outputs. +// When N and S are both empty, this is equivalent to NewShake256. +func NewCShake256(N, S []byte) ShakeHash { + if len(N) == 0 && len(S) == 0 { + return NewShake256() + } + return newCShake(N, S, rate256, 64, dsbyteCShake) +} + +// ShakeSum128 writes an arbitrary-length digest of data into hash. +func ShakeSum128(hash, data []byte) { + h := NewShake128() + h.Write(data) + h.Read(hash) +} + +// ShakeSum256 writes an arbitrary-length digest of data into hash. +func ShakeSum256(hash, data []byte) { + h := NewShake256() + h.Write(data) + h.Read(hash) +} diff --git a/src/vendor/golang.org/x/crypto/sha3/shake_generic.go b/src/vendor/golang.org/x/crypto/sha3/shake_generic.go new file mode 100644 index 00000000000..8d31cf5be2d --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/shake_generic.go @@ -0,0 +1,19 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !gc || purego || !s390x + +package sha3 + +// newShake128Asm returns an assembly implementation of SHAKE-128 if available, +// otherwise it returns nil. +func newShake128Asm() ShakeHash { + return nil +} + +// newShake256Asm returns an assembly implementation of SHAKE-256 if available, +// otherwise it returns nil. +func newShake256Asm() ShakeHash { + return nil +} diff --git a/src/vendor/golang.org/x/crypto/sha3/xor.go b/src/vendor/golang.org/x/crypto/sha3/xor.go new file mode 100644 index 00000000000..7337cca88ed --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/xor.go @@ -0,0 +1,23 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!amd64 && !386 && !ppc64le) || purego + +package sha3 + +// A storageBuf is an aligned array of maxRate bytes. +type storageBuf [maxRate]byte + +func (b *storageBuf) asBytes() *[maxRate]byte { + return (*[maxRate]byte)(b) +} + +var ( + xorIn = xorInGeneric + copyOut = copyOutGeneric + xorInUnaligned = xorInGeneric + copyOutUnaligned = copyOutGeneric +) + +const xorImplementationUnaligned = "generic" diff --git a/src/vendor/golang.org/x/crypto/sha3/xor_generic.go b/src/vendor/golang.org/x/crypto/sha3/xor_generic.go new file mode 100644 index 00000000000..8d947711272 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/xor_generic.go @@ -0,0 +1,28 @@ +// Copyright 2015 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 sha3 + +import "encoding/binary" + +// xorInGeneric xors the bytes in buf into the state; it +// makes no non-portable assumptions about memory layout +// or alignment. +func xorInGeneric(d *state, buf []byte) { + n := len(buf) / 8 + + for i := 0; i < n; i++ { + a := binary.LittleEndian.Uint64(buf) + d.a[i] ^= a + buf = buf[8:] + } +} + +// copyOutGeneric copies uint64s to a byte buffer. +func copyOutGeneric(d *state, b []byte) { + for i := 0; len(b) >= 8; i++ { + binary.LittleEndian.PutUint64(b, d.a[i]) + b = b[8:] + } +} diff --git a/src/vendor/golang.org/x/crypto/sha3/xor_unaligned.go b/src/vendor/golang.org/x/crypto/sha3/xor_unaligned.go new file mode 100644 index 00000000000..870e2d16e07 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/sha3/xor_unaligned.go @@ -0,0 +1,66 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (amd64 || 386 || ppc64le) && !purego + +package sha3 + +import "unsafe" + +// A storageBuf is an aligned array of maxRate bytes. +type storageBuf [maxRate / 8]uint64 + +func (b *storageBuf) asBytes() *[maxRate]byte { + return (*[maxRate]byte)(unsafe.Pointer(b)) +} + +// xorInUnaligned uses unaligned reads and writes to update d.a to contain d.a +// XOR buf. +func xorInUnaligned(d *state, buf []byte) { + n := len(buf) + bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] + if n >= 72 { + d.a[0] ^= bw[0] + d.a[1] ^= bw[1] + d.a[2] ^= bw[2] + d.a[3] ^= bw[3] + d.a[4] ^= bw[4] + d.a[5] ^= bw[5] + d.a[6] ^= bw[6] + d.a[7] ^= bw[7] + d.a[8] ^= bw[8] + } + if n >= 104 { + d.a[9] ^= bw[9] + d.a[10] ^= bw[10] + d.a[11] ^= bw[11] + d.a[12] ^= bw[12] + } + if n >= 136 { + d.a[13] ^= bw[13] + d.a[14] ^= bw[14] + d.a[15] ^= bw[15] + d.a[16] ^= bw[16] + } + if n >= 144 { + d.a[17] ^= bw[17] + } + if n >= 168 { + d.a[18] ^= bw[18] + d.a[19] ^= bw[19] + d.a[20] ^= bw[20] + } +} + +func copyOutUnaligned(d *state, buf []byte) { + ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) + copy(buf, ab[:]) +} + +var ( + xorIn = xorInUnaligned + copyOut = copyOutUnaligned +) + +const xorImplementationUnaligned = "unaligned" diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 9a234e59b10..b52c02e61c0 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,5 +1,50 @@ +# github.com/cloudflare/circl v1.4.1-0.20240905130006-2d6cd9871f69 +## explicit; go 1.21 +github.com/cloudflare/circl/dh/x25519 +github.com/cloudflare/circl/dh/x448 +github.com/cloudflare/circl/ecc/goldilocks +github.com/cloudflare/circl/ecc/p384 +github.com/cloudflare/circl/hpke +github.com/cloudflare/circl/internal/conv +github.com/cloudflare/circl/internal/sha3 +github.com/cloudflare/circl/kem +github.com/cloudflare/circl/kem/hybrid +github.com/cloudflare/circl/kem/kyber/kyber1024 +github.com/cloudflare/circl/kem/kyber/kyber512 +github.com/cloudflare/circl/kem/kyber/kyber768 +github.com/cloudflare/circl/kem/mlkem/mlkem768 +github.com/cloudflare/circl/math +github.com/cloudflare/circl/math/fp25519 +github.com/cloudflare/circl/math/fp448 +github.com/cloudflare/circl/math/mlsbset +github.com/cloudflare/circl/pke/kyber/internal/common +github.com/cloudflare/circl/pke/kyber/internal/common/params +github.com/cloudflare/circl/pke/kyber/kyber1024 +github.com/cloudflare/circl/pke/kyber/kyber1024/internal +github.com/cloudflare/circl/pke/kyber/kyber512 +github.com/cloudflare/circl/pke/kyber/kyber512/internal +github.com/cloudflare/circl/pke/kyber/kyber768 +github.com/cloudflare/circl/pke/kyber/kyber768/internal +github.com/cloudflare/circl/pki +github.com/cloudflare/circl/sign +github.com/cloudflare/circl/sign/dilithium/internal/common +github.com/cloudflare/circl/sign/dilithium/internal/common/params +github.com/cloudflare/circl/sign/dilithium/mode2 +github.com/cloudflare/circl/sign/dilithium/mode2/internal +github.com/cloudflare/circl/sign/dilithium/mode3 +github.com/cloudflare/circl/sign/dilithium/mode3/internal +github.com/cloudflare/circl/sign/ed25519 +github.com/cloudflare/circl/sign/ed448 +github.com/cloudflare/circl/sign/eddilithium2 +github.com/cloudflare/circl/sign/eddilithium3 +github.com/cloudflare/circl/sign/schemes +github.com/cloudflare/circl/simd/keccakf1600 +github.com/cloudflare/circl/xof +github.com/cloudflare/circl/xof/k12 # golang.org/x/crypto v0.16.1-0.20231129163542-152cdb1503eb ## explicit; go 1.18 +golang.org/x/crypto/blake2b +golang.org/x/crypto/blake2s golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20poly1305 golang.org/x/crypto/cryptobyte @@ -7,6 +52,7 @@ golang.org/x/crypto/cryptobyte/asn1 golang.org/x/crypto/hkdf golang.org/x/crypto/internal/alias golang.org/x/crypto/internal/poly1305 +golang.org/x/crypto/sha3 # golang.org/x/net v0.19.1-0.20240412193750-db050b07227e ## explicit; go 1.18 golang.org/x/net/dns/dnsmessage