From ad6d8311cce6dcaf2af788a193ed1c7557f9c86a Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Mon, 2 Oct 2023 15:14:26 +0200 Subject: [PATCH 01/21] Add README (#158) Add README Co-authored-by: Peter Wu --- README.md | 53 ++++++++++++++++++----------------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) 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`. From f6c2818f005d10245077b1123f153c6aa6b36a2e Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 22 Jul 2020 12:12:30 +0200 Subject: [PATCH 02/21] VERSION: add cf tag Include the `-cf` tag so this fork can be identified. Include the `devel` tag such that we can potentially add new APIs to the api/next.txt file in order to please the TestDependencies test. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 12d930db8511b3b886cf80e5560f39837949cc69 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 22 Jul 2020 12:11:34 +0200 Subject: [PATCH 03/21] cmd/go/internal/imports, go/build: add cfgo build tag This allows applications to use build tags to maintain compatibility with both this fork as well as standard Go. [ bas 2023-10-6: Fix cfgo build tag and add a test (#156) ] --- src/crypto/tls/cfgo_test.go | 9 +++++++++ src/internal/buildcfg/cfg.go | 1 + 2 files changed, 10 insertions(+) create mode 100644 src/crypto/tls/cfgo_test.go 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/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 } From 98209d8da8ba10def16f988e1c8d5b489ec4a49f Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Thu, 19 Aug 2021 17:09:39 +0200 Subject: [PATCH 04/21] .github: add docker-compose.yaml and GitHub Action for CI Tests can be run from the repo with: `docker-compose run test` --- .github/workflows/test.yml | 15 +++++++++++++++ docker-compose.yaml | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 .github/workflows/test.yml create mode 100644 docker-compose.yaml 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/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 From 8846cd808b031a1e6e93bf3a8e125af9c6b2305c Mon Sep 17 00:00:00 2001 From: Christopher Patton Date: Tue, 15 Jun 2021 14:47:09 -0700 Subject: [PATCH 05/21] .github: replace upstream templates and CODE_OF_CONDUCT.md [pwu: Go 1.22.0: resolve conflicts: git rm -r .github/ISSUE_TEMPLATE] --- .github/CODE_OF_CONDUCT.md | 2 +- .github/ISSUE_TEMPLATE/00-bug.yml | 94 ---------- .github/ISSUE_TEMPLATE/01-pkgsite.yml | 47 ----- .github/ISSUE_TEMPLATE/02-pkgsite-removal.yml | 42 ----- .github/ISSUE_TEMPLATE/03-gopls.yml | 56 ------ .github/ISSUE_TEMPLATE/04-vuln.yml | 52 ------ .github/ISSUE_TEMPLATE/10-proposal.yml | 15 -- .github/ISSUE_TEMPLATE/11-language-change.yml | 165 ------------------ .github/ISSUE_TEMPLATE/12-telemetry.yml | 68 -------- .github/ISSUE_TEMPLATE/config.yml | 5 - .github/PULL_REQUEST_TEMPLATE | 26 +-- 11 files changed, 2 insertions(+), 570 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/00-bug.yml delete mode 100644 .github/ISSUE_TEMPLATE/01-pkgsite.yml delete mode 100644 .github/ISSUE_TEMPLATE/02-pkgsite-removal.yml delete mode 100644 .github/ISSUE_TEMPLATE/03-gopls.yml delete mode 100644 .github/ISSUE_TEMPLATE/04-vuln.yml delete mode 100644 .github/ISSUE_TEMPLATE/10-proposal.yml delete mode 100644 .github/ISSUE_TEMPLATE/11-language-change.yml delete mode 100644 .github/ISSUE_TEMPLATE/12-telemetry.yml delete mode 100644 .github/ISSUE_TEMPLATE/config.yml 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. From 885e769d30219e70730c45acca38dc3efb6e650e Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 19 Jan 2022 15:36:52 +0100 Subject: [PATCH 06/21] cmd/api: ignore CF-specific API changes The "API check" test requires new APIs to be tracked in api/go1.X.txt or api/next/X.txt. Since Go 1.19 (commit b7041c7ad1c9), every line in these files also need a comment with the approval issue number. To reduce development friction, we disable the requirement of updating these files when the `-cf` tag is present in the VERSION file. --- src/cmd/api/api_test.go | 2 +- src/cmd/api/main_test.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) 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) From 10395434c5687926e63dcf5e77b54c9b4dc7bb68 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 1 Mar 2023 16:39:16 +0100 Subject: [PATCH 07/21] go/build: don't check dependencies of vendored circl library --- src/go/build/deps_test.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 7ce8d346b40..eeb5c88b2a0 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -499,6 +499,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 +735,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 +750,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 +770,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) From b5d791215ef7155c90aa5fc83a35e204db4086e5 Mon Sep 17 00:00:00 2001 From: Christopher Wood Date: Wed, 9 Dec 2020 17:50:40 -0800 Subject: [PATCH 08/21] crypto/tls: expose inter-handshake timing via CFEventHandlerContextKey Add basic support for handshake metrics: * Adds the ability to set a callback via the CFEventHandlerContextKey context value on the handshake context. It will be called at various points during the handshake to respond to various events. See #146. * Use this callback to expose client and server intra-handshake state machine durations, respectively. Each event records elapsed timestamps (durations) for relevant events during the course of a connection, such as reading and writing handshake messages of interest. This will be useful for recording intra-stack costs of TLS extensions such as ECH and KEMTLS. [pwu: Go 1.20.4: moved Config.CFEventHandler to context value] [pwu: Go 1.20.4: moved CFEvent code from tls_cf.go to cfevent.go] --- src/crypto/tls/cfevent.go | 98 +++++++++++++++++ src/crypto/tls/conn.go | 26 +++++ src/crypto/tls/handshake_client.go | 5 + src/crypto/tls/handshake_client_tls13.go | 21 ++++ src/crypto/tls/handshake_server.go | 1 + src/crypto/tls/handshake_server_tls13.go | 22 ++++ src/crypto/tls/metrics_test.go | 132 +++++++++++++++++++++++ 7 files changed, 305 insertions(+) create mode 100644 src/crypto/tls/cfevent.go create mode 100644 src/crypto/tls/metrics_test.go diff --git a/src/crypto/tls/cfevent.go b/src/crypto/tls/cfevent.go new file mode 100644 index 00000000000..ae23d10a802 --- /dev/null +++ b/src/crypto/tls/cfevent.go @@ -0,0 +1,98 @@ +// 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(), + } +} diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 0e4669866e5..99df8d636c8 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -120,6 +120,10 @@ 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) } // Access to net.Conn methods. @@ -1547,6 +1551,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() @@ -1664,3 +1672,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/handshake_client.go b/src/crypto/tls/handshake_client.go index 08a2d47974c..e8b250bfe11 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -175,6 +175,8 @@ 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 @@ -209,6 +211,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() @@ -257,6 +261,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { session: session, earlySecret: earlySecret, binderKey: binderKey, + hsTimings: hsTimings, } // In TLS 1.3, session tickets are delivered after the handshake. diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 2f59f6888c5..62c99744d12 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -34,6 +34,8 @@ type clientHandshakeStateTLS13 struct { transcript hash.Hash masterSecret []byte trafficSecret []byte // client_application_traffic_secret_0 + + hsTimings CFEventTLS13ClientHandshakeTimingInfo } // handshake requires hs.c, hs.hello, hs.serverHello, hs.ecdheKey, and, @@ -109,6 +111,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error { return err } + c.handleCFEvent(hs.hsTimings) c.isHandshakeComplete.Store(true) return nil @@ -314,6 +317,10 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { 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") @@ -479,6 +486,8 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error { } } + hs.hsTimings.ReadEncryptedExtensions = hs.hsTimings.elapsedTime() + return nil } @@ -525,6 +534,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 @@ -570,6 +581,8 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { return err } + hs.hsTimings.ReadCertificateVerify = hs.hsTimings.elapsedTime() + return nil } @@ -590,6 +603,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) @@ -651,6 +666,8 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { 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 @@ -688,6 +705,8 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { return err } + hs.hsTimings.WriteCertificateVerify = hs.hsTimings.elapsedTime() + return nil } @@ -702,6 +721,8 @@ 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 { diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 4e84aa9d8f0..163cbf582c0 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -49,6 +49,7 @@ func (c *Conn) serverHandshake(ctx context.Context) error { c: c, ctx: ctx, clientHello: clientHello, + hsTimings: createTLS13ServerHandshakeTimingInfo(c.config.Time), } return hs.handshake() } diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 21d798de37d..b3400e62aac 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -40,6 +40,8 @@ type serverHandshakeStateTLS13 struct { trafficSecret []byte // client_application_traffic_secret_0 transcript hash.Hash clientFinished []byte + + hsTimings CFEventTLS13ServerHandshakeTimingInfo } func (hs *serverHandshakeStateTLS13) handshake() error { @@ -82,6 +84,7 @@ func (hs *serverHandshakeStateTLS13) handshake() error { return err } + c.handleCFEvent(hs.hsTimings) c.isHandshakeComplete.Store(true) return nil @@ -261,6 +264,9 @@ GroupSelection: } c.serverName = hs.clientHello.serverName + + hs.hsTimings.ProcessClientHello = hs.hsTimings.elapsedTime() + return nil } @@ -604,6 +610,8 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { return err } + hs.hsTimings.WriteServerHello = hs.hsTimings.elapsedTime() + if err := hs.sendDummyChangeCipherSpec(); err != nil { return err } @@ -657,6 +665,8 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { return err } + hs.hsTimings.WriteEncryptedExtensions = hs.hsTimings.elapsedTime() + return nil } @@ -697,6 +707,8 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { return err } + hs.hsTimings.WriteCertificate = hs.hsTimings.elapsedTime() + certVerifyMsg := new(certificateVerifyMsg) certVerifyMsg.hasSignatureAlgorithm = true certVerifyMsg.signatureAlgorithm = hs.sigAlg @@ -728,6 +740,8 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { return err } + hs.hsTimings.WriteCertificateVerify = hs.hsTimings.elapsedTime() + return nil } @@ -742,6 +756,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, @@ -923,6 +939,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 @@ -963,6 +981,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 +1012,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/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") + } +} From 32f83b78a32efae4f80a15ce19e9d333c13c84ff Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Thu, 8 Sep 2022 12:25:53 +0200 Subject: [PATCH 09/21] crypto/tls: Add hybrid post-quantum key agreements This patch adds: - X25519Kyber768Draft00, this is the de facto standard for early deployment, see https://mailarchive.ietf.org/arch/msg/tls/HAWpNpgptl--UZNSYuvsjB-Pc2k/ https://datatracker.ietf.org/doc/draft-tls-westerbaan-xyber768d00/02/ - X25519Kyber768Draft00Old, which is the same as the previous, but under an old identifiers. - X25519Kyber512Draft00. This should only be used for testing, whether the smaller shares are advantageous. - P256Kyber768Draft00. Uses a non-standard identifier. Should not be used. Adds CFEvents to detect `HelloRetryRequest`s and to signal which key agreement was used. Co-authored-by: Christopher Wood Co-authored-by: Peter Wu --- src/crypto/tls/cfevent.go | 21 + src/crypto/tls/cfkem.go | 101 + src/crypto/tls/cfkem_test.go | 106 + src/crypto/tls/handshake_client.go | 65 +- src/crypto/tls/handshake_client_tls13.go | 91 +- src/crypto/tls/handshake_server.go | 9 + src/crypto/tls/handshake_server_tls13.go | 41 +- src/crypto/tls/key_agreement.go | 2 +- src/go.mod | 1 + src/go.sum | 2 + .../github.com/cloudflare/circl/LICENSE | 57 + .../cloudflare/circl/dh/x25519/curve.go | 96 + .../cloudflare/circl/dh/x25519/curve_amd64.go | 30 + .../cloudflare/circl/dh/x25519/curve_amd64.h | 111 + .../cloudflare/circl/dh/x25519/curve_amd64.s | 156 ++ .../circl/dh/x25519/curve_generic.go | 85 + .../cloudflare/circl/dh/x25519/curve_noasm.go | 11 + .../cloudflare/circl/dh/x25519/doc.go | 19 + .../cloudflare/circl/dh/x25519/key.go | 47 + .../cloudflare/circl/dh/x25519/table.go | 268 ++ .../cloudflare/circl/dh/x448/curve.go | 104 + .../cloudflare/circl/dh/x448/curve_amd64.go | 30 + .../cloudflare/circl/dh/x448/curve_amd64.h | 111 + .../cloudflare/circl/dh/x448/curve_amd64.s | 193 ++ .../cloudflare/circl/dh/x448/curve_generic.go | 100 + .../cloudflare/circl/dh/x448/curve_noasm.go | 11 + .../cloudflare/circl/dh/x448/doc.go | 19 + .../cloudflare/circl/dh/x448/key.go | 46 + .../cloudflare/circl/dh/x448/table.go | 460 ++++ .../cloudflare/circl/internal/conv/conv.go | 140 + .../cloudflare/circl/internal/sha3/doc.go | 62 + .../cloudflare/circl/internal/sha3/hashes.go | 69 + .../cloudflare/circl/internal/sha3/keccakf.go | 391 +++ .../cloudflare/circl/internal/sha3/rc.go | 29 + .../cloudflare/circl/internal/sha3/sha3.go | 200 ++ .../circl/internal/sha3/sha3_s390x.s | 33 + .../cloudflare/circl/internal/sha3/shake.go | 119 + .../cloudflare/circl/internal/sha3/xor.go | 15 + .../circl/internal/sha3/xor_generic.go | 33 + .../circl/internal/sha3/xor_unaligned.go | 61 + .../cloudflare/circl/kem/hybrid/ckem.go | 207 ++ .../cloudflare/circl/kem/hybrid/hybrid.go | 344 +++ .../cloudflare/circl/kem/hybrid/xkem.go | 208 ++ .../github.com/cloudflare/circl/kem/kem.go | 118 + .../circl/kem/kyber/kyber1024/kyber.go | 404 +++ .../circl/kem/kyber/kyber512/kyber.go | 404 +++ .../circl/kem/kyber/kyber768/kyber.go | 404 +++ .../cloudflare/circl/math/fp25519/fp.go | 205 ++ .../cloudflare/circl/math/fp25519/fp_amd64.go | 45 + .../cloudflare/circl/math/fp25519/fp_amd64.h | 351 +++ .../cloudflare/circl/math/fp25519/fp_amd64.s | 111 + .../circl/math/fp25519/fp_generic.go | 317 +++ .../cloudflare/circl/math/fp25519/fp_noasm.go | 13 + .../cloudflare/circl/math/fp448/fp.go | 164 ++ .../cloudflare/circl/math/fp448/fp_amd64.go | 43 + .../cloudflare/circl/math/fp448/fp_amd64.h | 591 +++++ .../cloudflare/circl/math/fp448/fp_amd64.s | 74 + .../cloudflare/circl/math/fp448/fp_generic.go | 339 +++ .../cloudflare/circl/math/fp448/fp_noasm.go | 12 + .../cloudflare/circl/math/fp448/fuzzer.go | 75 + .../circl/pke/kyber/internal/common/amd64.go | 302 +++ .../circl/pke/kyber/internal/common/amd64.s | 2354 +++++++++++++++++ .../circl/pke/kyber/internal/common/field.go | 74 + .../pke/kyber/internal/common/generic.go | 77 + .../circl/pke/kyber/internal/common/ntt.go | 193 ++ .../circl/pke/kyber/internal/common/params.go | 22 + .../kyber/internal/common/params/params.go | 21 + .../circl/pke/kyber/internal/common/poly.go | 332 +++ .../circl/pke/kyber/internal/common/sample.go | 236 ++ .../pke/kyber/internal/common/stubs_amd64.go | 32 + .../pke/kyber/kyber1024/internal/cpapke.go | 176 ++ .../circl/pke/kyber/kyber1024/internal/mat.go | 85 + .../pke/kyber/kyber1024/internal/params.go | 21 + .../circl/pke/kyber/kyber1024/internal/vec.go | 125 + .../circl/pke/kyber/kyber1024/kyber.go | 145 + .../pke/kyber/kyber512/internal/cpapke.go | 174 ++ .../circl/pke/kyber/kyber512/internal/mat.go | 83 + .../pke/kyber/kyber512/internal/params.go | 21 + .../circl/pke/kyber/kyber512/internal/vec.go | 123 + .../circl/pke/kyber/kyber512/kyber.go | 145 + .../pke/kyber/kyber768/internal/cpapke.go | 176 ++ .../circl/pke/kyber/kyber768/internal/mat.go | 85 + .../pke/kyber/kyber768/internal/params.go | 21 + .../circl/pke/kyber/kyber768/internal/vec.go | 125 + .../circl/pke/kyber/kyber768/kyber.go | 145 + .../circl/simd/keccakf1600/f1600x.go | 163 ++ .../circl/simd/keccakf1600/f1600x2_arm64.go | 13 + .../circl/simd/keccakf1600/f1600x2_arm64.s | 136 + .../circl/simd/keccakf1600/f1600x4_amd64.go | 7 + .../circl/simd/keccakf1600/f1600x4_amd64.s | 899 +++++++ .../simd/keccakf1600/f1600x4stubs_amd64.go | 8 + .../circl/simd/keccakf1600/fallback.go | 8 + .../cloudflare/circl/xof/k12/k12.go | 400 +++ .../github.com/cloudflare/circl/xof/xof.go | 85 + .../golang.org/x/crypto/blake2b/blake2b.go | 291 ++ .../x/crypto/blake2b/blake2bAVX2_amd64.go | 37 + .../x/crypto/blake2b/blake2bAVX2_amd64.s | 744 ++++++ .../x/crypto/blake2b/blake2b_amd64.s | 278 ++ .../x/crypto/blake2b/blake2b_generic.go | 182 ++ .../x/crypto/blake2b/blake2b_ref.go | 11 + .../golang.org/x/crypto/blake2b/blake2x.go | 177 ++ .../golang.org/x/crypto/blake2b/register.go | 30 + .../golang.org/x/crypto/blake2s/blake2s.go | 246 ++ .../x/crypto/blake2s/blake2s_386.go | 32 + .../golang.org/x/crypto/blake2s/blake2s_386.s | 429 +++ .../x/crypto/blake2s/blake2s_amd64.go | 37 + .../x/crypto/blake2s/blake2s_amd64.s | 432 +++ .../x/crypto/blake2s/blake2s_generic.go | 178 ++ .../x/crypto/blake2s/blake2s_ref.go | 17 + .../golang.org/x/crypto/blake2s/blake2x.go | 178 ++ .../golang.org/x/crypto/blake2s/register.go | 21 + src/vendor/modules.txt | 26 + 112 files changed, 18270 insertions(+), 62 deletions(-) create mode 100644 src/crypto/tls/cfkem.go create mode 100644 src/crypto/tls/cfkem_test.go create mode 100644 src/vendor/github.com/cloudflare/circl/LICENSE create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/curve.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/doc.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/key.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x25519/table.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/curve.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/doc.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/key.go create mode 100644 src/vendor/github.com/cloudflare/circl/dh/x448/table.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/conv/conv.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/doc.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/hashes.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/rc.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/sha3.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/shake.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/xor.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go create mode 100644 src/vendor/github.com/cloudflare/circl/kem/hybrid/ckem.go create mode 100644 src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go create mode 100644 src/vendor/github.com/cloudflare/circl/kem/hybrid/xkem.go create mode 100644 src/vendor/github.com/cloudflare/circl/kem/kem.go create mode 100644 src/vendor/github.com/cloudflare/circl/kem/kyber/kyber1024/kyber.go create mode 100644 src/vendor/github.com/cloudflare/circl/kem/kyber/kyber512/kyber.go create mode 100644 src/vendor/github.com/cloudflare/circl/kem/kyber/kyber768/kyber.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp25519/fp.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp25519/fp_generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp448/fp.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/field.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/ntt.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/params/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/poly.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/sample.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/stubs_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/cpapke.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/mat.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/vec.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/kyber.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/cpapke.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/mat.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/vec.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/kyber.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/cpapke.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/mat.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/vec.go create mode 100644 src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/kyber.go create mode 100644 src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x.go create mode 100644 src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.go create mode 100644 src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.s create mode 100644 src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4stubs_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go create mode 100644 src/vendor/github.com/cloudflare/circl/xof/k12/k12.go create mode 100644 src/vendor/github.com/cloudflare/circl/xof/xof.go create mode 100644 src/vendor/golang.org/x/crypto/blake2b/blake2b.go create mode 100644 src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go create mode 100644 src/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s create mode 100644 src/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s create mode 100644 src/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go create mode 100644 src/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go create mode 100644 src/vendor/golang.org/x/crypto/blake2b/blake2x.go create mode 100644 src/vendor/golang.org/x/crypto/blake2b/register.go create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2s.go create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2s_386.go create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2s_386.s create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go create mode 100644 src/vendor/golang.org/x/crypto/blake2s/blake2x.go create mode 100644 src/vendor/golang.org/x/crypto/blake2s/register.go diff --git a/src/crypto/tls/cfevent.go b/src/crypto/tls/cfevent.go index ae23d10a802..a2be30f516c 100644 --- a/src/crypto/tls/cfevent.go +++ b/src/crypto/tls/cfevent.go @@ -96,3 +96,24 @@ func createTLS13ServerHandshakeTimingInfo(timerFunc func() time.Time) CFEventTLS start: timer(), } } + +// 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/cfkem.go b/src/crypto/tls/cfkem.go new file mode 100644 index 00000000000..8d440e4c3c5 --- /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" + + "crypto/ecdh" + + "github.com/cloudflare/circl/kem" + "github.com/cloudflare/circl/kem/hybrid" +) + +// Either *ecdh.PrivateKey or *kemPrivateKey +type clientKeySharePrivate interface{} + +type kemPrivateKey struct { + secretKey kem.PrivateKey + curveID CurveID +} + +var ( + X25519Kyber512Draft00 = CurveID(0xfe30) + X25519Kyber768Draft00 = CurveID(0x6399) + X25519Kyber768Draft00Old = CurveID(0xfe31) + P256Kyber768Draft00 = CurveID(0xfe32) + invalidCurveID = CurveID(0) +) + +// Extract CurveID from clientKeySharePrivate +func clientKeySharePrivateCurveID(ks clientKeySharePrivate) CurveID { + switch v := ks.(type) { + case *kemPrivateKey: + return v.curveID + case *ecdh.PrivateKey: + ret, ok := curveIDForCurve(v.Curve()) + if !ok { + panic("cfkem: internal error: unknown curve") + } + return ret + default: + panic("cfkem: internal error: unknown clientKeySharePrivate") + } +} + +// 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() + } + 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..85da45ede8c --- /dev/null +++ b/src/crypto/tls/cfkem_test.go @@ -0,0 +1,106 @@ +// 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, + } { + 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) + } +} diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index e8b250bfe11..2346facb2c4 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" @@ -39,7 +38,7 @@ type clientHandshakeState struct { var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme -func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { +func (c *Conn) makeClientHello() (*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") @@ -133,7 +132,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms } - var key *ecdh.PrivateKey + var secret clientKeySharePrivate if hello.supportedVersions[0] == VersionTLS13 { // Reset the list of ciphers when the client only supports TLS 1.3. if len(hello.supportedVersions) == 1 { @@ -146,14 +145,30 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { } curveID := config.curvePreferences()[0] - 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 + 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) + } + hello.keyShares = []keyShare{{group: curveID, data: packedPk}} + secret = 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 + } + hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} + secret = key } - hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} } if c.quic != nil { @@ -167,7 +182,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) { @@ -253,15 +268,15 @@ 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, - hsTimings: hsTimings, + c: c, + ctx: ctx, + serverHello: serverHello, + hello: hello, + keySharePrivate: ecdheKey, + session: session, + earlySecret: earlySecret, + binderKey: binderKey, + hsTimings: hsTimings, } // In TLS 1.3, session tickets are delivered after the handshake. @@ -608,6 +623,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 diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 62c99744d12..d54999fd342 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -12,20 +12,22 @@ import ( "crypto/hmac" "crypto/rsa" "errors" + "fmt" "hash" "time" ) type clientHandshakeStateTLS13 struct { - c *Conn - ctx context.Context - serverHello *serverHelloMsg - hello *clientHelloMsg - ecdheKey *ecdh.PrivateKey + c *Conn + ctx context.Context + serverHello *serverHelloMsg + hello *clientHelloMsg + keySharePrivate clientKeySharePrivate - session *SessionState - earlySecret []byte - binderKey []byte + session *SessionState + earlySecret []byte + binderKey []byte + selectedGroup CurveID certReq *certificateRequestMsgTLS13 usingPSK bool @@ -55,7 +57,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 || len(hs.hello.keyShares) != 1 { return c.sendAlert(alertInternalError) } @@ -192,6 +194,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. @@ -235,21 +239,38 @@ 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 clientKeySharePrivateCurveID(hs.keySharePrivate) == curveID { 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 = sk + hs.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 = key + hs.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 @@ -340,11 +361,15 @@ 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 hs.serverHello.serverShare.group != clientKeySharePrivateCurveID(hs.keySharePrivate) { 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 } @@ -379,15 +404,25 @@ 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 + if key, ok := hs.keySharePrivate.(*ecdh.PrivateKey); ok { + peerKey, err := key.Curve().NewPublicKey(hs.serverHello.serverShare.data) + if err == nil { + sharedKey, _ = key.ECDH(peerKey) + } + } else if key, ok := hs.keySharePrivate.(*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 diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 163cbf582c0..1da1ae9a02a 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -675,6 +675,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, diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index b3400e62aac..10f699ce742 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 @@ -214,23 +216,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") } @@ -264,6 +274,9 @@ GroupSelection: } c.serverName = hs.clientHello.serverName + c.handleCFEvent(CFEventTLSNegotiatedNamedKEX{ + KEX: selectedGroup, + }) hs.hsTimings.ProcessClientHello = hs.hsTimings.elapsedTime() @@ -483,6 +496,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 { diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go index 2c8c5b8d771..102c1a3e51d 100644 --- a/src/crypto/tls/key_agreement.go +++ b/src/crypto/tls/key_agreement.go @@ -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/go.mod b/src/go.mod index 737d78da5d9..c82ed2bf9f0 100644 --- a/src/go.mod +++ b/src/go.mod @@ -3,6 +3,7 @@ module std go 1.22 require ( + github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7 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..a373acaa66d 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,3 +1,5 @@ +github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7 h1:nRedc5Iqg+cBRSKkA3c7+IUFgK9qdw87kz/McP3HnLs= +github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7/go.mod h1:uAwUTm6m3uQF5fuJKR6LvFqgxn2wyID+kF6KJAUcZl8= 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/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..b7723185b61 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s @@ -0,0 +1,156 @@ +// +build amd64 + +#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..810aa9e6481 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s @@ -0,0 +1,193 @@ +// +build amd64 + +#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/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..be8251c7f74 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go @@ -0,0 +1,344 @@ +// Package hybrid defines several hybrid classical/quantum KEMs. +// +// KEMs are combined by simple concatenation of shared secrets, cipher texts, +// public keys, etc, see +// +// https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/ +// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf +// +// Note that this is only fine if the shared secret is used in its entirety +// in a next step, such as being hashed or used as key. +// +// 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" +) + +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 } + +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(), +} + +// 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..6ab0aa3bad3 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kem.go @@ -0,0 +1,118 @@ +// Package kem provides a unified interface for KEM schemes. +// +// A register of schemes is available in the package +// +// github.com/cloudflare/circl/kem/schemes +package kem + +import ( + "encoding" + "errors" +) + +// A KEM public key +type PublicKey interface { + // Returns the scheme for this public key + Scheme() Scheme + + encoding.BinaryMarshaler + Equal(PublicKey) bool +} + +// A KEM private key +type PrivateKey interface { + // Returns the scheme for this private key + Scheme() Scheme + + encoding.BinaryMarshaler + Equal(PrivateKey) bool + Public() PublicKey +} + +// A Scheme represents a specific instance of a KEM. +type Scheme interface { + // Name of the scheme + Name() string + + // GenerateKeyPair creates a new key pair. + GenerateKeyPair() (PublicKey, PrivateKey, error) + + // Encapsulate generates a shared key ss for the public key and + // encapsulates it into a ciphertext ct. + Encapsulate(pk PublicKey) (ct, ss []byte, err error) + + // Returns the shared key encapsulated in ciphertext ct for the + // private key sk. + Decapsulate(sk PrivateKey, ct []byte) ([]byte, error) + + // Unmarshals a PublicKey from the provided buffer. + UnmarshalBinaryPublicKey([]byte) (PublicKey, error) + + // Unmarshals a PrivateKey from the provided buffer. + UnmarshalBinaryPrivateKey([]byte) (PrivateKey, error) + + // Size of encapsulated keys. + CiphertextSize() int + + // Size of established shared keys. + SharedKeySize() int + + // Size of packed private keys. + PrivateKeySize() int + + // Size of packed public keys. + PublicKeySize() int + + // DeriveKeyPair 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") + + // 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..428584528ea --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber1024/kyber.go @@ -0,0 +1,404 @@ +// 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") + } + + // m = H(seed) + var m [32]byte + 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[:SharedKeySize]) +} + +// 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) { + if len(buf) != PublicKeySize { + return nil, kem.ErrPubKeySize + } + var ret PublicKey + 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..c250d78c673 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber512/kyber.go @@ -0,0 +1,404 @@ +// 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") + } + + // m = H(seed) + var m [32]byte + 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[:SharedKeySize]) +} + +// 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) { + if len(buf) != PublicKeySize { + return nil, kem.ErrPubKeySize + } + var ret PublicKey + 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..832d9b371ad --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber768/kyber.go @@ -0,0 +1,404 @@ +// 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") + } + + // m = H(seed) + var m [32]byte + 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[:SharedKeySize]) +} + +// 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) { + if len(buf) != PublicKeySize { + return nil, kem.ErrPubKeySize + } + var ret PublicKey + 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/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..435addf5e6c --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s @@ -0,0 +1,74 @@ +// +build amd64 + +#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/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..6ffd94b1fc2 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/amd64.go @@ -0,0 +1,302 @@ +//go:build amd64 +// +build amd64 + +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..f721482fb9d --- /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 + +#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..2b742b95a38 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/internal/common/generic.go @@ -0,0 +1,77 @@ +//go:build !amd64 +// +build !amd64 + +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..cf14cff912d --- /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 + +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..01ef88b2f60 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/internal/cpapke.go @@ -0,0 +1,176 @@ +// Code generated from kyber512/internal/cpapke.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/internal/sha3" + "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. +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..fb5911facd4 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/kyber.go @@ -0,0 +1,145 @@ +// Code generated from modePkg.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/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. +// +// 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) +} + +// 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 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..80ab2501c2f --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/internal/cpapke.go @@ -0,0 +1,174 @@ +package internal + +import ( + "github.com/cloudflare/circl/internal/sha3" + "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. +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..ea9248487e1 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/kyber.go @@ -0,0 +1,145 @@ +// Code generated from modePkg.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/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. +// +// 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) +} + +// 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 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..01ef88b2f60 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/internal/cpapke.go @@ -0,0 +1,176 @@ +// Code generated from kyber512/internal/cpapke.go by gen.go + +package internal + +import ( + "github.com/cloudflare/circl/internal/sha3" + "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. +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..4cecbb1b871 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/kyber.go @@ -0,0 +1,145 @@ +// Code generated from modePkg.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/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. +// +// 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) +} + +// 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 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/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..44f05436a84 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.go @@ -0,0 +1,13 @@ +//go:build arm64 && go1.16 +// +build arm64,go1.16 + +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..68dd0e37bc0 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.s @@ -0,0 +1,136 @@ +// +build arm64,go1.16 + +// 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..669ce65f4db --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.go @@ -0,0 +1,7 @@ +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..314a8555330 --- /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 + +#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..de289441ef5 --- /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 + +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..5287c1f5d7b --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go @@ -0,0 +1,8 @@ +//go:build (!amd64 && !arm64) || (arm64 && !go1.16) +// +build !amd64,!arm64 arm64,!go1.16 + +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/modules.txt b/src/vendor/modules.txt index 9a234e59b10..7bd5b757067 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,5 +1,31 @@ +# github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7 +## explicit; go 1.19 +github.com/cloudflare/circl/dh/x25519 +github.com/cloudflare/circl/dh/x448 +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/math/fp25519 +github.com/cloudflare/circl/math/fp448 +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/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 From f2bfd08e62482e1385e921ef4b403c41c462f82d Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 19 Aug 2020 11:38:04 +0200 Subject: [PATCH 10/21] crypto: add support for CIRCL signature schemes To avoid having to regenerate all testdata files, add an option to control whether PQ signature algorithms are advertised. Tests were added for the client side. Since Go 1.19, FIPS-only mode must remain disabled to enable PQ sigalgs. [pwu: Go 1.17: moved parsePublicKey changes from x509/x509.go to x509/parser.go] [pwu: Go 1.22.5: add eddilithium2 support, fix eddilithium3, by Bas in #176] Co-authored-by: Christopher Patton Co-authored-by: Peter Wu --- src/crypto/tls/auth.go | 40 +- src/crypto/tls/auth_test.go | 4 +- src/crypto/tls/common.go | 8 + src/crypto/tls/generate_cert.go | 12 + src/crypto/tls/handshake_client.go | 6 +- src/crypto/tls/handshake_client_tls13.go | 2 +- src/crypto/tls/handshake_server.go | 6 +- src/crypto/tls/handshake_server_tls13.go | 4 +- src/crypto/tls/key_agreement.go | 2 +- src/crypto/tls/prf.go | 4 +- src/crypto/tls/tls.go | 15 +- src/crypto/tls/tls_cf.go | 68 + src/crypto/tls/tls_cf_circl_test.go | 134 + src/crypto/tls/tls_test.go | 2 + src/crypto/x509/parser.go | 15 + src/crypto/x509/pkcs8.go | 36 +- src/crypto/x509/x509.go | 68 +- src/crypto/x509/x509_cf.go | 74 + src/crypto/x509/x509_test.go | 19 + .../circl/ecc/goldilocks/constants.go | 71 + .../cloudflare/circl/ecc/goldilocks/curve.go | 80 + .../circl/ecc/goldilocks/isogeny.go | 52 + .../cloudflare/circl/ecc/goldilocks/point.go | 171 + .../cloudflare/circl/ecc/goldilocks/scalar.go | 203 + .../cloudflare/circl/ecc/goldilocks/twist.go | 138 + .../circl/ecc/goldilocks/twistPoint.go | 135 + .../circl/ecc/goldilocks/twistTables.go | 216 + .../circl/ecc/goldilocks/twist_basemult.go | 62 + .../cloudflare/circl/math/mlsbset/mlsbset.go | 122 + .../cloudflare/circl/math/mlsbset/power.go | 64 + .../cloudflare/circl/math/primes.go | 34 + .../github.com/cloudflare/circl/math/wnaf.go | 84 + .../github.com/cloudflare/circl/pki/pki.go | 182 + .../sign/dilithium/internal/common/aes.go | 46 + .../sign/dilithium/internal/common/amd64.go | 154 + .../sign/dilithium/internal/common/amd64.s | 8407 +++++++++++++++++ .../sign/dilithium/internal/common/field.go | 52 + .../sign/dilithium/internal/common/generic.go | 81 + .../sign/dilithium/internal/common/ntt.go | 217 + .../sign/dilithium/internal/common/pack.go | 160 + .../sign/dilithium/internal/common/params.go | 18 + .../internal/common/params/params.go | 25 + .../sign/dilithium/internal/common/poly.go | 101 + .../dilithium/internal/common/stubs_amd64.go | 35 + .../circl/sign/dilithium/mode2/dilithium.go | 181 + .../dilithium/mode2/internal/dilithium.go | 477 + .../sign/dilithium/mode2/internal/mat.go | 59 + .../sign/dilithium/mode2/internal/pack.go | 270 + .../sign/dilithium/mode2/internal/params.go | 16 + .../sign/dilithium/mode2/internal/rounding.go | 142 + .../sign/dilithium/mode2/internal/sample.go | 370 + .../sign/dilithium/mode2/internal/vec.go | 281 + .../circl/sign/dilithium/mode3/dilithium.go | 181 + .../dilithium/mode3/internal/dilithium.go | 475 + .../sign/dilithium/mode3/internal/mat.go | 57 + .../sign/dilithium/mode3/internal/pack.go | 268 + .../sign/dilithium/mode3/internal/params.go | 16 + .../sign/dilithium/mode3/internal/rounding.go | 140 + .../sign/dilithium/mode3/internal/sample.go | 368 + .../sign/dilithium/mode3/internal/vec.go | 279 + .../cloudflare/circl/sign/ed25519/ed25519.go | 453 + .../cloudflare/circl/sign/ed25519/modular.go | 175 + .../cloudflare/circl/sign/ed25519/mult.go | 180 + .../cloudflare/circl/sign/ed25519/point.go | 195 + .../cloudflare/circl/sign/ed25519/pubkey.go | 9 + .../circl/sign/ed25519/pubkey112.go | 7 + .../cloudflare/circl/sign/ed25519/signapi.go | 87 + .../cloudflare/circl/sign/ed25519/tables.go | 213 + .../cloudflare/circl/sign/ed448/ed448.go | 411 + .../cloudflare/circl/sign/ed448/signapi.go | 87 + .../circl/sign/eddilithium2/eddilithium.go | 239 + .../circl/sign/eddilithium2/signapi.go | 93 + .../circl/sign/eddilithium3/eddilithium.go | 234 + .../circl/sign/eddilithium3/signapi.go | 93 + .../cloudflare/circl/sign/schemes/schemes.go | 46 + .../github.com/cloudflare/circl/sign/sign.go | 110 + src/vendor/modules.txt | 16 + 77 files changed, 17631 insertions(+), 26 deletions(-) create mode 100644 src/crypto/tls/tls_cf.go create mode 100644 src/crypto/tls/tls_cf_circl_test.go create mode 100644 src/crypto/x509/x509_cf.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/mlsbset/power.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/primes.go create mode 100644 src/vendor/github.com/cloudflare/circl/math/wnaf.go create mode 100644 src/vendor/github.com/cloudflare/circl/pki/pki.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/aes.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/field.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/ntt.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/pack.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/params/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/poly.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/stubs_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/dilithium.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/dilithium.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/mat.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/pack.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/rounding.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/sample.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode2/internal/vec.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/dilithium.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/dilithium.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/mat.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/pack.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/params.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/rounding.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/sample.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/dilithium/mode3/internal/vec.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/modular.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/mult.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/point.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed25519/tables.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed448/ed448.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/ed448/signapi.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/eddilithium2/eddilithium.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/eddilithium2/signapi.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/eddilithium3/signapi.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/schemes/schemes.go create mode 100644 src/vendor/github.com/cloudflare/circl/sign/sign.go diff --git a/src/crypto/tls/auth.go b/src/crypto/tls/auth.go index 7c5675c6d93..289c1eef129 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 } 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/common.go b/src/crypto/tls/common.go index 849e8b0a209..d2ad884e338 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -187,6 +187,8 @@ const ( signatureRSAPSS signatureECDSA signatureEd25519 + signatureEdDilithium2 + signatureEdDilithium3 ) // directSigning is a standard Hash value that signals that no pre-hashing @@ -756,6 +758,11 @@ type Config struct { // 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 @@ -858,6 +865,7 @@ func (c *Config) Clone() *Config { MinVersion: c.MinVersion, MaxVersion: c.MaxVersion, CurvePreferences: c.CurvePreferences, + PQSignatureSchemesEnabled: c.PQSignatureSchemesEnabled, DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, Renegotiation: c.Renegotiation, KeyLogWriter: c.KeyLogWriter, diff --git a/src/crypto/tls/generate_cert.go b/src/crypto/tls/generate_cert.go index cd4bfc513f0..df97193c6d3 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 ( @@ -35,6 +38,7 @@ var ( 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 +49,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 +69,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) } diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 2346facb2c4..d7ee2e9f94f 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -22,6 +22,8 @@ import ( "strconv" "strings" "time" + + circlSign "github.com/cloudflare/circl/sign" ) type clientHandshakeState struct { @@ -126,7 +128,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, clientKeySharePrivate, error) } if hello.vers >= VersionTLS12 { - hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + hello.supportedSignatureAlgorithms = config.supportedSignatureAlgorithms() } if testingOnlyForceClientHelloSignatureAlgorithms != nil { hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms @@ -1032,7 +1034,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) diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index d54999fd342..06287255409 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -593,7 +593,7 @@ 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") } diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 1da1ae9a02a..d974f294896 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. @@ -601,7 +603,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 @@ -934,7 +936,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) diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 10f699ce742..4a2211af7cc 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -702,7 +702,7 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { certReq := new(certificateRequestMsgTLS13) certReq.ocspStapling = true certReq.scts = true - certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() + certReq.supportedSignatureAlgorithms = c.config.supportedSignatureAlgorithms() if c.config.ClientCAs != nil { certReq.certificateAuthorities = c.config.ClientCAs.Subjects() } @@ -972,7 +972,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") } diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go index 102c1a3e51d..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...) 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..3c6fe5aec01 100644 --- a/src/crypto/tls/tls.go +++ b/src/crypto/tls/tls.go @@ -25,6 +25,8 @@ import ( "net" "os" "strings" + + circlSign "github.com/cloudflare/circl/sign" ) // Server returns a new TLS server side connection @@ -326,6 +328,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 +355,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_test.go b/src/crypto/tls/tls_test.go index 42a0272f005..a70e65c3437 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -863,6 +863,8 @@ func TestCloneNonFuncFields(t *testing.T) { f.Set(reflect.ValueOf([]uint16{1, 2})) case "CurvePreferences": f.Set(reflect.ValueOf([]CurveID{CurveP256})) + case "PQSignatureSchemesEnabled": + f.Set(reflect.ValueOf(true)) case "Renegotiation": f.Set(reflect.ValueOf(RenegotiateOnceAsClient)) case "mutex", "autoSessionTicketKeys", "sessionTicketKeys": diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go index 812b0d2d285..b5bc3807697 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") } } 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/x509.go b/src/crypto/x509/x509.go index 15b3b9ed35e..9b31658e36c 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 @@ -896,7 +918,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 +967,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 } @@ -1469,9 +1504,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 +1537,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 } 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..ee9aba5cc2e 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") 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/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/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..a58e4bf46a9 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.go @@ -0,0 +1,154 @@ +//go:build amd64 +// +build amd64 + +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..f10545246ab --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/generic.go @@ -0,0 +1,81 @@ +//go:build !amd64 +// +build !amd64 + +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..97451507f8d --- /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 + +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..d1c8d629d64 --- /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 eddilithium4.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 eddilithium4.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("eddilithium4: 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/modules.txt b/src/vendor/modules.txt index 7bd5b757067..529b8a6a973 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -2,6 +2,7 @@ ## explicit; go 1.19 github.com/cloudflare/circl/dh/x25519 github.com/cloudflare/circl/dh/x448 +github.com/cloudflare/circl/ecc/goldilocks github.com/cloudflare/circl/internal/conv github.com/cloudflare/circl/internal/sha3 github.com/cloudflare/circl/kem @@ -9,8 +10,10 @@ 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/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 @@ -19,6 +22,19 @@ 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 From 1169950a0dd0afa57f7c2e9aafa0f1d1a9c48b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sof=C3=ADa=20Celi?= Date: Wed, 19 Aug 2020 08:39:59 -0500 Subject: [PATCH 11/21] crypto/tls: implement draft-ietf-tls-subcerts-10 * Define API for delegated credentials so they are fetched using the same mechanisms used to fetch certificates * Allow the usage of other keyUsage when checking for the DC extension. * Add tool for generating delegated credentials. Co-authored-by: Jonathan Hoyland --- src/crypto/tls/auth.go | 22 + src/crypto/tls/common.go | 66 ++ src/crypto/tls/conn.go | 6 + src/crypto/tls/delegated_credentials.go | 548 +++++++++++++++ src/crypto/tls/delegated_credentials_test.go | 652 ++++++++++++++++++ src/crypto/tls/generate_cert.go | 10 + .../tls/generate_delegated_credential.go | 126 ++++ src/crypto/tls/handshake_client.go | 6 + src/crypto/tls/handshake_client_tls13.go | 136 +++- src/crypto/tls/handshake_messages.go | 87 ++- src/crypto/tls/handshake_messages_test.go | 12 + src/crypto/tls/handshake_server.go | 22 +- src/crypto/tls/handshake_server_tls13.go | 116 +++- src/crypto/tls/tls.go | 14 + src/crypto/tls/tls_test.go | 2 + src/crypto/x509/parser.go | 9 + src/crypto/x509/verify_test.go | 15 +- src/crypto/x509/x509.go | 15 + src/crypto/x509/x509_test.go | 42 ++ 19 files changed, 1872 insertions(+), 34 deletions(-) create mode 100644 src/crypto/tls/delegated_credentials.go create mode 100644 src/crypto/tls/delegated_credentials_test.go create mode 100644 src/crypto/tls/generate_delegated_credential.go diff --git a/src/crypto/tls/auth.go b/src/crypto/tls/auth.go index 289c1eef129..604e4315409 100644 --- a/src/crypto/tls/auth.go +++ b/src/crypto/tls/auth.go @@ -260,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/common.go b/src/crypto/tls/common.go index d2ad884e338..a22543b7c03 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 @@ -215,6 +216,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. @@ -286,6 +297,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 @@ -431,6 +447,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). @@ -445,6 +468,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. @@ -475,10 +502,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 @@ -781,6 +819,13 @@ type Config struct { // used for debugging. KeyLogWriter io.Writer + // 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 @@ -869,6 +914,7 @@ func (c *Config) Clone() *Config { DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, Renegotiation: c.Renegotiation, KeyLogWriter: c.KeyLogWriter, + SupportDelegatedCredential: c.SupportDelegatedCredential, sessionTicketKeys: c.sessionTicketKeys, autoSessionTicketKeys: c.autoSessionTicketKeys, } @@ -1416,6 +1462,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 @@ -1433,6 +1489,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 99df8d636c8..e14b3f8a3c2 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -58,6 +58,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 @@ -1621,6 +1624,9 @@ 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 if (!c.didResume || c.extMasterSecret) && c.vers != VersionTLS13 { 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/generate_cert.go b/src/crypto/tls/generate_cert.go index df97193c6d3..360ce8fa80a 100644 --- a/src/crypto/tls/generate_cert.go +++ b/src/crypto/tls/generate_cert.go @@ -35,6 +35,7 @@ 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") @@ -144,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 d7ee2e9f94f..f1e816b3eb6 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -171,6 +171,9 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, clientKeySharePrivate, error) hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} secret = key } + + hello.delegatedCredentialSupported = config.SupportDelegatedCredential + hello.supportedSignatureAlgorithmsDC = supportedSignatureAlgorithmsDC } if c.quic != nil { @@ -1068,6 +1071,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 06287255409..6a7c526504a 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -40,6 +40,49 @@ type clientHandshakeStateTLS13 struct { 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, // optionally, hs.session, hs.earlySecret and hs.binderKey to be set. func (hs *clientHandshakeStateTLS13) handshake() error { @@ -597,6 +640,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error { 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) @@ -605,8 +649,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()) @@ -674,6 +729,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 @@ -681,21 +774,34 @@ 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 @@ -711,7 +817,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. @@ -719,6 +827,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) diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go index a86055a0601..23b854bf173 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 @@ -187,6 +189,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) @@ -554,6 +569,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 @@ -1128,7 +1157,9 @@ type certificateRequestMsgTLS13 struct { raw []byte ocspStapling bool scts bool + supportDelegatedCredential bool supportedSignatureAlgorithms []SignatureScheme + supportedSignatureAlgorithmsDC []SignatureScheme supportedSignatureAlgorithmsCert []SignatureScheme certificateAuthorities [][]byte } @@ -1159,6 +1190,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 +1268,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 +1411,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 +1435,9 @@ func (m *certificateMsgTLS13) marshal() ([]byte, error) { if !m.scts { certificate.SignedCertificateTimestamps = nil } + if !m.delegatedCredential { + certificate.DelegatedCredential = nil + } marshalCertificate(b, certificate) }) @@ -1392,7 +1454,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 +1479,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 +1504,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 +1556,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 d974f294896..f01fdf81c8c 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -960,15 +960,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_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 4a2211af7cc..6ad7aa09c08 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -42,10 +42,50 @@ type serverHandshakeStateTLS13 struct { trafficSecret []byte // client_application_traffic_secret_0 transcript hash.Hash clientFinished []byte + certReq *certificateRequestMsgTLS13 hsTimings CFEventTLS13ServerHandshakeTimingInfo } +// 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 { c := hs.c @@ -445,6 +485,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 @@ -467,6 +532,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 @@ -474,8 +540,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 } @@ -566,6 +653,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 } @@ -594,6 +682,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 @@ -610,6 +703,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) @@ -703,10 +797,13 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { certReq.ocspStapling = true certReq.scts = true 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 } @@ -717,6 +814,7 @@ 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 @@ -727,8 +825,7 @@ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error { 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) } @@ -984,9 +1081,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()) } diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go index 3c6fe5aec01..668bb807a76 100644 --- a/src/crypto/tls/tls.go +++ b/src/crypto/tls/tls.go @@ -4,6 +4,20 @@ // 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 "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(agl): The crypto/tls package only implements some countermeasures diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index a70e65c3437..5d1b42f21fc 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -857,6 +857,8 @@ 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": diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go index b5bc3807697..0cda16738c6 100644 --- a/src/crypto/x509/parser.go +++ b/src/crypto/x509/parser.go @@ -805,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/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 9b31658e36c..194a18c88a0 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -746,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". // @@ -1074,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 ( @@ -1178,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}) @@ -1568,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_test.go b/src/crypto/x509/x509_test.go index ee9aba5cc2e..480f8dae4eb 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1970,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. From 0e7b54069be9519e8b4834068dca3df7bb30650a Mon Sep 17 00:00:00 2001 From: Christopher Patton Date: Wed, 23 Sep 2020 17:10:26 -0700 Subject: [PATCH 12/21] crypto/tls: implement draft-ietf-tls-esni-13 Adds support for draft 13 of the Encrypted ClientHello (ECH) extension for TLS. This requires CIRCL to implement draft 08 or later of the HPKE specification (draft-irtf-cfrg-hpke-08). Adds a CFEvent for reporting when ECH is offered or greased by the client, when ECH is accepted or rejected by the server, and when the outer SNI doesn't match the public name of the ECH config. Missing ECH features: * Record-level padding. * Proper validation of the public name by the client. * Retry after rejection. * PSKs are disabled when ECH is accepted. --- src/crypto/tls/alert.go | 2 + src/crypto/tls/cfevent.go | 65 + src/crypto/tls/common.go | 83 +- src/crypto/tls/conn.go | 47 + src/crypto/tls/ech.go | 1094 +++++++++++++++++ src/crypto/tls/ech_config.go | 165 +++ src/crypto/tls/ech_provider.go | 303 +++++ src/crypto/tls/ech_test.go | 952 ++++++++++++++ src/crypto/tls/handshake_client.go | 37 +- src/crypto/tls/handshake_client_tls13.go | 236 +++- src/crypto/tls/handshake_messages.go | 42 + src/crypto/tls/handshake_server.go | 13 +- src/crypto/tls/handshake_server_tls13.go | 119 +- src/crypto/tls/hpke.go | 42 + src/crypto/tls/tls.go | 27 + src/crypto/tls/tls_cf_test.go | 54 + src/crypto/tls/tls_test.go | 6 +- .../cloudflare/circl/ecc/p384/LICENSE | 26 + .../cloudflare/circl/ecc/p384/arith.go | 149 +++ .../cloudflare/circl/ecc/p384/arith_amd64.go | 8 + .../cloudflare/circl/ecc/p384/arith_amd64.s | 730 +++++++++++ .../cloudflare/circl/ecc/p384/arith_arm64.s | 511 ++++++++ .../cloudflare/circl/ecc/p384/doc.go | 10 + .../cloudflare/circl/ecc/p384/p384.go | 28 + .../cloudflare/circl/ecc/p384/p384_generic.go | 21 + .../cloudflare/circl/ecc/p384/p384opt.go | 181 +++ .../cloudflare/circl/ecc/p384/point.go | 358 ++++++ .../cloudflare/circl/ecc/p384/tableBase.go | 331 +++++ .../github.com/cloudflare/circl/hpke/aead.go | 103 ++ .../github.com/cloudflare/circl/hpke/algs.go | 278 +++++ .../github.com/cloudflare/circl/hpke/hpke.go | 271 ++++ .../cloudflare/circl/hpke/hybridkem.go | 232 ++++ .../cloudflare/circl/hpke/kembase.go | 241 ++++ .../cloudflare/circl/hpke/marshal.go | 151 +++ .../cloudflare/circl/hpke/shortkem.go | 170 +++ .../github.com/cloudflare/circl/hpke/util.go | 121 ++ .../github.com/cloudflare/circl/hpke/xkem.go | 164 +++ src/vendor/modules.txt | 2 + 38 files changed, 7336 insertions(+), 37 deletions(-) create mode 100644 src/crypto/tls/ech.go create mode 100644 src/crypto/tls/ech_config.go create mode 100644 src/crypto/tls/ech_provider.go create mode 100644 src/crypto/tls/ech_test.go create mode 100644 src/crypto/tls/hpke.go create mode 100644 src/crypto/tls/tls_cf_test.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/LICENSE create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.s create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/arith_arm64.s create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/doc.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/p384.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/p384_generic.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/point.go create mode 100644 src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/aead.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/algs.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/hpke.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/hybridkem.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/kembase.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/marshal.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/shortkem.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/util.go create mode 100644 src/vendor/github.com/cloudflare/circl/hpke/xkem.go 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/cfevent.go b/src/crypto/tls/cfevent.go index a2be30f516c..bc092b811d6 100644 --- a/src/crypto/tls/cfevent.go +++ b/src/crypto/tls/cfevent.go @@ -97,6 +97,71 @@ func createTLS13ServerHandshakeTimingInfo(timerFunc func() time.Time) CFEventTLS } } +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 diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index a22543b7c03..4620731b1be 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -124,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 @@ -247,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). @@ -315,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) } @@ -729,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. @@ -819,6 +869,23 @@ 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. @@ -915,6 +982,9 @@ func (c *Config) Clone() *Config { Renegotiation: c.Renegotiation, KeyLogWriter: c.KeyLogWriter, SupportDelegatedCredential: c.SupportDelegatedCredential, + ECHEnabled: c.ECHEnabled, + ClientECHConfigs: c.ClientECHConfigs, + ServerECHProvider: c.ServerECHProvider, sessionTicketKeys: c.sessionTicketKeys, autoSessionTicketKeys: c.autoSessionTicketKeys, } @@ -1113,6 +1183,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 { diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index e14b3f8a3c2..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. @@ -127,6 +129,20 @@ type Conn struct { // 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. @@ -728,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] { @@ -1436,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 } @@ -1629,6 +1674,8 @@ func (c *Conn) connectionStateLocked() ConnectionState { } 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[:] 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/handshake_client.go b/src/crypto/tls/handshake_client.go index f1e816b3eb6..b7754c3aa72 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -40,7 +40,7 @@ type clientHandshakeState struct { var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme -func (c *Conn) makeClientHello() (*clientHelloMsg, clientKeySharePrivate, 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") @@ -58,7 +58,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, clientKeySharePrivate, 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") } @@ -201,13 +201,30 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { // 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 } @@ -277,6 +294,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { ctx: ctx, serverHello: serverHello, hello: hello, + helloInner: helloInner, keySharePrivate: ecdheKey, session: session, earlySecret: earlySecret, @@ -288,6 +306,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) { return hs.handshake() } + c.serverName = hello.serverName hs := &clientHandshakeState{ c: c, ctx: ctx, @@ -305,7 +324,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 } @@ -1018,10 +1037,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(), } diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 6a7c526504a..eac73fcc685 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -11,6 +11,7 @@ import ( "crypto/ecdh" "crypto/hmac" "crypto/rsa" + "crypto/subtle" "errors" "fmt" "hash" @@ -22,6 +23,7 @@ type clientHandshakeStateTLS13 struct { ctx context.Context serverHello *serverHelloMsg hello *clientHelloMsg + helloInner *clientHelloMsg keySharePrivate clientKeySharePrivate session *SessionState @@ -29,13 +31,14 @@ type clientHandshakeStateTLS13 struct { binderKey []byte selectedGroup CurveID - certReq *certificateRequestMsgTLS13 - usingPSK bool - sentDummyCCS bool - suite *cipherSuiteTLS13 - transcript hash.Hash - masterSecret []byte - trafficSecret []byte // client_application_traffic_secret_0 + 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 } @@ -114,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 @@ -123,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 @@ -152,6 +202,9 @@ 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 } @@ -250,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. @@ -259,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 { @@ -272,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 @@ -300,7 +397,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { scheme.Name(), err) } hs.keySharePrivate = sk - hs.hello.keyShares = []keyShare{{group: curveID, data: packedPk}} + hello.keyShares = []keyShare{{group: curveID, data: packedPk}} } else { if _, ok := curveForCurveID(curveID); !ok { c.sendAlert(alertInternalError) @@ -312,12 +409,12 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { return err } hs.keySharePrivate = key - hs.hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} + 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) @@ -325,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))}) @@ -333,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 } @@ -375,6 +524,11 @@ 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 } @@ -417,6 +571,16 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error { 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") @@ -563,6 +727,22 @@ 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() @@ -880,7 +1060,7 @@ func (hs *clientHandshakeStateTLS13) sendClientFinished() error { 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) } @@ -901,7 +1081,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 } @@ -946,3 +1126,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 23b854bf173..40c54cca58b 100644 --- a/src/crypto/tls/handshake_messages.go +++ b/src/crypto/tls/handshake_messages.go @@ -97,6 +97,7 @@ type clientHelloMsg struct { pskIdentities []pskIdentity pskBinders [][]byte quicTransportParameters []byte + ech []byte } func (m *clientHelloMsg) marshal() ([]byte, error) { @@ -105,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) @@ -437,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 @@ -677,6 +691,7 @@ type serverHelloMsg struct { // HelloRetryRequest extensions cookie []byte selectedGroup CurveID + ech []byte } func (m *serverHelloMsg) marshal() ([]byte, error) { @@ -771,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 { @@ -904,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 @@ -922,6 +949,7 @@ type encryptedExtensionsMsg struct { alpnProtocol string quicTransportParameters []byte earlyData bool + ech []byte } func (m *encryptedExtensionsMsg) marshal() ([]byte, error) { @@ -955,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) + }) + } }) }) @@ -1001,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 diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index f01fdf81c8c..2182a438c97 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -145,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 { @@ -416,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 } @@ -551,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) diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 6ad7aa09c08..f65a4edf34a 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -47,6 +47,10 @@ type serverHandshakeStateTLS13 struct { 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. @@ -222,12 +226,42 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { hs.hello.cipherSuite = hs.suite.id hs.transcript = hs.suite.hash.New() + // 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 + } + } + } + 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 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 _, preferredGroup := range supportedCurves { for _, ks := range hs.clientHello.keyShares { if ks.group == preferredGroup { selectedGroup = ks.group @@ -326,7 +360,7 @@ GroupSelection: func (hs *serverHandshakeStateTLS13) checkForResumption() error { c := hs.c - if c.config.SessionTicketsDisabled { + if c.config.SessionTicketsDisabled || c.config.ECHEnabled { return nil } @@ -605,6 +639,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 } @@ -625,6 +695,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") @@ -712,6 +787,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 } @@ -770,6 +879,10 @@ 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 } @@ -915,7 +1028,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 } 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/tls.go b/src/crypto/tls/tls.go index 668bb807a76..a4826be91a6 100644 --- a/src/crypto/tls/tls.go +++ b/src/crypto/tls/tls.go @@ -5,6 +5,14 @@ // 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 @@ -20,6 +28,25 @@ // 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 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 5d1b42f21fc..64d2a86084b 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 @@ -871,6 +871,10 @@ func TestCloneNonFuncFields(t *testing.T) { 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/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..1b742de871a --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go @@ -0,0 +1,149 @@ +//go:build (!noasm && arm64) || (!noasm && amd64) +// +build !noasm,arm64 !noasm,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..1ea343b5daa --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.go @@ -0,0 +1,8 @@ +//go:build amd64 && !noasm +// +build amd64,!noasm + +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..5f53c637d06 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.s @@ -0,0 +1,730 @@ +// +build amd64,!noasm + +#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..ec93991d426 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_arm64.s @@ -0,0 +1,511 @@ +// +build arm64,!noasm + +#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..8444a59e204 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384_generic.go @@ -0,0 +1,21 @@ +//go:build noasm || (!amd64 && !arm64) +// +build noasm !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..91d17705175 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go @@ -0,0 +1,181 @@ +//go:build (!noasm && arm64) || (!noasm && amd64) +// +build !noasm,arm64 !noasm,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..0ba1da8bdb3 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go @@ -0,0 +1,358 @@ +//go:build (!noasm && arm64) || (!noasm && amd64) +// +build !noasm,arm64 !noasm,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..59cd319f321 --- /dev/null +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go @@ -0,0 +1,331 @@ +//go:build (!noasm && arm64) || (!noasm && amd64) +// +build !noasm,arm64 !noasm,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/modules.txt b/src/vendor/modules.txt index 529b8a6a973..dd4540d7e4e 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -3,6 +3,8 @@ 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 From b935551fd7734af5aa179e63f14e0b2d3a5f066e Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Mon, 14 Aug 2023 13:56:04 +0200 Subject: [PATCH 13/21] Set GOTOOLCHAIN to local to prevent auto-download of new Go --- go.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From d26ab7234de144be228d3004e3841ca3c16136ba Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Mon, 2 Oct 2023 13:46:43 +0200 Subject: [PATCH 14/21] Add tls.Config.ClientCurveGuess to allow specifying which keyshares to send RTG-2919 [ Bas 1.21.3: Send empty keyshare extension instead of leaving it out ] --- src/crypto/tls/cfkem.go | 23 ++----- src/crypto/tls/cfkem_test.go | 45 ++++++++++++ src/crypto/tls/common.go | 13 ++++ src/crypto/tls/handshake_client.go | 88 ++++++++++++++++++------ src/crypto/tls/handshake_client_tls13.go | 18 +++-- src/crypto/tls/handshake_messages.go | 2 +- src/crypto/tls/tls_test.go | 2 + 7 files changed, 144 insertions(+), 47 deletions(-) diff --git a/src/crypto/tls/cfkem.go b/src/crypto/tls/cfkem.go index 8d440e4c3c5..b300ce15c57 100644 --- a/src/crypto/tls/cfkem.go +++ b/src/crypto/tls/cfkem.go @@ -22,14 +22,14 @@ import ( "fmt" "io" - "crypto/ecdh" - "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/kem/hybrid" ) // Either *ecdh.PrivateKey or *kemPrivateKey -type clientKeySharePrivate interface{} +type singleClientKeySharePrivate interface{} + +type clientKeySharePrivate map[CurveID]singleClientKeySharePrivate type kemPrivateKey struct { secretKey kem.PrivateKey @@ -44,20 +44,9 @@ var ( invalidCurveID = CurveID(0) ) -// Extract CurveID from clientKeySharePrivate -func clientKeySharePrivateCurveID(ks clientKeySharePrivate) CurveID { - switch v := ks.(type) { - case *kemPrivateKey: - return v.curveID - case *ecdh.PrivateKey: - ret, ok := curveIDForCurve(v.Curve()) - if !ok { - panic("cfkem: internal error: unknown curve") - } - return ret - default: - panic("cfkem: internal error: unknown clientKeySharePrivate") - } +func singleClientKeySharePrivateFor(ks clientKeySharePrivate, group CurveID) singleClientKeySharePrivate { + ret, _ := ks[group] + return ret } // Returns scheme by CurveID if supported by Circl diff --git a/src/crypto/tls/cfkem_test.go b/src/crypto/tls/cfkem_test.go index 85da45ede8c..821cc674aff 100644 --- a/src/crypto/tls/cfkem_test.go +++ b/src/crypto/tls/cfkem_test.go @@ -104,3 +104,48 @@ func TestHybridKEX(t *testing.T) { 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 4620731b1be..60c3b2d0883 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -840,6 +840,18 @@ 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 @@ -977,6 +989,7 @@ 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, diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index b7754c3aa72..6755ce04b4a 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -134,7 +134,7 @@ func (c *Conn) makeClientHello(minVersion uint16) (*clientHelloMsg, clientKeySha hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms } - var secret clientKeySharePrivate + 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 { @@ -146,30 +146,74 @@ func (c *Conn) makeClientHello(minVersion uint16) (*clientHelloMsg, clientKeySha hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) } - curveID := config.curvePreferences()[0] - 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) + curveIDs := []CurveID{config.curvePreferences()[0]} + + if config.ClientCurveGuess != nil { + curveIDs = config.ClientCurveGuess + } + + 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++ } - hello.keyShares = []keyShare{{group: curveID, data: packedPk}} - secret = sk - } else { - if _, ok := curveForCurveID(curveID); !ok { - return nil, nil, errors.New("tls: CurvePreferences includes unsupported curve") + } + 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") } - key, err := generateECDHEKey(config.rand(), curveID) - if err != nil { - return nil, nil, err + + 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 = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} - secret = key + hello.keyShares = append(hello.keyShares, keyShare{group: curveID, data: singleShare}) + secret[curveID] = singleSecret } hello.delegatedCredentialSupported = config.SupportDelegatedCredential diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index eac73fcc685..04a272c4a91 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -103,7 +103,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error { } // Consistency check on the presence of a keyShare and its parameters. - if hs.keySharePrivate == nil || len(hs.hello.keyShares) != 1 { + if hs.keySharePrivate == nil { return c.sendAlert(alertInternalError) } @@ -379,7 +379,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: server selected unsupported group") } - if clientKeySharePrivateCurveID(hs.keySharePrivate) == curveID { + if singleClientKeySharePrivateFor(hs.keySharePrivate, curveID) != nil { c.sendAlert(alertIllegalParameter) return errors.New("tls: server sent an unnecessary HelloRetryRequest key_share") } @@ -396,7 +396,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { return fmt.Errorf("HRR pack circl public key %s: %w", scheme.Name(), err) } - hs.keySharePrivate = sk + hs.keySharePrivate = clientKeySharePrivate{curveID: sk} hello.keyShares = []keyShare{{group: curveID, data: packedPk}} } else { if _, ok := curveForCurveID(curveID); !ok { @@ -408,7 +408,7 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { c.sendAlert(alertInternalError) return err } - hs.keySharePrivate = key + hs.keySharePrivate = clientKeySharePrivate{curveID: key} hello.keyShares = []keyShare{{group: curveID, data: key.PublicKey().Bytes()}} } } @@ -558,7 +558,7 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error { c.sendAlert(alertIllegalParameter) return errors.New("tls: server did not send a key share") } - if hs.serverHello.serverShare.group != clientKeySharePrivateCurveID(hs.keySharePrivate) { + if singleClientKeySharePrivateFor(hs.keySharePrivate, hs.serverHello.serverShare.group) == nil { c.sendAlert(alertIllegalParameter) return errors.New("tls: server selected unsupported group") } @@ -613,12 +613,16 @@ func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { var sharedKey []byte var err error - if key, ok := hs.keySharePrivate.(*ecdh.PrivateKey); ok { + + // 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 := hs.keySharePrivate.(*kemPrivateKey); ok { + } else if key, ok := ks.(*kemPrivateKey); ok { sk := key.secretKey sharedKey, err = sk.Scheme().Decapsulate(sk, hs.serverHello.serverShare.data) if err != nil { diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go index 40c54cca58b..b3840f6c10f 100644 --- a/src/crypto/tls/handshake_messages.go +++ b/src/crypto/tls/handshake_messages.go @@ -248,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) { diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index 64d2a86084b..874548db670 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -865,6 +865,8 @@ func TestCloneNonFuncFields(t *testing.T) { 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": From 9f089759949b6205801e8f3d85a01bb836b2fbd3 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Tue, 3 Oct 2023 13:24:35 +0200 Subject: [PATCH 15/21] Use server's preferred key agreement In contrast to upstream Go, we will send an HelloRetryRequest and accept an extra roundtrip if there is a more preferred group, than the one the client has provided a keyshare for in the initial ClientHello. Cf. https://datatracker.ietf.org/doc/draft-davidben-tls-key-share-prediction/ --- src/crypto/tls/handshake_server_test.go | 1 + src/crypto/tls/handshake_server_tls13.go | 25 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) 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 f65a4edf34a..298d271d5c6 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -256,26 +256,19 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { } } - // Pick the ECDHE group in server preference order, but give priority to - // groups with a key share, to avoid a HelloRetryRequest round-trip. + // 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 _, ks := range hs.clientHello.keyShares { - if ks.group == preferredGroup { - selectedGroup = ks.group - clientKeyShare = &ks - break GroupSelection - } - } - if selectedGroup != 0 { - continue - } for _, group := range hs.clientHello.supportedCurves { if group == preferredGroup { selectedGroup = group - break + break GroupSelection } } } @@ -283,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 From f4334cdc0c3f22a3bfdd7e66f387e3ffc65a5c38 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Tue, 10 Oct 2023 13:26:07 +0200 Subject: [PATCH 16/21] Add dummy key agreement with codepoint 0xfe33 (#162) DummyKex is 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. --- src/crypto/tls/cfkem.go | 8 ++++++++ src/crypto/tls/cfkem_test.go | 1 + 2 files changed, 9 insertions(+) diff --git a/src/crypto/tls/cfkem.go b/src/crypto/tls/cfkem.go index b300ce15c57..d3f54987616 100644 --- a/src/crypto/tls/cfkem.go +++ b/src/crypto/tls/cfkem.go @@ -22,6 +22,7 @@ import ( "fmt" "io" + "github.com/cloudflare/circl/hpke" "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/kem/hybrid" ) @@ -42,6 +43,11 @@ var ( X25519Kyber768Draft00Old = CurveID(0xfe31) P256Kyber768Draft00 = CurveID(0xfe32) 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 { @@ -58,6 +64,8 @@ func curveIdToCirclScheme(id CurveID) kem.Scheme { return hybrid.Kyber768X25519() case P256Kyber768Draft00: return hybrid.P256Kyber768Draft00() + case DummyKex: + return hpke.KEM_X25519_HKDF_SHA256.Scheme() } return nil } diff --git a/src/crypto/tls/cfkem_test.go b/src/crypto/tls/cfkem_test.go index 821cc674aff..b8f57a4f4de 100644 --- a/src/crypto/tls/cfkem_test.go +++ b/src/crypto/tls/cfkem_test.go @@ -95,6 +95,7 @@ func TestHybridKEX(t *testing.T) { X25519Kyber768Draft00, X25519Kyber768Draft00Old, P256Kyber768Draft00, + DummyKex, } { run(curveID, true, true, false, false) run(curveID, true, false, false, false) From af19da5605ca11f85776ef7af3384a02a315a52b Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Fri, 6 Sep 2024 15:00:02 +0200 Subject: [PATCH 17/21] Add support for X25519MLKEM768. (#179) --- src/crypto/tls/cfkem.go | 3 + src/crypto/tls/cfkem_test.go | 1 + src/go.mod | 2 +- src/go.sum | 4 +- src/go/build/deps_test.go | 6 +- .../cloudflare/circl/dh/x25519/curve_amd64.s | 3 +- .../cloudflare/circl/dh/x448/curve_amd64.s | 3 +- .../cloudflare/circl/ecc/p384/arith.go | 4 +- .../cloudflare/circl/ecc/p384/arith_amd64.go | 4 +- .../cloudflare/circl/ecc/p384/arith_amd64.s | 2 +- .../cloudflare/circl/ecc/p384/arith_arm64.s | 2 +- .../cloudflare/circl/ecc/p384/p384_generic.go | 4 +- .../cloudflare/circl/ecc/p384/p384opt.go | 4 +- .../cloudflare/circl/ecc/p384/point.go | 4 +- .../cloudflare/circl/ecc/p384/tableBase.go | 4 +- .../cloudflare/circl/kem/hybrid/hybrid.go | 21 +- .../github.com/cloudflare/circl/kem/kem.go | 3 + .../circl/kem/kyber/kyber1024/kyber.go | 9 +- .../circl/kem/kyber/kyber512/kyber.go | 9 +- .../circl/kem/kyber/kyber768/kyber.go | 9 +- .../circl/kem/mlkem/mlkem768/kyber.go | 407 +++++++++++++++++ .../cloudflare/circl/math/fp25519/fp_amd64.s | 3 +- .../cloudflare/circl/math/fp448/fp_amd64.s | 3 +- .../circl/pke/kyber/internal/common/amd64.go | 4 +- .../circl/pke/kyber/internal/common/amd64.s | 2 +- .../pke/kyber/internal/common/generic.go | 4 +- .../pke/kyber/internal/common/stubs_amd64.go | 2 +- .../pke/kyber/kyber1024/internal/cpapke.go | 16 + .../circl/pke/kyber/kyber1024/kyber.go | 32 +- .../pke/kyber/kyber512/internal/cpapke.go | 16 + .../circl/pke/kyber/kyber512/kyber.go | 32 +- .../pke/kyber/kyber768/internal/cpapke.go | 16 + .../circl/pke/kyber/kyber768/kyber.go | 32 +- .../sign/dilithium/internal/common/amd64.go | 4 +- .../sign/dilithium/internal/common/amd64.s | 2 +- .../sign/dilithium/internal/common/generic.go | 4 +- .../dilithium/internal/common/stubs_amd64.go | 2 +- .../circl/sign/eddilithium3/eddilithium.go | 6 +- .../circl/simd/keccakf1600/f1600x2_arm64.go | 4 +- .../circl/simd/keccakf1600/f1600x2_arm64.s | 2 +- .../circl/simd/keccakf1600/f1600x4_amd64.go | 3 + .../circl/simd/keccakf1600/f1600x4_amd64.s | 2 +- .../simd/keccakf1600/f1600x4stubs_amd64.go | 2 +- .../circl/simd/keccakf1600/fallback.go | 4 +- src/vendor/golang.org/x/crypto/sha3/doc.go | 62 +++ src/vendor/golang.org/x/crypto/sha3/hashes.go | 97 ++++ .../x/crypto/sha3/hashes_generic.go | 27 ++ .../golang.org/x/crypto/sha3/keccakf.go | 414 ++++++++++++++++++ .../golang.org/x/crypto/sha3/keccakf_amd64.go | 13 + .../golang.org/x/crypto/sha3/keccakf_amd64.s | 390 +++++++++++++++++ .../golang.org/x/crypto/sha3/register.go | 18 + src/vendor/golang.org/x/crypto/sha3/sha3.go | 197 +++++++++ .../golang.org/x/crypto/sha3/sha3_s390x.go | 288 ++++++++++++ .../golang.org/x/crypto/sha3/sha3_s390x.s | 33 ++ src/vendor/golang.org/x/crypto/sha3/shake.go | 172 ++++++++ .../golang.org/x/crypto/sha3/shake_generic.go | 19 + src/vendor/golang.org/x/crypto/sha3/xor.go | 23 + .../golang.org/x/crypto/sha3/xor_generic.go | 28 ++ .../golang.org/x/crypto/sha3/xor_unaligned.go | 66 +++ src/vendor/modules.txt | 6 +- 60 files changed, 2492 insertions(+), 66 deletions(-) create mode 100644 src/vendor/github.com/cloudflare/circl/kem/mlkem/mlkem768/kyber.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/doc.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/hashes.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/hashes_generic.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/keccakf.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s create mode 100644 src/vendor/golang.org/x/crypto/sha3/register.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/sha3.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/sha3_s390x.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/sha3_s390x.s create mode 100644 src/vendor/golang.org/x/crypto/sha3/shake.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/shake_generic.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/xor.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/xor_generic.go create mode 100644 src/vendor/golang.org/x/crypto/sha3/xor_unaligned.go diff --git a/src/crypto/tls/cfkem.go b/src/crypto/tls/cfkem.go index d3f54987616..7f1bb6cd5bf 100644 --- a/src/crypto/tls/cfkem.go +++ b/src/crypto/tls/cfkem.go @@ -42,6 +42,7 @@ var ( 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 @@ -64,6 +65,8 @@ func curveIdToCirclScheme(id CurveID) kem.Scheme { return hybrid.Kyber768X25519() case P256Kyber768Draft00: return hybrid.P256Kyber768Draft00() + case X25519MLKEM768: + return hybrid.X25519MLKEM768() case DummyKex: return hpke.KEM_X25519_HKDF_SHA256.Scheme() } diff --git a/src/crypto/tls/cfkem_test.go b/src/crypto/tls/cfkem_test.go index b8f57a4f4de..cf59ac5f3af 100644 --- a/src/crypto/tls/cfkem_test.go +++ b/src/crypto/tls/cfkem_test.go @@ -95,6 +95,7 @@ func TestHybridKEX(t *testing.T) { X25519Kyber768Draft00, X25519Kyber768Draft00Old, P256Kyber768Draft00, + X25519MLKEM768, DummyKex, } { run(curveID, true, true, false, false) diff --git a/src/go.mod b/src/go.mod index c82ed2bf9f0..24f3d5946e0 100644 --- a/src/go.mod +++ b/src/go.mod @@ -3,7 +3,7 @@ module std go 1.22 require ( - github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7 + 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 a373acaa66d..4e86797268f 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,5 +1,5 @@ -github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7 h1:nRedc5Iqg+cBRSKkA3c7+IUFgK9qdw87kz/McP3HnLs= -github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7/go.mod h1:uAwUTm6m3uQF5fuJKR6LvFqgxn2wyID+kF6KJAUcZl8= +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 eeb5c88b2a0..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; 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 index b7723185b61..ce9f062894a 100644 --- a/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s +++ b/src/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s @@ -1,4 +1,5 @@ -// +build amd64 +//go:build amd64 && !purego +// +build amd64,!purego #include "textflag.h" 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 index 810aa9e6481..ed33ba3d032 100644 --- a/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s +++ b/src/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s @@ -1,4 +1,5 @@ -// +build amd64 +//go:build amd64 && !purego +// +build amd64,!purego #include "textflag.h" diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go index 1b742de871a..889e7771f1d 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith.go @@ -1,5 +1,5 @@ -//go:build (!noasm && arm64) || (!noasm && amd64) -// +build !noasm,arm64 !noasm,amd64 +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 package p384 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 index 1ea343b5daa..2e9d8fddb5e 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.go +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.go @@ -1,5 +1,5 @@ -//go:build amd64 && !noasm -// +build amd64,!noasm +//go:build amd64 && !purego +// +build amd64,!purego package p384 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 index 5f53c637d06..eaf6fb7a771 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.s +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_amd64.s @@ -1,4 +1,4 @@ -// +build amd64,!noasm +// +build amd64,!purego #include "textflag.h" 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 index ec93991d426..a02e76d576e 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_arm64.s +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/arith_arm64.s @@ -1,4 +1,4 @@ -// +build arm64,!noasm +// +build arm64,!purego #include "textflag.h" 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 index 8444a59e204..9b14feaec08 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/p384_generic.go +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384_generic.go @@ -1,5 +1,5 @@ -//go:build noasm || (!amd64 && !arm64) -// +build noasm !amd64,!arm64 +//go:build purego || (!amd64 && !arm64) +// +build purego !amd64,!arm64 package p384 diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go index 91d17705175..5f744eac89b 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/p384opt.go @@ -1,5 +1,5 @@ -//go:build (!noasm && arm64) || (!noasm && amd64) -// +build !noasm,arm64 !noasm,amd64 +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 package p384 diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go index 0ba1da8bdb3..e20b57b0176 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/point.go @@ -1,5 +1,5 @@ -//go:build (!noasm && arm64) || (!noasm && amd64) -// +build !noasm,arm64 !noasm,amd64 +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 package p384 diff --git a/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go b/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go index 59cd319f321..5132565ef34 100644 --- a/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go +++ b/src/vendor/github.com/cloudflare/circl/ecc/p384/tableBase.go @@ -1,5 +1,5 @@ -//go:build (!noasm && arm64) || (!noasm && amd64) -// +build !noasm,arm64 !noasm,amd64 +//go:build (!purego && arm64) || (!purego && amd64) +// +build !purego,arm64 !purego,amd64 package p384 diff --git a/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go b/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go index be8251c7f74..8be85d70c81 100644 --- a/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go +++ b/src/vendor/github.com/cloudflare/circl/kem/hybrid/hybrid.go @@ -1,13 +1,13 @@ -// Package hybrid defines several hybrid classical/quantum KEMs. +// Package hybrid defines several hybrid classical/quantum KEMs for use in TLS. // -// KEMs are combined by simple concatenation of shared secrets, cipher texts, -// public keys, etc, see +// 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 is only fine if the shared secret is used in its entirety -// in a next step, such as being hashed or used as key. +// 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, @@ -38,6 +38,7 @@ import ( "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") @@ -57,6 +58,10 @@ 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, @@ -87,6 +92,12 @@ var kyber1024X kem.Scheme = &scheme{ kyber1024.Scheme(), } +var xmlkem768 kem.Scheme = &scheme{ + "X25519MLKEM768", + mlkem768.Scheme(), + x25519Kem, +} + // Public key of a hybrid KEM. type publicKey struct { scheme *scheme diff --git a/src/vendor/github.com/cloudflare/circl/kem/kem.go b/src/vendor/github.com/cloudflare/circl/kem/kem.go index 6ab0aa3bad3..a2f6a2aae7a 100644 --- a/src/vendor/github.com/cloudflare/circl/kem/kem.go +++ b/src/vendor/github.com/cloudflare/circl/kem/kem.go @@ -113,6 +113,9 @@ var ( // 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 index 428584528ea..c2f767cbe72 100644 --- a/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber1024/kyber.go +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber1024/kyber.go @@ -123,10 +123,10 @@ func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { panic("ss must be of length SharedKeySize") } - // m = H(seed) var m [32]byte + // m = H(seed), the hash of shame h := sha3.New256() - h.Write(seed[:]) + h.Write(seed) h.Read(m[:]) // (K', r) = G(m ‖ H(pk)) @@ -194,7 +194,7 @@ func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) { // K = KDF(K''/z, H(c)) kdf := sha3.NewShake256() kdf.Write(kr2[:]) - kdf.Read(ss[:SharedKeySize]) + kdf.Read(ss) } // Packs sk to buf. @@ -258,6 +258,7 @@ func (pk *PublicKey) Unpack(buf []byte) { h := sha3.New256() h.Write(buf) h.Read(pk.hpk[:]) + } // Boilerplate down below for the KEM scheme API. @@ -386,10 +387,10 @@ func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + var ret PublicKey if len(buf) != PublicKeySize { return nil, kem.ErrPubKeySize } - var ret PublicKey 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 index c250d78c673..e60ca0fe58b 100644 --- a/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber512/kyber.go +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber512/kyber.go @@ -123,10 +123,10 @@ func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { panic("ss must be of length SharedKeySize") } - // m = H(seed) var m [32]byte + // m = H(seed), the hash of shame h := sha3.New256() - h.Write(seed[:]) + h.Write(seed) h.Read(m[:]) // (K', r) = G(m ‖ H(pk)) @@ -194,7 +194,7 @@ func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) { // K = KDF(K''/z, H(c)) kdf := sha3.NewShake256() kdf.Write(kr2[:]) - kdf.Read(ss[:SharedKeySize]) + kdf.Read(ss) } // Packs sk to buf. @@ -258,6 +258,7 @@ func (pk *PublicKey) Unpack(buf []byte) { h := sha3.New256() h.Write(buf) h.Read(pk.hpk[:]) + } // Boilerplate down below for the KEM scheme API. @@ -386,10 +387,10 @@ func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + var ret PublicKey if len(buf) != PublicKeySize { return nil, kem.ErrPubKeySize } - var ret PublicKey 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 index 832d9b371ad..0e03c40ddd6 100644 --- a/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber768/kyber.go +++ b/src/vendor/github.com/cloudflare/circl/kem/kyber/kyber768/kyber.go @@ -123,10 +123,10 @@ func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { panic("ss must be of length SharedKeySize") } - // m = H(seed) var m [32]byte + // m = H(seed), the hash of shame h := sha3.New256() - h.Write(seed[:]) + h.Write(seed) h.Read(m[:]) // (K', r) = G(m ‖ H(pk)) @@ -194,7 +194,7 @@ func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) { // K = KDF(K''/z, H(c)) kdf := sha3.NewShake256() kdf.Write(kr2[:]) - kdf.Read(ss[:SharedKeySize]) + kdf.Read(ss) } // Packs sk to buf. @@ -258,6 +258,7 @@ func (pk *PublicKey) Unpack(buf []byte) { h := sha3.New256() h.Write(buf) h.Read(pk.hpk[:]) + } // Boilerplate down below for the KEM scheme API. @@ -386,10 +387,10 @@ func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { } func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { + var ret PublicKey if len(buf) != PublicKeySize { return nil, kem.ErrPubKeySize } - var ret PublicKey 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_amd64.s b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.s index 5c4aeddecb4..1fcc2dee17f 100644 --- a/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.s +++ b/src/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.s @@ -1,4 +1,5 @@ -// +build amd64 +//go:build amd64 && !purego +// +build amd64,!purego #include "textflag.h" #include "fp_amd64.h" 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 index 435addf5e6c..3f1f07c9862 100644 --- a/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s +++ b/src/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s @@ -1,4 +1,5 @@ -// +build amd64 +//go:build amd64 && !purego +// +build amd64,!purego #include "textflag.h" #include "fp_amd64.h" 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 index 6ffd94b1fc2..2c96563c7dc 100644 --- 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 @@ -1,5 +1,5 @@ -//go:build amd64 -// +build amd64 +//go:build amd64 && !purego +// +build amd64,!purego package common 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 index f721482fb9d..5c7536b7013 100644 --- 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 @@ -1,6 +1,6 @@ // Code generated by command: go run src.go -out ../amd64.s -stubs ../stubs_amd64.go -pkg common. DO NOT EDIT. -//go:build amd64 +//go:build amd64 && !purego #include "textflag.h" 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 index 2b742b95a38..66e0e86dc8c 100644 --- 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 @@ -1,5 +1,5 @@ -//go:build !amd64 -// +build !amd64 +//go:build !amd64 || purego +// +build !amd64 purego package common 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 index cf14cff912d..4b4700dfd9d 100644 --- 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 @@ -1,6 +1,6 @@ // Code generated by command: go run src.go -out ../amd64.s -stubs ../stubs_amd64.go -pkg common. DO NOT EDIT. -//go:build amd64 +//go:build amd64 && !purego package common 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 index 01ef88b2f60..bea07e87438 100644 --- 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 @@ -3,7 +3,10 @@ package internal import ( + "bytes" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/pke/kyber/internal/common" ) @@ -38,6 +41,19 @@ func (pk *PublicKey) Pack(buf []byte) { 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) 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 index fb5911facd4..86cc6c6dbcd 100644 --- a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/kyber.go +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber1024/kyber.go @@ -1,4 +1,4 @@ -// Code generated from modePkg.templ.go. DO NOT EDIT. +// 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 @@ -11,6 +11,7 @@ import ( cryptoRand "crypto/rand" "io" + "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/pke/kyber/kyber1024/internal" ) @@ -57,6 +58,9 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { // 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 { @@ -66,6 +70,21 @@ func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { 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. // @@ -129,6 +148,17 @@ func (pk *PublicKey) Unpack(buf []byte) { (*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. 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 index 80ab2501c2f..be9bd6eafd5 100644 --- 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 @@ -1,7 +1,10 @@ package internal import ( + "bytes" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/pke/kyber/internal/common" ) @@ -36,6 +39,19 @@ func (pk *PublicKey) Pack(buf []byte) { 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) 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 index ea9248487e1..d4b166a5244 100644 --- a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/kyber.go +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber512/kyber.go @@ -1,4 +1,4 @@ -// Code generated from modePkg.templ.go. DO NOT EDIT. +// 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 @@ -11,6 +11,7 @@ import ( cryptoRand "crypto/rand" "io" + "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/pke/kyber/kyber512/internal" ) @@ -57,6 +58,9 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { // 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 { @@ -66,6 +70,21 @@ func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { 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. // @@ -129,6 +148,17 @@ func (pk *PublicKey) Unpack(buf []byte) { (*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. 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 index 01ef88b2f60..bea07e87438 100644 --- 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 @@ -3,7 +3,10 @@ package internal import ( + "bytes" + "github.com/cloudflare/circl/internal/sha3" + "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/pke/kyber/internal/common" ) @@ -38,6 +41,19 @@ func (pk *PublicKey) Pack(buf []byte) { 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) 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 index 4cecbb1b871..75bb7bd34db 100644 --- a/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/kyber.go +++ b/src/vendor/github.com/cloudflare/circl/pke/kyber/kyber768/kyber.go @@ -1,4 +1,4 @@ -// Code generated from modePkg.templ.go. DO NOT EDIT. +// 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 @@ -11,6 +11,7 @@ import ( cryptoRand "crypto/rand" "io" + "github.com/cloudflare/circl/kem" "github.com/cloudflare/circl/pke/kyber/kyber768/internal" ) @@ -57,6 +58,9 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) { // 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 { @@ -66,6 +70,21 @@ func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) { 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. // @@ -129,6 +148,17 @@ func (pk *PublicKey) Unpack(buf []byte) { (*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. 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 index a58e4bf46a9..11f0e3dcf6b 100644 --- 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 @@ -1,5 +1,5 @@ -//go:build amd64 -// +build amd64 +//go:build amd64 && !purego +// +build amd64,!purego package common diff --git a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.s b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.s index 90953ac1ebe..94180fb7344 100644 --- a/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.s +++ b/src/vendor/github.com/cloudflare/circl/sign/dilithium/internal/common/amd64.s @@ -1,6 +1,6 @@ // Code generated by command: go run src.go -out ../amd64.s -stubs ../stubs_amd64.go -pkg common. DO NOT EDIT. -//go:build amd64 +//go:build amd64 && !purego #include "textflag.h" 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 index f10545246ab..2736e1617f4 100644 --- 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 @@ -1,5 +1,5 @@ -//go:build !amd64 -// +build !amd64 +//go:build !amd64 || purego +// +build !amd64 purego package common 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 index 97451507f8d..3afeda4ddbb 100644 --- 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 @@ -1,6 +1,6 @@ // Code generated by command: go run src.go -out ../amd64.s -stubs ../stubs_amd64.go -pkg common. DO NOT EDIT. -//go:build amd64 +//go:build amd64 && !purego package common diff --git a/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go b/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go index d1c8d629d64..aa05c689c31 100644 --- a/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go +++ b/src/vendor/github.com/cloudflare/circl/sign/eddilithium3/eddilithium.go @@ -162,7 +162,7 @@ func (sk *PrivateKey) MarshalBinary() ([]byte, error) { // 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 eddilithium4.PublicKeySize bytes") + return errors.New("packed public key must be of eddilithium3.PublicKeySize bytes") } var buf [PublicKeySize]byte copy(buf[:], data) @@ -173,7 +173,7 @@ func (pk *PublicKey) UnmarshalBinary(data []byte) error { // 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 eddilithium4.PrivateKeySize bytes") + return errors.New("packed private key must be of eddilithium3.PrivateKeySize bytes") } var buf [PrivateKeySize]byte copy(buf[:], data) @@ -215,7 +215,7 @@ func (sk *PrivateKey) Sign( var sig [SignatureSize]byte if opts.HashFunc() != crypto.Hash(0) { - return nil, errors.New("eddilithium4: cannot sign hashed message") + return nil, errors.New("eddilithium3: cannot sign hashed message") } SignTo(sk, msg, sig[:]) 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 index 44f05436a84..0cb9692c327 100644 --- a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.go +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.go @@ -1,5 +1,5 @@ -//go:build arm64 && go1.16 -// +build arm64,go1.16 +//go:build arm64 && go1.16 && !purego +// +build arm64,go1.16,!purego package keccakf1600 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 index 68dd0e37bc0..998aeca5b4c 100644 --- a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.s +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x2_arm64.s @@ -1,4 +1,4 @@ -// +build arm64,go1.16 +// +build arm64,go1.16,!purego // Taken from https://github.com/bwesterb/armed-keccak 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 index 669ce65f4db..bf5b865d0b6 100644 --- a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.go +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.go @@ -1,3 +1,6 @@ +//go:build amd64 && !purego +// +build amd64,!purego + package keccakf1600 import "github.com/cloudflare/circl/internal/sha3" 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 index 314a8555330..67b64550c26 100644 --- a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.s +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4_amd64.s @@ -1,6 +1,6 @@ // Code generated by command: go run src.go -out ../../f1600x4_amd64.s -stubs ../../f1600x4stubs_amd64.go -pkg keccakf1600. DO NOT EDIT. -//go:build amd64 +//go:build amd64 && !purego #include "textflag.h" 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 index de289441ef5..102fdd04d16 100644 --- a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4stubs_amd64.go +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/f1600x4stubs_amd64.go @@ -1,6 +1,6 @@ // Code generated by command: go run src.go -out ../../f1600x4_amd64.s -stubs ../../f1600x4stubs_amd64.go -pkg keccakf1600. DO NOT EDIT. -//go:build amd64 +//go:build amd64 && !purego package keccakf1600 diff --git a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go index 5287c1f5d7b..0da75e9b776 100644 --- a/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go +++ b/src/vendor/github.com/cloudflare/circl/simd/keccakf1600/fallback.go @@ -1,5 +1,5 @@ -//go:build (!amd64 && !arm64) || (arm64 && !go1.16) -// +build !amd64,!arm64 arm64,!go1.16 +//go:build (!amd64 && !arm64) || (arm64 && !go1.16) || purego +// +build !amd64,!arm64 arm64,!go1.16 purego package keccakf1600 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 dd4540d7e4e..b52c02e61c0 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,5 +1,5 @@ -# github.com/cloudflare/circl v1.3.8-0.20240208083452-454cfdc0f6c7 -## explicit; go 1.19 +# 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 @@ -12,6 +12,7 @@ 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 @@ -51,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 From 26c1b8207ee3f2ddd29f3424b216141abe3171a2 Mon Sep 17 00:00:00 2001 From: Hrushikesh Deshpande Date: Mon, 16 Sep 2024 10:05:37 -0400 Subject: [PATCH 18/21] Adding semgrep yaml file --- .github/workflows/semgrep.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/semgrep.yml diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml new file mode 100644 index 00000000000..ede31f55b71 --- /dev/null +++ b/.github/workflows/semgrep.yml @@ -0,0 +1,23 @@ + +on: + pull_request: {} + workflow_dispatch: {} + push: + branches: + - main + - master +name: Semgrep config +jobs: + semgrep: + name: semgrep/ci + runs-on: ubuntu-20.04 + env: + SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + SEMGREP_URL: https://cloudflare.semgrep.dev + SEMGREP_APP_URL: https://cloudflare.semgrep.dev + SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version + container: + image: returntocorp/semgrep + steps: + - uses: actions/checkout@v3 + - run: semgrep ci From a4257822dadb8bf01bf136905522d95ec3a88abc Mon Sep 17 00:00:00 2001 From: Hrushikesh Deshpande Date: Mon, 16 Sep 2024 10:06:22 -0400 Subject: [PATCH 19/21] Adding semgrep yaml file From 6a2fa247ea5e2d6cf2891155a11d264ee51c7044 Mon Sep 17 00:00:00 2001 From: hrushikeshdeshpande <161167942+hrushikeshdeshpande@users.noreply.github.com> Date: Sat, 21 Sep 2024 17:01:04 -0400 Subject: [PATCH 20/21] Update semgrep.yml Updating Semgrep.yml file - Semgrep is a tool that will be used to scan Cloudflare's public repos for Supply chain, code and secrets. This work is part of Application & Product Security team's initiative to onboard Semgrep onto all of Cloudflare's public repos. In case of any questions, please reach out to "Hrushikesh Deshpande" on cf internal chat. --- .github/workflows/semgrep.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index ede31f55b71..b40314b3677 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -1,4 +1,3 @@ - on: pull_request: {} workflow_dispatch: {} @@ -6,11 +5,13 @@ on: branches: - main - master + schedule: + - cron: '0 0 * * *' name: Semgrep config jobs: semgrep: name: semgrep/ci - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest env: SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} SEMGREP_URL: https://cloudflare.semgrep.dev @@ -19,5 +20,5 @@ jobs: container: image: returntocorp/semgrep steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: semgrep ci From 532645c46272ccc6b49ad6a19787863157b4618f Mon Sep 17 00:00:00 2001 From: Hrushikesh Deshpande <161167942+hrushikeshdeshpande@users.noreply.github.com> Date: Wed, 25 Sep 2024 00:19:34 -0400 Subject: [PATCH 21/21] Update semgrep.yml --- .github/workflows/semgrep.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index b40314b3677..4090692fe0b 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -18,7 +18,7 @@ jobs: SEMGREP_APP_URL: https://cloudflare.semgrep.dev SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version container: - image: returntocorp/semgrep + image: semgrep/semgrep steps: - uses: actions/checkout@v4 - run: semgrep ci