Bump github.com/go-git/go-git/v5 from 5.4.2 to 5.11.0
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.4.2 to 5.11.0. - [Release notes](https://github.com/go-git/go-git/releases) - [Commits](https://github.com/go-git/go-git/compare/v5.4.2...v5.11.0) --- updated-dependencies: - dependency-name: github.com/go-git/go-git/v5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
1
vendor/github.com/Microsoft/go-winio/.gitattributes
generated
vendored
Normal file
1
vendor/github.com/Microsoft/go-winio/.gitattributes
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
9
vendor/github.com/Microsoft/go-winio/.gitignore
generated
vendored
9
vendor/github.com/Microsoft/go-winio/.gitignore
generated
vendored
@@ -1 +1,10 @@
|
||||
.vscode/
|
||||
|
||||
*.exe
|
||||
|
||||
# testing
|
||||
testdata
|
||||
|
||||
# go workspaces
|
||||
go.work
|
||||
go.work.sum
|
||||
|
||||
149
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
Normal file
149
vendor/github.com/Microsoft/go-winio/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
run:
|
||||
skip-dirs:
|
||||
- pkg/etw/sample
|
||||
|
||||
linters:
|
||||
enable:
|
||||
# style
|
||||
- containedctx # struct contains a context
|
||||
- dupl # duplicate code
|
||||
- errname # erorrs are named correctly
|
||||
- nolintlint # "//nolint" directives are properly explained
|
||||
- revive # golint replacement
|
||||
- unconvert # unnecessary conversions
|
||||
- wastedassign
|
||||
|
||||
# bugs, performance, unused, etc ...
|
||||
- contextcheck # function uses a non-inherited context
|
||||
- errorlint # errors not wrapped for 1.13
|
||||
- exhaustive # check exhaustiveness of enum switch statements
|
||||
- gofmt # files are gofmt'ed
|
||||
- gosec # security
|
||||
- nilerr # returns nil even with non-nil error
|
||||
- unparam # unused function params
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# err is very often shadowed in nested scopes
|
||||
- linters:
|
||||
- govet
|
||||
text: '^shadow: declaration of "err" shadows declaration'
|
||||
|
||||
# ignore long lines for skip autogen directives
|
||||
- linters:
|
||||
- revive
|
||||
text: "^line-length-limit: "
|
||||
source: "^//(go:generate|sys) "
|
||||
|
||||
#TODO: remove after upgrading to go1.18
|
||||
# ignore comment spacing for nolint and sys directives
|
||||
- linters:
|
||||
- revive
|
||||
text: "^comment-spacings: no space between comment delimiter and comment text"
|
||||
source: "//(cspell:|nolint:|sys |todo)"
|
||||
|
||||
# not on go 1.18 yet, so no any
|
||||
- linters:
|
||||
- revive
|
||||
text: "^use-any: since GO 1.18 'interface{}' can be replaced by 'any'"
|
||||
|
||||
# allow unjustified ignores of error checks in defer statements
|
||||
- linters:
|
||||
- nolintlint
|
||||
text: "^directive `//nolint:errcheck` should provide explanation"
|
||||
source: '^\s*defer '
|
||||
|
||||
# allow unjustified ignores of error lints for io.EOF
|
||||
- linters:
|
||||
- nolintlint
|
||||
text: "^directive `//nolint:errorlint` should provide explanation"
|
||||
source: '[=|!]= io.EOF'
|
||||
|
||||
|
||||
linters-settings:
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
# struct order is often for Win32 compat
|
||||
# also, ignore pointer bytes/GC issues for now until performance becomes an issue
|
||||
- fieldalignment
|
||||
check-shadowing: true
|
||||
nolintlint:
|
||||
allow-leading-space: false
|
||||
require-explanation: true
|
||||
require-specific: true
|
||||
revive:
|
||||
# revive is more configurable than static check, so likely the preferred alternative to static-check
|
||||
# (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997)
|
||||
enable-all-rules:
|
||||
true
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
|
||||
rules:
|
||||
# rules with required arguments
|
||||
- name: argument-limit
|
||||
disabled: true
|
||||
- name: banned-characters
|
||||
disabled: true
|
||||
- name: cognitive-complexity
|
||||
disabled: true
|
||||
- name: cyclomatic
|
||||
disabled: true
|
||||
- name: file-header
|
||||
disabled: true
|
||||
- name: function-length
|
||||
disabled: true
|
||||
- name: function-result-limit
|
||||
disabled: true
|
||||
- name: max-public-structs
|
||||
disabled: true
|
||||
# geneally annoying rules
|
||||
- name: add-constant # complains about any and all strings and integers
|
||||
disabled: true
|
||||
- name: confusing-naming # we frequently use "Foo()" and "foo()" together
|
||||
disabled: true
|
||||
- name: flag-parameter # excessive, and a common idiom we use
|
||||
disabled: true
|
||||
- name: unhandled-error # warns over common fmt.Print* and io.Close; rely on errcheck instead
|
||||
disabled: true
|
||||
# general config
|
||||
- name: line-length-limit
|
||||
arguments:
|
||||
- 140
|
||||
- name: var-naming
|
||||
arguments:
|
||||
- []
|
||||
- - CID
|
||||
- CRI
|
||||
- CTRD
|
||||
- DACL
|
||||
- DLL
|
||||
- DOS
|
||||
- ETW
|
||||
- FSCTL
|
||||
- GCS
|
||||
- GMSA
|
||||
- HCS
|
||||
- HV
|
||||
- IO
|
||||
- LCOW
|
||||
- LDAP
|
||||
- LPAC
|
||||
- LTSC
|
||||
- MMIO
|
||||
- NT
|
||||
- OCI
|
||||
- PMEM
|
||||
- PWSH
|
||||
- RX
|
||||
- SACl
|
||||
- SID
|
||||
- SMB
|
||||
- TX
|
||||
- VHD
|
||||
- VHDX
|
||||
- VMID
|
||||
- VPCI
|
||||
- WCOW
|
||||
- WIM
|
||||
74
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
74
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
@@ -13,16 +13,60 @@ Please see the LICENSE file for licensing information.
|
||||
|
||||
## Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA)
|
||||
declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
|
||||
This project welcomes contributions and suggestions.
|
||||
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that
|
||||
you have the right to, and actually do, grant us the rights to use your contribution.
|
||||
For details, visit [Microsoft CLA](https://cla.microsoft.com).
|
||||
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR
|
||||
appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether you need to
|
||||
provide a CLA and decorate the PR appropriately (e.g., label, comment).
|
||||
Simply follow the instructions provided by the bot.
|
||||
You will only need to do this once across all repos using our CLA.
|
||||
|
||||
We also require that contributors sign their commits using git commit -s or git commit --signoff to certify they either authored the work themselves
|
||||
or otherwise have permission to use it in this project. Please see https://developercertificate.org/ for more info, as well as to make sure that you can
|
||||
attest to the rules listed. Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
|
||||
Additionally, the pull request pipeline requires the following steps to be performed before
|
||||
mergining.
|
||||
|
||||
### Code Sign-Off
|
||||
|
||||
We require that contributors sign their commits using [`git commit --signoff`][git-commit-s]
|
||||
to certify they either authored the work themselves or otherwise have permission to use it in this project.
|
||||
|
||||
A range of commits can be signed off using [`git rebase --signoff`][git-rebase-s].
|
||||
|
||||
Please see [the developer certificate](https://developercertificate.org) for more info,
|
||||
as well as to make sure that you can attest to the rules listed.
|
||||
Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
|
||||
|
||||
### Linting
|
||||
|
||||
Code must pass a linting stage, which uses [`golangci-lint`][lint].
|
||||
The linting settings are stored in [`.golangci.yaml`](./.golangci.yaml), and can be run
|
||||
automatically with VSCode by adding the following to your workspace or folder settings:
|
||||
|
||||
```json
|
||||
"go.lintTool": "golangci-lint",
|
||||
"go.lintOnSave": "package",
|
||||
```
|
||||
|
||||
Additional editor [integrations options are also available][lint-ide].
|
||||
|
||||
Alternatively, `golangci-lint` can be [installed locally][lint-install] and run from the repo root:
|
||||
|
||||
```shell
|
||||
# use . or specify a path to only lint a package
|
||||
# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0"
|
||||
> golangci-lint run ./...
|
||||
```
|
||||
|
||||
### Go Generate
|
||||
|
||||
The pipeline checks that auto-generated code, via `go generate`, are up to date.
|
||||
|
||||
This can be done for the entire repo:
|
||||
|
||||
```shell
|
||||
> go generate ./...
|
||||
```
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
@@ -30,8 +74,16 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
|
||||
|
||||
## Special Thanks
|
||||
Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
|
||||
for another named pipe implementation.
|
||||
|
||||
Thanks to [natefinch][natefinch] for the inspiration for this library.
|
||||
See [npipe](https://github.com/natefinch/npipe) for another named pipe implementation.
|
||||
|
||||
[lint]: https://golangci-lint.run/
|
||||
[lint-ide]: https://golangci-lint.run/usage/integrations/#editor-integration
|
||||
[lint-install]: https://golangci-lint.run/usage/install/#local-installation
|
||||
|
||||
[git-commit-s]: https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s
|
||||
[git-rebase-s]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---signoff
|
||||
|
||||
[natefinch]: https://github.com/natefinch
|
||||
|
||||
41
vendor/github.com/Microsoft/go-winio/SECURITY.md
generated
vendored
Normal file
41
vendor/github.com/Microsoft/go-winio/SECURITY.md
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
||||
48
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
48
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
@@ -7,11 +8,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
|
||||
@@ -24,7 +26,7 @@ const (
|
||||
BackupAlternateData
|
||||
BackupLink
|
||||
BackupPropertyData
|
||||
BackupObjectId
|
||||
BackupObjectId //revive:disable-line:var-naming ID, not Id
|
||||
BackupReparseData
|
||||
BackupSparseBlock
|
||||
BackupTxfsData
|
||||
@@ -34,14 +36,16 @@ const (
|
||||
StreamSparseAttributes = uint32(8)
|
||||
)
|
||||
|
||||
//nolint:revive // var-naming: ALL_CAPS
|
||||
const (
|
||||
WRITE_DAC = 0x40000
|
||||
WRITE_OWNER = 0x80000
|
||||
ACCESS_SYSTEM_SECURITY = 0x1000000
|
||||
WRITE_DAC = windows.WRITE_DAC
|
||||
WRITE_OWNER = windows.WRITE_OWNER
|
||||
ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY
|
||||
)
|
||||
|
||||
// BackupHeader represents a backup stream of a file.
|
||||
type BackupHeader struct {
|
||||
//revive:disable-next-line:var-naming ID, not Id
|
||||
Id uint32 // The backup stream ID
|
||||
Attributes uint32 // Stream attributes
|
||||
Size int64 // The size of the stream in bytes
|
||||
@@ -49,8 +53,8 @@ type BackupHeader struct {
|
||||
Offset int64 // The offset of the stream in the file (for BackupSparseBlock only).
|
||||
}
|
||||
|
||||
type win32StreamId struct {
|
||||
StreamId uint32
|
||||
type win32StreamID struct {
|
||||
StreamID uint32
|
||||
Attributes uint32
|
||||
Size uint64
|
||||
NameSize uint32
|
||||
@@ -71,7 +75,7 @@ func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
|
||||
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
|
||||
// it was not completely read.
|
||||
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
||||
if r.bytesLeft > 0 {
|
||||
if r.bytesLeft > 0 { //nolint:nestif // todo: flatten this
|
||||
if s, ok := r.r.(io.Seeker); ok {
|
||||
// Make sure Seek on io.SeekCurrent sometimes succeeds
|
||||
// before trying the actual seek.
|
||||
@@ -82,16 +86,16 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
||||
r.bytesLeft = 0
|
||||
}
|
||||
}
|
||||
if _, err := io.Copy(ioutil.Discard, r); err != nil {
|
||||
if _, err := io.Copy(io.Discard, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var wsi win32StreamId
|
||||
var wsi win32StreamID
|
||||
if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr := &BackupHeader{
|
||||
Id: wsi.StreamId,
|
||||
Id: wsi.StreamID,
|
||||
Attributes: wsi.Attributes,
|
||||
Size: int64(wsi.Size),
|
||||
}
|
||||
@@ -102,7 +106,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
||||
}
|
||||
hdr.Name = syscall.UTF16ToString(name)
|
||||
}
|
||||
if wsi.StreamId == BackupSparseBlock {
|
||||
if wsi.StreamID == BackupSparseBlock {
|
||||
if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -147,8 +151,8 @@ func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
|
||||
return fmt.Errorf("missing %d bytes", w.bytesLeft)
|
||||
}
|
||||
name := utf16.Encode([]rune(hdr.Name))
|
||||
wsi := win32StreamId{
|
||||
StreamId: hdr.Id,
|
||||
wsi := win32StreamID{
|
||||
StreamID: hdr.Id,
|
||||
Attributes: hdr.Attributes,
|
||||
Size: uint64(hdr.Size),
|
||||
NameSize: uint32(len(name) * 2),
|
||||
@@ -203,7 +207,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
|
||||
var bytesRead uint32
|
||||
err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{"BackupRead", r.f.Name(), err}
|
||||
return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(r.f)
|
||||
if bytesRead == 0 {
|
||||
@@ -216,7 +220,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) {
|
||||
// the underlying file.
|
||||
func (r *BackupFileReader) Close() error {
|
||||
if r.ctx != 0 {
|
||||
backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
|
||||
_ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
|
||||
runtime.KeepAlive(r.f)
|
||||
r.ctx = 0
|
||||
}
|
||||
@@ -242,7 +246,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
|
||||
var bytesWritten uint32
|
||||
err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
|
||||
return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(w.f)
|
||||
if int(bytesWritten) != len(b) {
|
||||
@@ -255,7 +259,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) {
|
||||
// close the underlying file.
|
||||
func (w *BackupFileWriter) Close() error {
|
||||
if w.ctx != 0 {
|
||||
backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
|
||||
_ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
|
||||
runtime.KeepAlive(w.f)
|
||||
w.ctx = 0
|
||||
}
|
||||
@@ -271,7 +275,13 @@ func OpenForBackup(path string, access uint32, share uint32, createmode uint32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0)
|
||||
h, err := syscall.CreateFile(&winPath[0],
|
||||
access,
|
||||
share,
|
||||
nil,
|
||||
createmode,
|
||||
syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
0)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "open", Path: path, Err: err}
|
||||
return nil, err
|
||||
|
||||
22
vendor/github.com/Microsoft/go-winio/doc.go
generated
vendored
Normal file
22
vendor/github.com/Microsoft/go-winio/doc.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// This package provides utilities for efficiently performing Win32 IO operations in Go.
|
||||
// Currently, this package is provides support for genreal IO and management of
|
||||
// - named pipes
|
||||
// - files
|
||||
// - [Hyper-V sockets]
|
||||
//
|
||||
// This code is similar to Go's [net] package, and uses IO completion ports to avoid
|
||||
// blocking IO on system threads, allowing Go to reuse the thread to schedule other goroutines.
|
||||
//
|
||||
// This limits support to Windows Vista and newer operating systems.
|
||||
//
|
||||
// Additionally, this package provides support for:
|
||||
// - creating and managing GUIDs
|
||||
// - writing to [ETW]
|
||||
// - opening and manageing VHDs
|
||||
// - parsing [Windows Image files]
|
||||
// - auto-generating Win32 API code
|
||||
//
|
||||
// [Hyper-V sockets]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service
|
||||
// [ETW]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-
|
||||
// [Windows Image files]: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/work-with-windows-images
|
||||
package winio
|
||||
8
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
8
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
@@ -33,7 +33,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
||||
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
|
||||
if err != nil {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
return ea, nb, err
|
||||
}
|
||||
|
||||
nameOffset := fileFullEaInformationSize
|
||||
@@ -43,7 +43,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
||||
nextOffset := int(info.NextEntryOffset)
|
||||
if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
return ea, nb, err
|
||||
}
|
||||
|
||||
ea.Name = string(b[nameOffset : nameOffset+nameLen])
|
||||
@@ -52,7 +52,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
||||
if info.NextEntryOffset != 0 {
|
||||
nb = b[info.NextEntryOffset:]
|
||||
}
|
||||
return
|
||||
return ea, nb, err
|
||||
}
|
||||
|
||||
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
|
||||
@@ -67,7 +67,7 @@ func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
|
||||
eas = append(eas, ea)
|
||||
b = nb
|
||||
}
|
||||
return
|
||||
return eas, err
|
||||
}
|
||||
|
||||
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
|
||||
|
||||
66
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
66
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
@@ -11,6 +11,8 @@ import (
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
|
||||
@@ -24,6 +26,8 @@ type atomicBool int32
|
||||
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
|
||||
func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
|
||||
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
|
||||
|
||||
//revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg
|
||||
func (b *atomicBool) swap(new bool) bool {
|
||||
var newInt int32
|
||||
if new {
|
||||
@@ -32,11 +36,6 @@ func (b *atomicBool) swap(new bool) bool {
|
||||
return atomic.SwapInt32((*int32)(b), newInt) == 1
|
||||
}
|
||||
|
||||
const (
|
||||
cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
|
||||
cFILE_SKIP_SET_EVENT_ON_HANDLE = 2
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFileClosed = errors.New("file has already been closed")
|
||||
ErrTimeout = &timeoutError{}
|
||||
@@ -44,28 +43,28 @@ var (
|
||||
|
||||
type timeoutError struct{}
|
||||
|
||||
func (e *timeoutError) Error() string { return "i/o timeout" }
|
||||
func (e *timeoutError) Timeout() bool { return true }
|
||||
func (e *timeoutError) Temporary() bool { return true }
|
||||
func (*timeoutError) Error() string { return "i/o timeout" }
|
||||
func (*timeoutError) Timeout() bool { return true }
|
||||
func (*timeoutError) Temporary() bool { return true }
|
||||
|
||||
type timeoutChan chan struct{}
|
||||
|
||||
var ioInitOnce sync.Once
|
||||
var ioCompletionPort syscall.Handle
|
||||
|
||||
// ioResult contains the result of an asynchronous IO operation
|
||||
// ioResult contains the result of an asynchronous IO operation.
|
||||
type ioResult struct {
|
||||
bytes uint32
|
||||
err error
|
||||
}
|
||||
|
||||
// ioOperation represents an outstanding asynchronous Win32 IO
|
||||
// ioOperation represents an outstanding asynchronous Win32 IO.
|
||||
type ioOperation struct {
|
||||
o syscall.Overlapped
|
||||
ch chan ioResult
|
||||
}
|
||||
|
||||
func initIo() {
|
||||
func initIO() {
|
||||
h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -94,15 +93,15 @@ type deadlineHandler struct {
|
||||
timedout atomicBool
|
||||
}
|
||||
|
||||
// makeWin32File makes a new win32File from an existing file handle
|
||||
// makeWin32File makes a new win32File from an existing file handle.
|
||||
func makeWin32File(h syscall.Handle) (*win32File, error) {
|
||||
f := &win32File{handle: h}
|
||||
ioInitOnce.Do(initIo)
|
||||
ioInitOnce.Do(initIO)
|
||||
_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
|
||||
err = setFileCompletionNotificationModes(h, windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS|windows.FILE_SKIP_SET_EVENT_ON_HANDLE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -121,14 +120,14 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// closeHandle closes the resources associated with a Win32 handle
|
||||
// closeHandle closes the resources associated with a Win32 handle.
|
||||
func (f *win32File) closeHandle() {
|
||||
f.wgLock.Lock()
|
||||
// Atomically set that we are closing, releasing the resources only once.
|
||||
if !f.closing.swap(true) {
|
||||
f.wgLock.Unlock()
|
||||
// cancel all IO and wait for it to complete
|
||||
cancelIoEx(f.handle, nil)
|
||||
_ = cancelIoEx(f.handle, nil)
|
||||
f.wg.Wait()
|
||||
// at this point, no new IO can start
|
||||
syscall.Close(f.handle)
|
||||
@@ -144,14 +143,14 @@ func (f *win32File) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsClosed checks if the file has been closed
|
||||
// IsClosed checks if the file has been closed.
|
||||
func (f *win32File) IsClosed() bool {
|
||||
return f.closing.isSet()
|
||||
}
|
||||
|
||||
// prepareIo prepares for a new IO operation.
|
||||
// prepareIO prepares for a new IO operation.
|
||||
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
|
||||
func (f *win32File) prepareIo() (*ioOperation, error) {
|
||||
func (f *win32File) prepareIO() (*ioOperation, error) {
|
||||
f.wgLock.RLock()
|
||||
if f.closing.isSet() {
|
||||
f.wgLock.RUnlock()
|
||||
@@ -164,7 +163,7 @@ func (f *win32File) prepareIo() (*ioOperation, error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// ioCompletionProcessor processes completed async IOs forever
|
||||
// ioCompletionProcessor processes completed async IOs forever.
|
||||
func ioCompletionProcessor(h syscall.Handle) {
|
||||
for {
|
||||
var bytes uint32
|
||||
@@ -178,15 +177,17 @@ func ioCompletionProcessor(h syscall.Handle) {
|
||||
}
|
||||
}
|
||||
|
||||
// asyncIo processes the return value from ReadFile or WriteFile, blocking until
|
||||
// todo: helsaawy - create an asyncIO version that takes a context
|
||||
|
||||
// asyncIO processes the return value from ReadFile or WriteFile, blocking until
|
||||
// the operation has actually completed.
|
||||
func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
|
||||
if err != syscall.ERROR_IO_PENDING {
|
||||
func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
|
||||
if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno
|
||||
return int(bytes), err
|
||||
}
|
||||
|
||||
if f.closing.isSet() {
|
||||
cancelIoEx(f.handle, &c.o)
|
||||
_ = cancelIoEx(f.handle, &c.o)
|
||||
}
|
||||
|
||||
var timeout timeoutChan
|
||||
@@ -200,7 +201,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
||||
select {
|
||||
case r = <-c.ch:
|
||||
err = r.err
|
||||
if err == syscall.ERROR_OPERATION_ABORTED {
|
||||
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||
if f.closing.isSet() {
|
||||
err = ErrFileClosed
|
||||
}
|
||||
@@ -210,10 +211,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
||||
err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
|
||||
}
|
||||
case <-timeout:
|
||||
cancelIoEx(f.handle, &c.o)
|
||||
_ = cancelIoEx(f.handle, &c.o)
|
||||
r = <-c.ch
|
||||
err = r.err
|
||||
if err == syscall.ERROR_OPERATION_ABORTED {
|
||||
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
|
||||
err = ErrTimeout
|
||||
}
|
||||
}
|
||||
@@ -221,13 +222,14 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
||||
// runtime.KeepAlive is needed, as c is passed via native
|
||||
// code to ioCompletionProcessor, c must remain alive
|
||||
// until the channel read is complete.
|
||||
// todo: (de)allocate *ioOperation via win32 heap functions, instead of needing to KeepAlive?
|
||||
runtime.KeepAlive(c)
|
||||
return int(r.bytes), err
|
||||
}
|
||||
|
||||
// Read reads from a file handle.
|
||||
func (f *win32File) Read(b []byte) (int, error) {
|
||||
c, err := f.prepareIo()
|
||||
c, err := f.prepareIO()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -239,13 +241,13 @@ func (f *win32File) Read(b []byte) (int, error) {
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
|
||||
n, err := f.asyncIo(c, &f.readDeadline, bytes, err)
|
||||
n, err := f.asyncIO(c, &f.readDeadline, bytes, err)
|
||||
runtime.KeepAlive(b)
|
||||
|
||||
// Handle EOF conditions.
|
||||
if err == nil && n == 0 && len(b) != 0 {
|
||||
return 0, io.EOF
|
||||
} else if err == syscall.ERROR_BROKEN_PIPE {
|
||||
} else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno
|
||||
return 0, io.EOF
|
||||
} else {
|
||||
return n, err
|
||||
@@ -254,7 +256,7 @@ func (f *win32File) Read(b []byte) (int, error) {
|
||||
|
||||
// Write writes to a file handle.
|
||||
func (f *win32File) Write(b []byte) (int, error) {
|
||||
c, err := f.prepareIo()
|
||||
c, err := f.prepareIO()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -266,7 +268,7 @@ func (f *win32File) Write(b []byte) (int, error) {
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
|
||||
n, err := f.asyncIo(c, &f.writeDeadline, bytes, err)
|
||||
n, err := f.asyncIO(c, &f.writeDeadline, bytes, err)
|
||||
runtime.KeepAlive(b)
|
||||
return n, err
|
||||
}
|
||||
|
||||
29
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
29
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
@@ -14,13 +15,18 @@ import (
|
||||
type FileBasicInfo struct {
|
||||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
|
||||
FileAttributes uint32
|
||||
pad uint32 // padding
|
||||
_ uint32 // padding
|
||||
}
|
||||
|
||||
// GetFileBasicInfo retrieves times and attributes for a file.
|
||||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
||||
bi := &FileBasicInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
if err := windows.GetFileInformationByHandleEx(
|
||||
windows.Handle(f.Fd()),
|
||||
windows.FileBasicInfo,
|
||||
(*byte)(unsafe.Pointer(bi)),
|
||||
uint32(unsafe.Sizeof(*bi)),
|
||||
); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
@@ -29,7 +35,12 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
||||
|
||||
// SetFileBasicInfo sets times and attributes for a file.
|
||||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
|
||||
if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
if err := windows.SetFileInformationByHandle(
|
||||
windows.Handle(f.Fd()),
|
||||
windows.FileBasicInfo,
|
||||
(*byte)(unsafe.Pointer(bi)),
|
||||
uint32(unsafe.Sizeof(*bi)),
|
||||
); err != nil {
|
||||
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
@@ -48,7 +59,10 @@ type FileStandardInfo struct {
|
||||
// GetFileStandardInfo retrieves ended information for the file.
|
||||
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
|
||||
si := &FileStandardInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil {
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()),
|
||||
windows.FileStandardInfo,
|
||||
(*byte)(unsafe.Pointer(si)),
|
||||
uint32(unsafe.Sizeof(*si))); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
@@ -65,7 +79,12 @@ type FileIDInfo struct {
|
||||
// GetFileID retrieves the unique (volume, file ID) pair for a file.
|
||||
func GetFileID(f *os.File) (*FileIDInfo, error) {
|
||||
fileID := &FileIDInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
|
||||
if err := windows.GetFileInformationByHandleEx(
|
||||
windows.Handle(f.Fd()),
|
||||
windows.FileIdInfo,
|
||||
(*byte)(unsafe.Pointer(fileID)),
|
||||
uint32(unsafe.Sizeof(*fileID)),
|
||||
); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
|
||||
345
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
345
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
@@ -4,6 +4,8 @@
|
||||
package winio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -12,16 +14,87 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/socket"
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
)
|
||||
|
||||
//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
|
||||
const afHVSock = 34 // AF_HYPERV
|
||||
|
||||
const (
|
||||
afHvSock = 34 // AF_HYPERV
|
||||
// Well known Service and VM IDs
|
||||
// https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards
|
||||
|
||||
socketError = ^uintptr(0)
|
||||
)
|
||||
// HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions.
|
||||
func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000
|
||||
return guid.GUID{}
|
||||
}
|
||||
|
||||
// HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions.
|
||||
func HvsockGUIDBroadcast() guid.GUID { // ffffffff-ffff-ffff-ffff-ffffffffffff
|
||||
return guid.GUID{
|
||||
Data1: 0xffffffff,
|
||||
Data2: 0xffff,
|
||||
Data3: 0xffff,
|
||||
Data4: [8]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
}
|
||||
}
|
||||
|
||||
// HvsockGUIDLoopback is the Loopback VmId for accepting connections to the same partition as the connector.
|
||||
func HvsockGUIDLoopback() guid.GUID { // e0e16197-dd56-4a10-9195-5ee7a155a838
|
||||
return guid.GUID{
|
||||
Data1: 0xe0e16197,
|
||||
Data2: 0xdd56,
|
||||
Data3: 0x4a10,
|
||||
Data4: [8]uint8{0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38},
|
||||
}
|
||||
}
|
||||
|
||||
// HvsockGUIDSiloHost is the address of a silo's host partition:
|
||||
// - The silo host of a hosted silo is the utility VM.
|
||||
// - The silo host of a silo on a physical host is the physical host.
|
||||
func HvsockGUIDSiloHost() guid.GUID { // 36bd0c5c-7276-4223-88ba-7d03b654c568
|
||||
return guid.GUID{
|
||||
Data1: 0x36bd0c5c,
|
||||
Data2: 0x7276,
|
||||
Data3: 0x4223,
|
||||
Data4: [8]byte{0x88, 0xba, 0x7d, 0x03, 0xb6, 0x54, 0xc5, 0x68},
|
||||
}
|
||||
}
|
||||
|
||||
// HvsockGUIDChildren is the wildcard VmId for accepting connections from the connector's child partitions.
|
||||
func HvsockGUIDChildren() guid.GUID { // 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd
|
||||
return guid.GUID{
|
||||
Data1: 0x90db8b89,
|
||||
Data2: 0xd35,
|
||||
Data3: 0x4f79,
|
||||
Data4: [8]uint8{0x8c, 0xe9, 0x49, 0xea, 0xa, 0xc8, 0xb7, 0xcd},
|
||||
}
|
||||
}
|
||||
|
||||
// HvsockGUIDParent is the wildcard VmId for accepting connections from the connector's parent partition.
|
||||
// Listening on this VmId accepts connection from:
|
||||
// - Inside silos: silo host partition.
|
||||
// - Inside hosted silo: host of the VM.
|
||||
// - Inside VM: VM host.
|
||||
// - Physical host: Not supported.
|
||||
func HvsockGUIDParent() guid.GUID { // a42e7cda-d03f-480c-9cc2-a4de20abb878
|
||||
return guid.GUID{
|
||||
Data1: 0xa42e7cda,
|
||||
Data2: 0xd03f,
|
||||
Data3: 0x480c,
|
||||
Data4: [8]uint8{0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78},
|
||||
}
|
||||
}
|
||||
|
||||
// hvsockVsockServiceTemplate is the Service GUID used for the VSOCK protocol.
|
||||
func hvsockVsockServiceTemplate() guid.GUID { // 00000000-facb-11e6-bd58-64006a7986d3
|
||||
return guid.GUID{
|
||||
Data2: 0xfacb,
|
||||
Data3: 0x11e6,
|
||||
Data4: [8]uint8{0xbd, 0x58, 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3},
|
||||
}
|
||||
}
|
||||
|
||||
// An HvsockAddr is an address for a AF_HYPERV socket.
|
||||
type HvsockAddr struct {
|
||||
@@ -36,8 +109,10 @@ type rawHvsockAddr struct {
|
||||
ServiceID guid.GUID
|
||||
}
|
||||
|
||||
var _ socket.RawSockaddr = &rawHvsockAddr{}
|
||||
|
||||
// Network returns the address's network name, "hvsock".
|
||||
func (addr *HvsockAddr) Network() string {
|
||||
func (*HvsockAddr) Network() string {
|
||||
return "hvsock"
|
||||
}
|
||||
|
||||
@@ -47,14 +122,14 @@ func (addr *HvsockAddr) String() string {
|
||||
|
||||
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
|
||||
func VsockServiceID(port uint32) guid.GUID {
|
||||
g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
|
||||
g := hvsockVsockServiceTemplate() // make a copy
|
||||
g.Data1 = port
|
||||
return g
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) raw() rawHvsockAddr {
|
||||
return rawHvsockAddr{
|
||||
Family: afHvSock,
|
||||
Family: afHVSock,
|
||||
VMID: addr.VMID,
|
||||
ServiceID: addr.ServiceID,
|
||||
}
|
||||
@@ -65,20 +140,48 @@ func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
|
||||
addr.ServiceID = raw.ServiceID
|
||||
}
|
||||
|
||||
// Sockaddr returns a pointer to and the size of this struct.
|
||||
//
|
||||
// Implements the [socket.RawSockaddr] interface, and allows use in
|
||||
// [socket.Bind] and [socket.ConnectEx].
|
||||
func (r *rawHvsockAddr) Sockaddr() (unsafe.Pointer, int32, error) {
|
||||
return unsafe.Pointer(r), int32(unsafe.Sizeof(rawHvsockAddr{})), nil
|
||||
}
|
||||
|
||||
// Sockaddr interface allows use with `sockets.Bind()` and `.ConnectEx()`.
|
||||
func (r *rawHvsockAddr) FromBytes(b []byte) error {
|
||||
n := int(unsafe.Sizeof(rawHvsockAddr{}))
|
||||
|
||||
if len(b) < n {
|
||||
return fmt.Errorf("got %d, want %d: %w", len(b), n, socket.ErrBufferSize)
|
||||
}
|
||||
|
||||
copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), b[:n])
|
||||
if r.Family != afHVSock {
|
||||
return fmt.Errorf("got %d, want %d: %w", r.Family, afHVSock, socket.ErrAddrFamily)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HvsockListener is a socket listener for the AF_HYPERV address family.
|
||||
type HvsockListener struct {
|
||||
sock *win32File
|
||||
addr HvsockAddr
|
||||
}
|
||||
|
||||
var _ net.Listener = &HvsockListener{}
|
||||
|
||||
// HvsockConn is a connected socket of the AF_HYPERV address family.
|
||||
type HvsockConn struct {
|
||||
sock *win32File
|
||||
local, remote HvsockAddr
|
||||
}
|
||||
|
||||
func newHvSocket() (*win32File, error) {
|
||||
fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
|
||||
var _ net.Conn = &HvsockConn{}
|
||||
|
||||
func newHVSocket() (*win32File, error) {
|
||||
fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
@@ -94,12 +197,12 @@ func newHvSocket() (*win32File, error) {
|
||||
// ListenHvsock listens for connections on the specified hvsock address.
|
||||
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
|
||||
l := &HvsockListener{addr: *addr}
|
||||
sock, err := newHvSocket()
|
||||
sock, err := newHVSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", err)
|
||||
}
|
||||
sa := addr.raw()
|
||||
err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
|
||||
err = socket.Bind(windows.Handle(sock.handle), &sa)
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
|
||||
}
|
||||
@@ -121,7 +224,7 @@ func (l *HvsockListener) Addr() net.Addr {
|
||||
|
||||
// Accept waits for the next connection and returns it.
|
||||
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
sock, err := newHvSocket()
|
||||
sock, err := newHVSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
@@ -130,27 +233,42 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := l.sock.prepareIo()
|
||||
c, err := l.sock.prepareIO()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
defer l.sock.wg.Done()
|
||||
|
||||
// AcceptEx, per documentation, requires an extra 16 bytes per address.
|
||||
//
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
|
||||
const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
|
||||
var addrbuf [addrlen * 2]byte
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
|
||||
_, err = l.sock.asyncIo(c, nil, bytes, err)
|
||||
if err != nil {
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o)
|
||||
if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil {
|
||||
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
||||
}
|
||||
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
}
|
||||
// The local address returned in the AcceptEx buffer is the same as the Listener socket's
|
||||
// address. However, the service GUID reported by GetSockName is different from the Listeners
|
||||
// socket, and is sometimes the same as the local address of the socket that dialed the
|
||||
// address, with the service GUID.Data1 incremented, but othertimes is different.
|
||||
// todo: does the local address matter? is the listener's address or the actual address appropriate?
|
||||
conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
|
||||
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
|
||||
|
||||
// initialize the accepted socket and update its properties with those of the listening socket
|
||||
if err = windows.Setsockopt(windows.Handle(sock.handle),
|
||||
windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT,
|
||||
(*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil {
|
||||
return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err))
|
||||
}
|
||||
|
||||
sock = nil
|
||||
return conn, nil
|
||||
}
|
||||
@@ -160,43 +278,171 @@ func (l *HvsockListener) Close() error {
|
||||
return l.sock.Close()
|
||||
}
|
||||
|
||||
/* Need to finish ConnectEx handling
|
||||
func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
|
||||
sock, err := newHvSocket()
|
||||
// HvsockDialer configures and dials a Hyper-V Socket (ie, [HvsockConn]).
|
||||
type HvsockDialer struct {
|
||||
// Deadline is the time the Dial operation must connect before erroring.
|
||||
Deadline time.Time
|
||||
|
||||
// Retries is the number of additional connects to try if the connection times out, is refused,
|
||||
// or the host is unreachable
|
||||
Retries uint
|
||||
|
||||
// RetryWait is the time to wait after a connection error to retry
|
||||
RetryWait time.Duration
|
||||
|
||||
rt *time.Timer // redial wait timer
|
||||
}
|
||||
|
||||
// Dial the Hyper-V socket at addr.
|
||||
//
|
||||
// See [HvsockDialer.Dial] for more information.
|
||||
func Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
|
||||
return (&HvsockDialer{}).Dial(ctx, addr)
|
||||
}
|
||||
|
||||
// Dial attempts to connect to the Hyper-V socket at addr, and returns a connection if successful.
|
||||
// Will attempt (HvsockDialer).Retries if dialing fails, waiting (HvsockDialer).RetryWait between
|
||||
// retries.
|
||||
//
|
||||
// Dialing can be cancelled either by providing (HvsockDialer).Deadline, or cancelling ctx.
|
||||
func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
|
||||
op := "dial"
|
||||
// create the conn early to use opErr()
|
||||
conn = &HvsockConn{
|
||||
remote: *addr,
|
||||
}
|
||||
|
||||
if !d.Deadline.IsZero() {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithDeadline(ctx, d.Deadline)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
// preemptive timeout/cancellation check
|
||||
if err = ctx.Err(); err != nil {
|
||||
return nil, conn.opErr(op, err)
|
||||
}
|
||||
|
||||
sock, err := newHVSocket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, conn.opErr(op, err)
|
||||
}
|
||||
defer func() {
|
||||
if sock != nil {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := sock.prepareIo()
|
||||
|
||||
sa := addr.raw()
|
||||
err = socket.Bind(windows.Handle(sock.handle), &sa)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, conn.opErr(op, os.NewSyscallError("bind", err))
|
||||
}
|
||||
|
||||
c, err := sock.prepareIO()
|
||||
if err != nil {
|
||||
return nil, conn.opErr(op, err)
|
||||
}
|
||||
defer sock.wg.Done()
|
||||
var bytes uint32
|
||||
err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
|
||||
_, err = sock.asyncIo(ctx, c, nil, bytes, err)
|
||||
for i := uint(0); i <= d.Retries; i++ {
|
||||
err = socket.ConnectEx(
|
||||
windows.Handle(sock.handle),
|
||||
&sa,
|
||||
nil, // sendBuf
|
||||
0, // sendDataLen
|
||||
&bytes,
|
||||
(*windows.Overlapped)(unsafe.Pointer(&c.o)))
|
||||
_, err = sock.asyncIO(c, nil, bytes, err)
|
||||
if i < d.Retries && canRedial(err) {
|
||||
if err = d.redialWait(ctx); err == nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, conn.opErr(op, os.NewSyscallError("connectex", err))
|
||||
}
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
remote: *addr,
|
||||
|
||||
// update the connection properties, so shutdown can be used
|
||||
if err = windows.Setsockopt(
|
||||
windows.Handle(sock.handle),
|
||||
windows.SOL_SOCKET,
|
||||
windows.SO_UPDATE_CONNECT_CONTEXT,
|
||||
nil, // optvalue
|
||||
0, // optlen
|
||||
); err != nil {
|
||||
return nil, conn.opErr(op, os.NewSyscallError("setsockopt", err))
|
||||
}
|
||||
|
||||
// get the local name
|
||||
var sal rawHvsockAddr
|
||||
err = socket.GetSockName(windows.Handle(sock.handle), &sal)
|
||||
if err != nil {
|
||||
return nil, conn.opErr(op, os.NewSyscallError("getsockname", err))
|
||||
}
|
||||
conn.local.fromRaw(&sal)
|
||||
|
||||
// one last check for timeout, since asyncIO doesn't check the context
|
||||
if err = ctx.Err(); err != nil {
|
||||
return nil, conn.opErr(op, err)
|
||||
}
|
||||
|
||||
conn.sock = sock
|
||||
sock = nil
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
*/
|
||||
|
||||
// redialWait waits before attempting to redial, resetting the timer as appropriate.
|
||||
func (d *HvsockDialer) redialWait(ctx context.Context) (err error) {
|
||||
if d.RetryWait == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.rt == nil {
|
||||
d.rt = time.NewTimer(d.RetryWait)
|
||||
} else {
|
||||
// should already be stopped and drained
|
||||
d.rt.Reset(d.RetryWait)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-d.rt.C:
|
||||
return nil
|
||||
}
|
||||
|
||||
// stop and drain the timer
|
||||
if !d.rt.Stop() {
|
||||
<-d.rt.C
|
||||
}
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
// assumes error is a plain, unwrapped syscall.Errno provided by direct syscall.
|
||||
func canRedial(err error) bool {
|
||||
//nolint:errorlint // guaranteed to be an Errno
|
||||
switch err {
|
||||
case windows.WSAECONNREFUSED, windows.WSAENETUNREACH, windows.WSAETIMEDOUT,
|
||||
windows.ERROR_CONNECTION_REFUSED, windows.ERROR_CONNECTION_UNAVAIL:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) opErr(op string, err error) error {
|
||||
// translate from "file closed" to "socket closed"
|
||||
if errors.Is(err, ErrFileClosed) {
|
||||
err = socket.ErrSocketClosed
|
||||
}
|
||||
return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) Read(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
c, err := conn.sock.prepareIO()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("read", err)
|
||||
}
|
||||
@@ -204,10 +450,11 @@ func (conn *HvsockConn) Read(b []byte) (int, error) {
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var flags, bytes uint32
|
||||
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
|
||||
n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsarecv", err)
|
||||
var eno windows.Errno
|
||||
if errors.As(err, &eno) {
|
||||
err = os.NewSyscallError("wsarecv", eno)
|
||||
}
|
||||
return 0, conn.opErr("read", err)
|
||||
} else if n == 0 {
|
||||
@@ -230,7 +477,7 @@ func (conn *HvsockConn) Write(b []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) write(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
c, err := conn.sock.prepareIO()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
@@ -238,10 +485,11 @@ func (conn *HvsockConn) write(b []byte) (int, error) {
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var bytes uint32
|
||||
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
|
||||
n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsasend", err)
|
||||
var eno windows.Errno
|
||||
if errors.As(err, &eno) {
|
||||
err = os.NewSyscallError("wsasend", eno)
|
||||
}
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
@@ -257,13 +505,19 @@ func (conn *HvsockConn) IsClosed() bool {
|
||||
return conn.sock.IsClosed()
|
||||
}
|
||||
|
||||
// shutdown disables sending or receiving on a socket.
|
||||
func (conn *HvsockConn) shutdown(how int) error {
|
||||
if conn.IsClosed() {
|
||||
return ErrFileClosed
|
||||
return socket.ErrSocketClosed
|
||||
}
|
||||
|
||||
err := syscall.Shutdown(conn.sock.handle, how)
|
||||
if err != nil {
|
||||
// If the connection was closed, shutdowns fail with "not connected"
|
||||
if errors.Is(err, windows.WSAENOTCONN) ||
|
||||
errors.Is(err, windows.WSAESHUTDOWN) {
|
||||
err = socket.ErrSocketClosed
|
||||
}
|
||||
return os.NewSyscallError("shutdown", err)
|
||||
}
|
||||
return nil
|
||||
@@ -273,7 +527,7 @@ func (conn *HvsockConn) shutdown(how int) error {
|
||||
func (conn *HvsockConn) CloseRead() error {
|
||||
err := conn.shutdown(syscall.SHUT_RD)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
return conn.opErr("closeread", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -283,7 +537,7 @@ func (conn *HvsockConn) CloseRead() error {
|
||||
func (conn *HvsockConn) CloseWrite() error {
|
||||
err := conn.shutdown(syscall.SHUT_WR)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
return conn.opErr("closewrite", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -300,8 +554,13 @@ func (conn *HvsockConn) RemoteAddr() net.Addr {
|
||||
|
||||
// SetDeadline implements the net.Conn SetDeadline method.
|
||||
func (conn *HvsockConn) SetDeadline(t time.Time) error {
|
||||
conn.SetReadDeadline(t)
|
||||
conn.SetWriteDeadline(t)
|
||||
// todo: implement `SetDeadline` for `win32File`
|
||||
if err := conn.SetReadDeadline(t); err != nil {
|
||||
return fmt.Errorf("set read deadline: %w", err)
|
||||
}
|
||||
if err := conn.SetWriteDeadline(t); err != nil {
|
||||
return fmt.Errorf("set write deadline: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/Microsoft/go-winio/internal/fs/doc.go
generated
vendored
Normal file
2
vendor/github.com/Microsoft/go-winio/internal/fs/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// This package contains Win32 filesystem functionality.
|
||||
package fs
|
||||
202
vendor/github.com/Microsoft/go-winio/internal/fs/fs.go
generated
vendored
Normal file
202
vendor/github.com/Microsoft/go-winio/internal/fs/fs.go
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
//go:build windows
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/stringbuffer"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW
|
||||
|
||||
const NullHandle windows.Handle = 0
|
||||
|
||||
// AccessMask defines standard, specific, and generic rights.
|
||||
//
|
||||
// Bitmask:
|
||||
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
// +---------------+---------------+-------------------------------+
|
||||
// |G|G|G|G|Resvd|A| StandardRights| SpecificRights |
|
||||
// |R|W|E|A| |S| | |
|
||||
// +-+-------------+---------------+-------------------------------+
|
||||
//
|
||||
// GR Generic Read
|
||||
// GW Generic Write
|
||||
// GE Generic Exectue
|
||||
// GA Generic All
|
||||
// Resvd Reserved
|
||||
// AS Access Security System
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants
|
||||
type AccessMask = windows.ACCESS_MASK
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
// Not actually any.
|
||||
//
|
||||
// For CreateFile: "query certain metadata such as file, directory, or device attributes without accessing that file or device"
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters
|
||||
FILE_ANY_ACCESS AccessMask = 0
|
||||
|
||||
// Specific Object Access
|
||||
// from ntioapi.h
|
||||
|
||||
FILE_READ_DATA AccessMask = (0x0001) // file & pipe
|
||||
FILE_LIST_DIRECTORY AccessMask = (0x0001) // directory
|
||||
|
||||
FILE_WRITE_DATA AccessMask = (0x0002) // file & pipe
|
||||
FILE_ADD_FILE AccessMask = (0x0002) // directory
|
||||
|
||||
FILE_APPEND_DATA AccessMask = (0x0004) // file
|
||||
FILE_ADD_SUBDIRECTORY AccessMask = (0x0004) // directory
|
||||
FILE_CREATE_PIPE_INSTANCE AccessMask = (0x0004) // named pipe
|
||||
|
||||
FILE_READ_EA AccessMask = (0x0008) // file & directory
|
||||
FILE_READ_PROPERTIES AccessMask = FILE_READ_EA
|
||||
|
||||
FILE_WRITE_EA AccessMask = (0x0010) // file & directory
|
||||
FILE_WRITE_PROPERTIES AccessMask = FILE_WRITE_EA
|
||||
|
||||
FILE_EXECUTE AccessMask = (0x0020) // file
|
||||
FILE_TRAVERSE AccessMask = (0x0020) // directory
|
||||
|
||||
FILE_DELETE_CHILD AccessMask = (0x0040) // directory
|
||||
|
||||
FILE_READ_ATTRIBUTES AccessMask = (0x0080) // all
|
||||
|
||||
FILE_WRITE_ATTRIBUTES AccessMask = (0x0100) // all
|
||||
|
||||
FILE_ALL_ACCESS AccessMask = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF)
|
||||
FILE_GENERIC_READ AccessMask = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE)
|
||||
FILE_GENERIC_WRITE AccessMask = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE)
|
||||
FILE_GENERIC_EXECUTE AccessMask = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE)
|
||||
|
||||
SPECIFIC_RIGHTS_ALL AccessMask = 0x0000FFFF
|
||||
|
||||
// Standard Access
|
||||
// from ntseapi.h
|
||||
|
||||
DELETE AccessMask = 0x0001_0000
|
||||
READ_CONTROL AccessMask = 0x0002_0000
|
||||
WRITE_DAC AccessMask = 0x0004_0000
|
||||
WRITE_OWNER AccessMask = 0x0008_0000
|
||||
SYNCHRONIZE AccessMask = 0x0010_0000
|
||||
|
||||
STANDARD_RIGHTS_REQUIRED AccessMask = 0x000F_0000
|
||||
|
||||
STANDARD_RIGHTS_READ AccessMask = READ_CONTROL
|
||||
STANDARD_RIGHTS_WRITE AccessMask = READ_CONTROL
|
||||
STANDARD_RIGHTS_EXECUTE AccessMask = READ_CONTROL
|
||||
|
||||
STANDARD_RIGHTS_ALL AccessMask = 0x001F_0000
|
||||
)
|
||||
|
||||
type FileShareMode uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
FILE_SHARE_NONE FileShareMode = 0x00
|
||||
FILE_SHARE_READ FileShareMode = 0x01
|
||||
FILE_SHARE_WRITE FileShareMode = 0x02
|
||||
FILE_SHARE_DELETE FileShareMode = 0x04
|
||||
FILE_SHARE_VALID_FLAGS FileShareMode = 0x07
|
||||
)
|
||||
|
||||
type FileCreationDisposition uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
// from winbase.h
|
||||
|
||||
CREATE_NEW FileCreationDisposition = 0x01
|
||||
CREATE_ALWAYS FileCreationDisposition = 0x02
|
||||
OPEN_EXISTING FileCreationDisposition = 0x03
|
||||
OPEN_ALWAYS FileCreationDisposition = 0x04
|
||||
TRUNCATE_EXISTING FileCreationDisposition = 0x05
|
||||
)
|
||||
|
||||
// CreateFile and co. take flags or attributes together as one parameter.
|
||||
// Define alias until we can use generics to allow both
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
|
||||
type FileFlagOrAttribute uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const ( // from winnt.h
|
||||
FILE_FLAG_WRITE_THROUGH FileFlagOrAttribute = 0x8000_0000
|
||||
FILE_FLAG_OVERLAPPED FileFlagOrAttribute = 0x4000_0000
|
||||
FILE_FLAG_NO_BUFFERING FileFlagOrAttribute = 0x2000_0000
|
||||
FILE_FLAG_RANDOM_ACCESS FileFlagOrAttribute = 0x1000_0000
|
||||
FILE_FLAG_SEQUENTIAL_SCAN FileFlagOrAttribute = 0x0800_0000
|
||||
FILE_FLAG_DELETE_ON_CLOSE FileFlagOrAttribute = 0x0400_0000
|
||||
FILE_FLAG_BACKUP_SEMANTICS FileFlagOrAttribute = 0x0200_0000
|
||||
FILE_FLAG_POSIX_SEMANTICS FileFlagOrAttribute = 0x0100_0000
|
||||
FILE_FLAG_OPEN_REPARSE_POINT FileFlagOrAttribute = 0x0020_0000
|
||||
FILE_FLAG_OPEN_NO_RECALL FileFlagOrAttribute = 0x0010_0000
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000
|
||||
)
|
||||
|
||||
type FileSQSFlag = FileFlagOrAttribute
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const ( // from winbase.h
|
||||
SECURITY_ANONYMOUS FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16)
|
||||
SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16)
|
||||
SECURITY_IMPERSONATION FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16)
|
||||
SECURITY_DELEGATION FileSQSFlag = FileSQSFlag(SecurityDelegation << 16)
|
||||
|
||||
SECURITY_SQOS_PRESENT FileSQSFlag = 0x00100000
|
||||
SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F0000
|
||||
)
|
||||
|
||||
// GetFinalPathNameByHandle flags
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew#parameters
|
||||
type GetFinalPathFlag uint32
|
||||
|
||||
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
|
||||
const (
|
||||
GetFinalPathDefaultFlag GetFinalPathFlag = 0x0
|
||||
|
||||
FILE_NAME_NORMALIZED GetFinalPathFlag = 0x0
|
||||
FILE_NAME_OPENED GetFinalPathFlag = 0x8
|
||||
|
||||
VOLUME_NAME_DOS GetFinalPathFlag = 0x0
|
||||
VOLUME_NAME_GUID GetFinalPathFlag = 0x1
|
||||
VOLUME_NAME_NT GetFinalPathFlag = 0x2
|
||||
VOLUME_NAME_NONE GetFinalPathFlag = 0x4
|
||||
)
|
||||
|
||||
// getFinalPathNameByHandle facilitates calling the Windows API GetFinalPathNameByHandle
|
||||
// with the given handle and flags. It transparently takes care of creating a buffer of the
|
||||
// correct size for the call.
|
||||
//
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
|
||||
func GetFinalPathNameByHandle(h windows.Handle, flags GetFinalPathFlag) (string, error) {
|
||||
b := stringbuffer.NewWString()
|
||||
//TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n?
|
||||
for {
|
||||
n, err := windows.GetFinalPathNameByHandle(h, b.Pointer(), b.Cap(), uint32(flags))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// If the buffer wasn't large enough, n will be the total size needed (including null terminator).
|
||||
// Resize and try again.
|
||||
if n > b.Cap() {
|
||||
b.ResizeTo(n)
|
||||
continue
|
||||
}
|
||||
// If the buffer is large enough, n will be the size not including the null terminator.
|
||||
// Convert to a Go string and return.
|
||||
return b.String(), nil
|
||||
}
|
||||
}
|
||||
12
vendor/github.com/Microsoft/go-winio/internal/fs/security.go
generated
vendored
Normal file
12
vendor/github.com/Microsoft/go-winio/internal/fs/security.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
package fs
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level
|
||||
type SecurityImpersonationLevel int32 // C default enums underlying type is `int`, which is Go `int32`
|
||||
|
||||
// Impersonation levels
|
||||
const (
|
||||
SecurityAnonymous SecurityImpersonationLevel = 0
|
||||
SecurityIdentification SecurityImpersonationLevel = 1
|
||||
SecurityImpersonation SecurityImpersonationLevel = 2
|
||||
SecurityDelegation SecurityImpersonationLevel = 3
|
||||
)
|
||||
64
vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go
generated
vendored
Normal file
64
vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//go:build windows
|
||||
|
||||
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
)
|
||||
|
||||
func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _CreateFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = windows.Handle(r0)
|
||||
if handle == windows.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
20
vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
generated
vendored
Normal file
20
vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// RawSockaddr allows structs to be used with [Bind] and [ConnectEx]. The
|
||||
// struct must meet the Win32 sockaddr requirements specified here:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2
|
||||
//
|
||||
// Specifically, the struct size must be least larger than an int16 (unsigned short)
|
||||
// for the address family.
|
||||
type RawSockaddr interface {
|
||||
// Sockaddr returns a pointer to the RawSockaddr and its struct size, allowing
|
||||
// for the RawSockaddr's data to be overwritten by syscalls (if necessary).
|
||||
//
|
||||
// It is the callers responsibility to validate that the values are valid; invalid
|
||||
// pointers or size can cause a panic.
|
||||
Sockaddr() (unsafe.Pointer, int32, error)
|
||||
}
|
||||
179
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
Normal file
179
vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
//go:build windows
|
||||
|
||||
package socket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go socket.go
|
||||
|
||||
//sys getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getsockname
|
||||
//sys getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getpeername
|
||||
//sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
|
||||
|
||||
const socketError = uintptr(^uint32(0))
|
||||
|
||||
var (
|
||||
// todo(helsaawy): create custom error types to store the desired vs actual size and addr family?
|
||||
|
||||
ErrBufferSize = errors.New("buffer size")
|
||||
ErrAddrFamily = errors.New("address family")
|
||||
ErrInvalidPointer = errors.New("invalid pointer")
|
||||
ErrSocketClosed = fmt.Errorf("socket closed: %w", net.ErrClosed)
|
||||
)
|
||||
|
||||
// todo(helsaawy): replace these with generics, ie: GetSockName[S RawSockaddr](s windows.Handle) (S, error)
|
||||
|
||||
// GetSockName writes the local address of socket s to the [RawSockaddr] rsa.
|
||||
// If rsa is not large enough, the [windows.WSAEFAULT] is returned.
|
||||
func GetSockName(s windows.Handle, rsa RawSockaddr) error {
|
||||
ptr, l, err := rsa.Sockaddr()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
|
||||
}
|
||||
|
||||
// although getsockname returns WSAEFAULT if the buffer is too small, it does not set
|
||||
// &l to the correct size, so--apart from doubling the buffer repeatedly--there is no remedy
|
||||
return getsockname(s, ptr, &l)
|
||||
}
|
||||
|
||||
// GetPeerName returns the remote address the socket is connected to.
|
||||
//
|
||||
// See [GetSockName] for more information.
|
||||
func GetPeerName(s windows.Handle, rsa RawSockaddr) error {
|
||||
ptr, l, err := rsa.Sockaddr()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
|
||||
}
|
||||
|
||||
return getpeername(s, ptr, &l)
|
||||
}
|
||||
|
||||
func Bind(s windows.Handle, rsa RawSockaddr) (err error) {
|
||||
ptr, l, err := rsa.Sockaddr()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
|
||||
}
|
||||
|
||||
return bind(s, ptr, l)
|
||||
}
|
||||
|
||||
// "golang.org/x/sys/windows".ConnectEx and .Bind only accept internal implementations of the
|
||||
// their sockaddr interface, so they cannot be used with HvsockAddr
|
||||
// Replicate functionality here from
|
||||
// https://cs.opensource.google/go/x/sys/+/master:windows/syscall_windows.go
|
||||
|
||||
// The function pointers to `AcceptEx`, `ConnectEx` and `GetAcceptExSockaddrs` must be loaded at
|
||||
// runtime via a WSAIoctl call:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/Mswsock/nc-mswsock-lpfn_connectex#remarks
|
||||
|
||||
type runtimeFunc struct {
|
||||
id guid.GUID
|
||||
once sync.Once
|
||||
addr uintptr
|
||||
err error
|
||||
}
|
||||
|
||||
func (f *runtimeFunc) Load() error {
|
||||
f.once.Do(func() {
|
||||
var s windows.Handle
|
||||
s, f.err = windows.Socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP)
|
||||
if f.err != nil {
|
||||
return
|
||||
}
|
||||
defer windows.CloseHandle(s) //nolint:errcheck
|
||||
|
||||
var n uint32
|
||||
f.err = windows.WSAIoctl(s,
|
||||
windows.SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
(*byte)(unsafe.Pointer(&f.id)),
|
||||
uint32(unsafe.Sizeof(f.id)),
|
||||
(*byte)(unsafe.Pointer(&f.addr)),
|
||||
uint32(unsafe.Sizeof(f.addr)),
|
||||
&n,
|
||||
nil, // overlapped
|
||||
0, // completionRoutine
|
||||
)
|
||||
})
|
||||
return f.err
|
||||
}
|
||||
|
||||
var (
|
||||
// todo: add `AcceptEx` and `GetAcceptExSockaddrs`
|
||||
WSAID_CONNECTEX = guid.GUID{ //revive:disable-line:var-naming ALL_CAPS
|
||||
Data1: 0x25a207b9,
|
||||
Data2: 0xddf3,
|
||||
Data3: 0x4660,
|
||||
Data4: [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e},
|
||||
}
|
||||
|
||||
connectExFunc = runtimeFunc{id: WSAID_CONNECTEX}
|
||||
)
|
||||
|
||||
func ConnectEx(
|
||||
fd windows.Handle,
|
||||
rsa RawSockaddr,
|
||||
sendBuf *byte,
|
||||
sendDataLen uint32,
|
||||
bytesSent *uint32,
|
||||
overlapped *windows.Overlapped,
|
||||
) error {
|
||||
if err := connectExFunc.Load(); err != nil {
|
||||
return fmt.Errorf("failed to load ConnectEx function pointer: %w", err)
|
||||
}
|
||||
ptr, n, err := rsa.Sockaddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
|
||||
}
|
||||
|
||||
// BOOL LpfnConnectex(
|
||||
// [in] SOCKET s,
|
||||
// [in] const sockaddr *name,
|
||||
// [in] int namelen,
|
||||
// [in, optional] PVOID lpSendBuffer,
|
||||
// [in] DWORD dwSendDataLength,
|
||||
// [out] LPDWORD lpdwBytesSent,
|
||||
// [in] LPOVERLAPPED lpOverlapped
|
||||
// )
|
||||
|
||||
func connectEx(
|
||||
s windows.Handle,
|
||||
name unsafe.Pointer,
|
||||
namelen int32,
|
||||
sendBuf *byte,
|
||||
sendDataLen uint32,
|
||||
bytesSent *uint32,
|
||||
overlapped *windows.Overlapped,
|
||||
) (err error) {
|
||||
// todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN
|
||||
r1, _, e1 := syscall.Syscall9(connectExFunc.addr,
|
||||
7,
|
||||
uintptr(s),
|
||||
uintptr(name),
|
||||
uintptr(namelen),
|
||||
uintptr(unsafe.Pointer(sendBuf)),
|
||||
uintptr(sendDataLen),
|
||||
uintptr(unsafe.Pointer(bytesSent)),
|
||||
uintptr(unsafe.Pointer(overlapped)),
|
||||
0,
|
||||
0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = error(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
72
vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
generated
vendored
Normal file
72
vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
//go:build windows
|
||||
|
||||
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||
|
||||
package socket
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||
|
||||
procbind = modws2_32.NewProc("bind")
|
||||
procgetpeername = modws2_32.NewProc("getpeername")
|
||||
procgetsockname = modws2_32.NewProc("getsockname")
|
||||
)
|
||||
|
||||
func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
132
vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go
generated
vendored
Normal file
132
vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
package stringbuffer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"unicode/utf16"
|
||||
)
|
||||
|
||||
// TODO: worth exporting and using in mkwinsyscall?
|
||||
|
||||
// Uint16BufferSize is the buffer size in the pool, chosen somewhat arbitrarily to accommodate
|
||||
// large path strings:
|
||||
// MAX_PATH (260) + size of volume GUID prefix (49) + null terminator = 310.
|
||||
const MinWStringCap = 310
|
||||
|
||||
// use *[]uint16 since []uint16 creates an extra allocation where the slice header
|
||||
// is copied to heap and then referenced via pointer in the interface header that sync.Pool
|
||||
// stores.
|
||||
var pathPool = sync.Pool{ // if go1.18+ adds Pool[T], use that to store []uint16 directly
|
||||
New: func() interface{} {
|
||||
b := make([]uint16, MinWStringCap)
|
||||
return &b
|
||||
},
|
||||
}
|
||||
|
||||
func newBuffer() []uint16 { return *(pathPool.Get().(*[]uint16)) }
|
||||
|
||||
// freeBuffer copies the slice header data, and puts a pointer to that in the pool.
|
||||
// This avoids taking a pointer to the slice header in WString, which can be set to nil.
|
||||
func freeBuffer(b []uint16) { pathPool.Put(&b) }
|
||||
|
||||
// WString is a wide string buffer ([]uint16) meant for storing UTF-16 encoded strings
|
||||
// for interacting with Win32 APIs.
|
||||
// Sizes are specified as uint32 and not int.
|
||||
//
|
||||
// It is not thread safe.
|
||||
type WString struct {
|
||||
// type-def allows casting to []uint16 directly, use struct to prevent that and allow adding fields in the future.
|
||||
|
||||
// raw buffer
|
||||
b []uint16
|
||||
}
|
||||
|
||||
// NewWString returns a [WString] allocated from a shared pool with an
|
||||
// initial capacity of at least [MinWStringCap].
|
||||
// Since the buffer may have been previously used, its contents are not guaranteed to be empty.
|
||||
//
|
||||
// The buffer should be freed via [WString.Free]
|
||||
func NewWString() *WString {
|
||||
return &WString{
|
||||
b: newBuffer(),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *WString) Free() {
|
||||
if b.empty() {
|
||||
return
|
||||
}
|
||||
freeBuffer(b.b)
|
||||
b.b = nil
|
||||
}
|
||||
|
||||
// ResizeTo grows the buffer to at least c and returns the new capacity, freeing the
|
||||
// previous buffer back into pool.
|
||||
func (b *WString) ResizeTo(c uint32) uint32 {
|
||||
// allready sufficient (or n is 0)
|
||||
if c <= b.Cap() {
|
||||
return b.Cap()
|
||||
}
|
||||
|
||||
if c <= MinWStringCap {
|
||||
c = MinWStringCap
|
||||
}
|
||||
// allocate at-least double buffer size, as is done in [bytes.Buffer] and other places
|
||||
if c <= 2*b.Cap() {
|
||||
c = 2 * b.Cap()
|
||||
}
|
||||
|
||||
b2 := make([]uint16, c)
|
||||
if !b.empty() {
|
||||
copy(b2, b.b)
|
||||
freeBuffer(b.b)
|
||||
}
|
||||
b.b = b2
|
||||
return c
|
||||
}
|
||||
|
||||
// Buffer returns the underlying []uint16 buffer.
|
||||
func (b *WString) Buffer() []uint16 {
|
||||
if b.empty() {
|
||||
return nil
|
||||
}
|
||||
return b.b
|
||||
}
|
||||
|
||||
// Pointer returns a pointer to the first uint16 in the buffer.
|
||||
// If the [WString.Free] has already been called, the pointer will be nil.
|
||||
func (b *WString) Pointer() *uint16 {
|
||||
if b.empty() {
|
||||
return nil
|
||||
}
|
||||
return &b.b[0]
|
||||
}
|
||||
|
||||
// String returns the returns the UTF-8 encoding of the UTF-16 string in the buffer.
|
||||
//
|
||||
// It assumes that the data is null-terminated.
|
||||
func (b *WString) String() string {
|
||||
// Using [windows.UTF16ToString] would require importing "golang.org/x/sys/windows"
|
||||
// and would make this code Windows-only, which makes no sense.
|
||||
// So copy UTF16ToString code into here.
|
||||
// If other windows-specific code is added, switch to [windows.UTF16ToString]
|
||||
|
||||
s := b.b
|
||||
for i, v := range s {
|
||||
if v == 0 {
|
||||
s = s[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
return string(utf16.Decode(s))
|
||||
}
|
||||
|
||||
// Cap returns the underlying buffer capacity.
|
||||
func (b *WString) Cap() uint32 {
|
||||
if b.empty() {
|
||||
return 0
|
||||
}
|
||||
return b.cap()
|
||||
}
|
||||
|
||||
func (b *WString) cap() uint32 { return uint32(cap(b.b)) }
|
||||
func (b *WString) empty() bool { return b == nil || b.cap() == 0 }
|
||||
134
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
134
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
@@ -13,18 +14,21 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
"github.com/Microsoft/go-winio/internal/fs"
|
||||
)
|
||||
|
||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
||||
//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
|
||||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
||||
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
|
||||
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
|
||||
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile
|
||||
//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
|
||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
|
||||
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile
|
||||
//sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U
|
||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl
|
||||
|
||||
type ioStatusBlock struct {
|
||||
Status, Information uintptr
|
||||
@@ -51,45 +55,22 @@ type securityDescriptor struct {
|
||||
Control uint16
|
||||
Owner uintptr
|
||||
Group uintptr
|
||||
Sacl uintptr
|
||||
Dacl uintptr
|
||||
Sacl uintptr //revive:disable-line:var-naming SACL, not Sacl
|
||||
Dacl uintptr //revive:disable-line:var-naming DACL, not Dacl
|
||||
}
|
||||
|
||||
type ntstatus int32
|
||||
type ntStatus int32
|
||||
|
||||
func (status ntstatus) Err() error {
|
||||
func (status ntStatus) Err() error {
|
||||
if status >= 0 {
|
||||
return nil
|
||||
}
|
||||
return rtlNtStatusToDosError(status)
|
||||
}
|
||||
|
||||
const (
|
||||
cERROR_PIPE_BUSY = syscall.Errno(231)
|
||||
cERROR_NO_DATA = syscall.Errno(232)
|
||||
cERROR_PIPE_CONNECTED = syscall.Errno(535)
|
||||
cERROR_SEM_TIMEOUT = syscall.Errno(121)
|
||||
|
||||
cSECURITY_SQOS_PRESENT = 0x100000
|
||||
cSECURITY_ANONYMOUS = 0
|
||||
|
||||
cPIPE_TYPE_MESSAGE = 4
|
||||
|
||||
cPIPE_READMODE_MESSAGE = 2
|
||||
|
||||
cFILE_OPEN = 1
|
||||
cFILE_CREATE = 2
|
||||
|
||||
cFILE_PIPE_MESSAGE_TYPE = 1
|
||||
cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2
|
||||
|
||||
cSE_DACL_PRESENT = 4
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
|
||||
// This error should match net.errClosing since docker takes a dependency on its text.
|
||||
ErrPipeListenerClosed = errors.New("use of closed network connection")
|
||||
ErrPipeListenerClosed = net.ErrClosed
|
||||
|
||||
errPipeWriteClosed = errors.New("pipe has been closed for write")
|
||||
)
|
||||
@@ -116,9 +97,10 @@ func (f *win32Pipe) RemoteAddr() net.Addr {
|
||||
}
|
||||
|
||||
func (f *win32Pipe) SetDeadline(t time.Time) error {
|
||||
f.SetReadDeadline(t)
|
||||
f.SetWriteDeadline(t)
|
||||
return nil
|
||||
if err := f.SetReadDeadline(t); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
// CloseWrite closes the write side of a message pipe in byte mode.
|
||||
@@ -157,14 +139,14 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n, err := f.win32File.Read(b)
|
||||
if err == io.EOF {
|
||||
if err == io.EOF { //nolint:errorlint
|
||||
// If this was the result of a zero-byte read, then
|
||||
// it is possible that the read was due to a zero-size
|
||||
// message. Since we are simulating CloseWrite with a
|
||||
// zero-byte message, ensure that all future Read() calls
|
||||
// also return EOF.
|
||||
f.readEOF = true
|
||||
} else if err == syscall.ERROR_MORE_DATA {
|
||||
} else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno
|
||||
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
|
||||
// and the message still has more bytes. Treat this as a success, since
|
||||
// this package presents all named pipes as byte streams.
|
||||
@@ -173,7 +155,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (s pipeAddress) Network() string {
|
||||
func (pipeAddress) Network() string {
|
||||
return "pipe"
|
||||
}
|
||||
|
||||
@@ -182,18 +164,25 @@ func (s pipeAddress) String() string {
|
||||
}
|
||||
|
||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
||||
func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
|
||||
func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask) (syscall.Handle, error) {
|
||||
for {
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return syscall.Handle(0), ctx.Err()
|
||||
default:
|
||||
h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
wh, err := fs.CreateFile(*path,
|
||||
access,
|
||||
0, // mode
|
||||
nil, // security attributes
|
||||
fs.OPEN_EXISTING,
|
||||
fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.SECURITY_ANONYMOUS,
|
||||
0, // template file handle
|
||||
)
|
||||
h := syscall.Handle(wh)
|
||||
if err == nil {
|
||||
return h, nil
|
||||
}
|
||||
if err != cERROR_PIPE_BUSY {
|
||||
if err != windows.ERROR_PIPE_BUSY { //nolint:errorlint // err is Errno
|
||||
return h, &os.PathError{Err: err, Op: "open", Path: *path}
|
||||
}
|
||||
// Wait 10 msec and try again. This is a rather simplistic
|
||||
@@ -213,9 +202,10 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
||||
} else {
|
||||
absTimeout = time.Now().Add(2 * time.Second)
|
||||
}
|
||||
ctx, _ := context.WithDeadline(context.Background(), absTimeout)
|
||||
ctx, cancel := context.WithDeadline(context.Background(), absTimeout)
|
||||
defer cancel()
|
||||
conn, err := DialPipeContext(ctx, path)
|
||||
if err == context.DeadlineExceeded {
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
return nil, ErrTimeout
|
||||
}
|
||||
return conn, err
|
||||
@@ -232,7 +222,7 @@ func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
|
||||
func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) {
|
||||
var err error
|
||||
var h syscall.Handle
|
||||
h, err = tryDialPipe(ctx, &path, access)
|
||||
h, err = tryDialPipe(ctx, &path, fs.AccessMask(access))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -251,7 +241,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn,
|
||||
|
||||
// If the pipe is in message mode, return a message byte pipe, which
|
||||
// supports CloseWrite().
|
||||
if flags&cPIPE_TYPE_MESSAGE != 0 {
|
||||
if flags&windows.PIPE_TYPE_MESSAGE != 0 {
|
||||
return &win32MessageBytePipe{
|
||||
win32Pipe: win32Pipe{win32File: f, path: path},
|
||||
}, nil
|
||||
@@ -283,17 +273,22 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
||||
oa.Length = unsafe.Sizeof(oa)
|
||||
|
||||
var ntPath unicodeString
|
||||
if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
|
||||
if err := rtlDosPathNameToNtPathName(&path16[0],
|
||||
&ntPath,
|
||||
0,
|
||||
0,
|
||||
).Err(); err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
defer localFree(ntPath.Buffer)
|
||||
oa.ObjectName = &ntPath
|
||||
oa.Attributes = windows.OBJ_CASE_INSENSITIVE
|
||||
|
||||
// The security descriptor is only needed for the first pipe.
|
||||
if first {
|
||||
if sd != nil {
|
||||
len := uint32(len(sd))
|
||||
sdb := localAlloc(0, len)
|
||||
l := uint32(len(sd))
|
||||
sdb := localAlloc(0, l)
|
||||
defer localFree(sdb)
|
||||
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
|
||||
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
|
||||
@@ -301,28 +296,28 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
||||
// Construct the default named pipe security descriptor.
|
||||
var dacl uintptr
|
||||
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
|
||||
return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
|
||||
return 0, fmt.Errorf("getting default named pipe ACL: %w", err)
|
||||
}
|
||||
defer localFree(dacl)
|
||||
|
||||
sdb := &securityDescriptor{
|
||||
Revision: 1,
|
||||
Control: cSE_DACL_PRESENT,
|
||||
Control: windows.SE_DACL_PRESENT,
|
||||
Dacl: dacl,
|
||||
}
|
||||
oa.SecurityDescriptor = sdb
|
||||
}
|
||||
}
|
||||
|
||||
typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
|
||||
typ := uint32(windows.FILE_PIPE_REJECT_REMOTE_CLIENTS)
|
||||
if c.MessageMode {
|
||||
typ |= cFILE_PIPE_MESSAGE_TYPE
|
||||
typ |= windows.FILE_PIPE_MESSAGE_TYPE
|
||||
}
|
||||
|
||||
disposition := uint32(cFILE_OPEN)
|
||||
disposition := uint32(windows.FILE_OPEN)
|
||||
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
|
||||
if first {
|
||||
disposition = cFILE_CREATE
|
||||
disposition = windows.FILE_CREATE
|
||||
// By not asking for read or write access, the named pipe file system
|
||||
// will put this pipe into an initially disconnected state, blocking
|
||||
// client connections until the next call with first == false.
|
||||
@@ -335,7 +330,20 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy
|
||||
h syscall.Handle
|
||||
iosb ioStatusBlock
|
||||
)
|
||||
err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err()
|
||||
err = ntCreateNamedPipeFile(&h,
|
||||
access,
|
||||
&oa,
|
||||
&iosb,
|
||||
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
|
||||
disposition,
|
||||
0,
|
||||
typ,
|
||||
0,
|
||||
0,
|
||||
0xffffffff,
|
||||
uint32(c.InputBufferSize),
|
||||
uint32(c.OutputBufferSize),
|
||||
&timeout).Err()
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
@@ -380,7 +388,7 @@ func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
|
||||
p.Close()
|
||||
p = nil
|
||||
err = <-ch
|
||||
if err == nil || err == ErrFileClosed {
|
||||
if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno
|
||||
err = ErrPipeListenerClosed
|
||||
}
|
||||
}
|
||||
@@ -402,12 +410,12 @@ func (l *win32PipeListener) listenerRoutine() {
|
||||
p, err = l.makeConnectedServerPipe()
|
||||
// If the connection was immediately closed by the client, try
|
||||
// again.
|
||||
if err != cERROR_NO_DATA {
|
||||
if err != windows.ERROR_NO_DATA { //nolint:errorlint // err is Errno
|
||||
break
|
||||
}
|
||||
}
|
||||
responseCh <- acceptResponse{p, err}
|
||||
closed = err == ErrPipeListenerClosed
|
||||
closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno
|
||||
}
|
||||
}
|
||||
syscall.Close(l.firstHandle)
|
||||
@@ -469,15 +477,15 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
|
||||
}
|
||||
|
||||
func connectPipe(p *win32File) error {
|
||||
c, err := p.prepareIo()
|
||||
c, err := p.prepareIO()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer p.wg.Done()
|
||||
|
||||
err = connectNamedPipe(p.handle, &c.o)
|
||||
_, err = p.asyncIo(c, nil, 0, err)
|
||||
if err != nil && err != cERROR_PIPE_CONNECTED {
|
||||
_, err = p.asyncIO(c, nil, 0, err)
|
||||
if err != nil && err != windows.ERROR_PIPE_CONNECTED { //nolint:errorlint // err is Errno
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
16
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
16
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
@@ -1,5 +1,3 @@
|
||||
// +build windows
|
||||
|
||||
// Package guid provides a GUID type. The backing structure for a GUID is
|
||||
// identical to that used by the golang.org/x/sys/windows GUID type.
|
||||
// There are two main binary encodings used for a GUID, the big-endian encoding,
|
||||
@@ -9,24 +7,26 @@ package guid
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha1" //nolint:gosec // not used for secure application
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment
|
||||
|
||||
// Variant specifies which GUID variant (or "type") of the GUID. It determines
|
||||
// how the entirety of the rest of the GUID is interpreted.
|
||||
type Variant uint8
|
||||
|
||||
// The variants specified by RFC 4122.
|
||||
// The variants specified by RFC 4122 section 4.1.1.
|
||||
const (
|
||||
// VariantUnknown specifies a GUID variant which does not conform to one of
|
||||
// the variant encodings specified in RFC 4122.
|
||||
VariantUnknown Variant = iota
|
||||
VariantNCS
|
||||
VariantRFC4122
|
||||
VariantRFC4122 // RFC 4122
|
||||
VariantMicrosoft
|
||||
VariantFuture
|
||||
)
|
||||
@@ -36,6 +36,10 @@ const (
|
||||
// hash of an input string.
|
||||
type Version uint8
|
||||
|
||||
func (v Version) String() string {
|
||||
return strconv.FormatUint(uint64(v), 10)
|
||||
}
|
||||
|
||||
var _ = (encoding.TextMarshaler)(GUID{})
|
||||
var _ = (encoding.TextUnmarshaler)(&GUID{})
|
||||
|
||||
@@ -61,7 +65,7 @@ func NewV4() (GUID, error) {
|
||||
// big-endian UTF16 stream of bytes. If that is desired, the string can be
|
||||
// encoded as such before being passed to this function.
|
||||
func NewV5(namespace GUID, name []byte) (GUID, error) {
|
||||
b := sha1.New()
|
||||
b := sha1.New() //nolint:gosec // not used for secure application
|
||||
namespaceBytes := namespace.ToArray()
|
||||
b.Write(namespaceBytes[:])
|
||||
b.Write(name)
|
||||
|
||||
1
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
generated
vendored
1
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package guid
|
||||
|
||||
3
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
generated
vendored
3
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package guid
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
27
vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
generated
vendored
Normal file
27
vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// Code generated by "stringer -type=Variant -trimprefix=Variant -linecomment"; DO NOT EDIT.
|
||||
|
||||
package guid
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[VariantUnknown-0]
|
||||
_ = x[VariantNCS-1]
|
||||
_ = x[VariantRFC4122-2]
|
||||
_ = x[VariantMicrosoft-3]
|
||||
_ = x[VariantFuture-4]
|
||||
}
|
||||
|
||||
const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture"
|
||||
|
||||
var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33}
|
||||
|
||||
func (i Variant) String() string {
|
||||
if i >= Variant(len(_Variant_index)-1) {
|
||||
return "Variant(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Variant_name[_Variant_index[i]:_Variant_index[i+1]]
|
||||
}
|
||||
32
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
32
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
@@ -24,22 +25,17 @@ import (
|
||||
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
|
||||
|
||||
const (
|
||||
SE_PRIVILEGE_ENABLED = 2
|
||||
//revive:disable-next-line:var-naming ALL_CAPS
|
||||
SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED
|
||||
|
||||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
|
||||
//revive:disable-next-line:var-naming ALL_CAPS
|
||||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED
|
||||
|
||||
SeBackupPrivilege = "SeBackupPrivilege"
|
||||
SeRestorePrivilege = "SeRestorePrivilege"
|
||||
SeSecurityPrivilege = "SeSecurityPrivilege"
|
||||
)
|
||||
|
||||
const (
|
||||
securityAnonymous = iota
|
||||
securityIdentification
|
||||
securityImpersonation
|
||||
securityDelegation
|
||||
)
|
||||
|
||||
var (
|
||||
privNames = make(map[string]uint64)
|
||||
privNameMutex sync.Mutex
|
||||
@@ -51,11 +47,9 @@ type PrivilegeError struct {
|
||||
}
|
||||
|
||||
func (e *PrivilegeError) Error() string {
|
||||
s := ""
|
||||
s := "Could not enable privilege "
|
||||
if len(e.privileges) > 1 {
|
||||
s = "Could not enable privileges "
|
||||
} else {
|
||||
s = "Could not enable privilege "
|
||||
}
|
||||
for i, p := range e.privileges {
|
||||
if i != 0 {
|
||||
@@ -94,7 +88,7 @@ func RunWithPrivileges(names []string, fn func() error) error {
|
||||
}
|
||||
|
||||
func mapPrivileges(names []string) ([]uint64, error) {
|
||||
var privileges []uint64
|
||||
privileges := make([]uint64, 0, len(names))
|
||||
privNameMutex.Lock()
|
||||
defer privNameMutex.Unlock()
|
||||
for _, name := range names {
|
||||
@@ -127,7 +121,7 @@ func enableDisableProcessPrivilege(names []string, action uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
p, _ := windows.GetCurrentProcess()
|
||||
p := windows.CurrentProcess()
|
||||
var token windows.Token
|
||||
err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
|
||||
if err != nil {
|
||||
@@ -140,10 +134,10 @@ func enableDisableProcessPrivilege(names []string, action uint32) error {
|
||||
|
||||
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
|
||||
var b bytes.Buffer
|
||||
binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
|
||||
_ = binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
|
||||
for _, p := range privileges {
|
||||
binary.Write(&b, binary.LittleEndian, p)
|
||||
binary.Write(&b, binary.LittleEndian, action)
|
||||
_ = binary.Write(&b, binary.LittleEndian, p)
|
||||
_ = binary.Write(&b, binary.LittleEndian, action)
|
||||
}
|
||||
prevState := make([]byte, b.Len())
|
||||
reqSize := uint32(0)
|
||||
@@ -151,7 +145,7 @@ func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) e
|
||||
if !success {
|
||||
return err
|
||||
}
|
||||
if err == ERROR_NOT_ALL_ASSIGNED {
|
||||
if err == ERROR_NOT_ALL_ASSIGNED { //nolint:errorlint // err is Errno
|
||||
return &PrivilegeError{privileges}
|
||||
}
|
||||
return nil
|
||||
@@ -177,7 +171,7 @@ func getPrivilegeName(luid uint64) string {
|
||||
}
|
||||
|
||||
func newThreadToken() (windows.Token, error) {
|
||||
err := impersonateSelf(securityImpersonation)
|
||||
err := impersonateSelf(windows.SecurityImpersonation)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
11
vendor/github.com/Microsoft/go-winio/reparse.go
generated
vendored
11
vendor/github.com/Microsoft/go-winio/reparse.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
@@ -113,16 +116,16 @@ func EncodeReparsePoint(rp *ReparsePoint) []byte {
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
binary.Write(&b, binary.LittleEndian, &data)
|
||||
_ = binary.Write(&b, binary.LittleEndian, &data)
|
||||
if !rp.IsMountPoint {
|
||||
flags := uint32(0)
|
||||
if relative {
|
||||
flags |= 1
|
||||
}
|
||||
binary.Write(&b, binary.LittleEndian, flags)
|
||||
_ = binary.Write(&b, binary.LittleEndian, flags)
|
||||
}
|
||||
|
||||
binary.Write(&b, binary.LittleEndian, ntTarget16)
|
||||
binary.Write(&b, binary.LittleEndian, target16)
|
||||
_ = binary.Write(&b, binary.LittleEndian, ntTarget16)
|
||||
_ = binary.Write(&b, binary.LittleEndian, target16)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
64
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
64
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
@@ -1,23 +1,25 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
|
||||
//sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW
|
||||
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
||||
//sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW
|
||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
|
||||
//sys localFree(mem uintptr) = LocalFree
|
||||
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
|
||||
|
||||
const (
|
||||
cERROR_NONE_MAPPED = syscall.Errno(1332)
|
||||
)
|
||||
|
||||
type AccountLookupError struct {
|
||||
Name string
|
||||
Err error
|
||||
@@ -28,8 +30,10 @@ func (e *AccountLookupError) Error() string {
|
||||
return "lookup account: empty account name specified"
|
||||
}
|
||||
var s string
|
||||
switch e.Err {
|
||||
case cERROR_NONE_MAPPED:
|
||||
switch {
|
||||
case errors.Is(e.Err, windows.ERROR_INVALID_SID):
|
||||
s = "the security ID structure is invalid"
|
||||
case errors.Is(e.Err, windows.ERROR_NONE_MAPPED):
|
||||
s = "not found"
|
||||
default:
|
||||
s = e.Err.Error()
|
||||
@@ -37,6 +41,8 @@ func (e *AccountLookupError) Error() string {
|
||||
return "lookup account " + e.Name + ": " + s
|
||||
}
|
||||
|
||||
func (e *AccountLookupError) Unwrap() error { return e.Err }
|
||||
|
||||
type SddlConversionError struct {
|
||||
Sddl string
|
||||
Err error
|
||||
@@ -46,15 +52,19 @@ func (e *SddlConversionError) Error() string {
|
||||
return "convert " + e.Sddl + ": " + e.Err.Error()
|
||||
}
|
||||
|
||||
func (e *SddlConversionError) Unwrap() error { return e.Err }
|
||||
|
||||
// LookupSidByName looks up the SID of an account by name
|
||||
//
|
||||
//revive:disable-next-line:var-naming SID, not Sid
|
||||
func LookupSidByName(name string) (sid string, err error) {
|
||||
if name == "" {
|
||||
return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
|
||||
return "", &AccountLookupError{name, windows.ERROR_NONE_MAPPED}
|
||||
}
|
||||
|
||||
var sidSize, sidNameUse, refDomainSize uint32
|
||||
err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
|
||||
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
|
||||
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
|
||||
return "", &AccountLookupError{name, err}
|
||||
}
|
||||
sidBuffer := make([]byte, sidSize)
|
||||
@@ -73,6 +83,42 @@ func LookupSidByName(name string) (sid string, err error) {
|
||||
return sid, nil
|
||||
}
|
||||
|
||||
// LookupNameBySid looks up the name of an account by SID
|
||||
//
|
||||
//revive:disable-next-line:var-naming SID, not Sid
|
||||
func LookupNameBySid(sid string) (name string, err error) {
|
||||
if sid == "" {
|
||||
return "", &AccountLookupError{sid, windows.ERROR_NONE_MAPPED}
|
||||
}
|
||||
|
||||
sidBuffer, err := windows.UTF16PtrFromString(sid)
|
||||
if err != nil {
|
||||
return "", &AccountLookupError{sid, err}
|
||||
}
|
||||
|
||||
var sidPtr *byte
|
||||
if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil {
|
||||
return "", &AccountLookupError{sid, err}
|
||||
}
|
||||
defer localFree(uintptr(unsafe.Pointer(sidPtr)))
|
||||
|
||||
var nameSize, refDomainSize, sidNameUse uint32
|
||||
err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse)
|
||||
if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
|
||||
return "", &AccountLookupError{sid, err}
|
||||
}
|
||||
|
||||
nameBuffer := make([]uint16, nameSize)
|
||||
refDomainBuffer := make([]uint16, refDomainSize)
|
||||
err = lookupAccountSid(nil, sidPtr, &nameBuffer[0], &nameSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
|
||||
if err != nil {
|
||||
return "", &AccountLookupError{sid, err}
|
||||
}
|
||||
|
||||
name = windows.UTF16ToString(nameBuffer)
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
||||
var sdBuffer uintptr
|
||||
err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
|
||||
@@ -87,7 +133,7 @@ func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
||||
|
||||
func SecurityDescriptorToSddl(sd []byte) (string, error) {
|
||||
var sddl *uint16
|
||||
// The returned string length seems to including an aribtrary number of terminating NULs.
|
||||
// The returned string length seems to include an arbitrary number of terminating NULs.
|
||||
// Don't use it.
|
||||
err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
|
||||
if err != nil {
|
||||
|
||||
4
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
@@ -1,3 +1,5 @@
|
||||
//go:build windows
|
||||
|
||||
package winio
|
||||
|
||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
|
||||
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go
|
||||
|
||||
5
vendor/github.com/Microsoft/go-winio/tools.go
generated
vendored
Normal file
5
vendor/github.com/Microsoft/go-winio/tools.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
//go:build tools
|
||||
|
||||
package winio
|
||||
|
||||
import _ "golang.org/x/tools/cmd/stringer"
|
||||
64
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
64
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
@@ -1,4 +1,6 @@
|
||||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
//go:build windows
|
||||
|
||||
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
|
||||
|
||||
package winio
|
||||
|
||||
@@ -47,9 +49,11 @@ var (
|
||||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
|
||||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||
procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW")
|
||||
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
||||
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
|
||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||
procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW")
|
||||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
||||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
|
||||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
|
||||
@@ -59,7 +63,6 @@ var (
|
||||
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||
@@ -74,7 +77,6 @@ var (
|
||||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||
procbind = modws2_32.NewProc("bind")
|
||||
)
|
||||
|
||||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
|
||||
@@ -123,6 +125,14 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision
|
||||
return
|
||||
}
|
||||
|
||||
func convertStringSidToSid(str *uint16, sid **byte) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
||||
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
|
||||
len = uint32(r0)
|
||||
@@ -154,6 +164,14 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS
|
||||
return
|
||||
}
|
||||
|
||||
func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
@@ -286,24 +304,6 @@ func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
||||
newport = syscall.Handle(r0)
|
||||
@@ -380,25 +380,25 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
|
||||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) {
|
||||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
status = ntstatus(r0)
|
||||
status = ntStatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) {
|
||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
status = ntStatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) {
|
||||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
status = ntStatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
|
||||
func rtlNtStatusToDosError(status ntStatus) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
@@ -417,11 +417,3 @@ func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
4
vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go
generated
vendored
4
vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go
generated
vendored
@@ -191,7 +191,7 @@ func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
|
||||
return x3, y3, z3
|
||||
}
|
||||
|
||||
//TODO: double check if it is okay
|
||||
// TODO: double check if it is okay
|
||||
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
|
||||
func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
|
||||
// We have a slight problem in that the identity of the group (the
|
||||
@@ -239,7 +239,7 @@ func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
|
||||
|
||||
var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
|
||||
|
||||
//TODO: double check if it is okay
|
||||
// TODO: double check if it is okay
|
||||
// GenerateKey returns a public/private key pair. The private key is generated
|
||||
// using the given reader, which must return random data.
|
||||
func (bitCurve *BitCurve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err error) {
|
||||
|
||||
2
vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// Package brainpool implements Brainpool elliptic curves.
|
||||
// Implementation of rcurves is from github.com/ebfe/brainpool
|
||||
// Note that these curves are implemented with naive, non-constant time operations
|
||||
// and are likely not suitable for enviroments where timing attacks are a concern.
|
||||
// and are likely not suitable for environments where timing attacks are a concern.
|
||||
package brainpool
|
||||
|
||||
import (
|
||||
|
||||
2
vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go
generated
vendored
@@ -80,4 +80,4 @@ func (curve *rcurve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int)
|
||||
|
||||
func (curve *rcurve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
|
||||
return curve.fromTwisted(curve.twisted.ScalarBaseMult(scalar))
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/github.com/ProtonMail/go-crypto/eax/eax.go
generated
vendored
4
vendor/github.com/ProtonMail/go-crypto/eax/eax.go
generated
vendored
@@ -67,7 +67,7 @@ func (e *eax) Seal(dst, nonce, plaintext, adata []byte) []byte {
|
||||
if len(nonce) > e.nonceSize {
|
||||
panic("crypto/eax: Nonce too long for this instance")
|
||||
}
|
||||
ret, out := byteutil.SliceForAppend(dst, len(plaintext) + e.tagSize)
|
||||
ret, out := byteutil.SliceForAppend(dst, len(plaintext)+e.tagSize)
|
||||
omacNonce := e.omacT(0, nonce)
|
||||
omacAdata := e.omacT(1, adata)
|
||||
|
||||
@@ -85,7 +85,7 @@ func (e *eax) Seal(dst, nonce, plaintext, adata []byte) []byte {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (e* eax) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
|
||||
func (e *eax) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
|
||||
if len(nonce) > e.nonceSize {
|
||||
panic("crypto/eax: Nonce too long for this instance")
|
||||
}
|
||||
|
||||
8
vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go
generated
vendored
8
vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go
generated
vendored
@@ -41,7 +41,7 @@ func ShiftNBytesLeft(dst, x []byte, n int) {
|
||||
bits := uint(n % 8)
|
||||
l := len(dst)
|
||||
for i := 0; i < l-1; i++ {
|
||||
dst[i] = (dst[i] << bits) | (dst[i+1] >> uint(8 - bits))
|
||||
dst[i] = (dst[i] << bits) | (dst[i+1] >> uint(8-bits))
|
||||
}
|
||||
dst[l-1] = dst[l-1] << bits
|
||||
|
||||
@@ -56,7 +56,6 @@ func XorBytesMut(X, Y []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// XorBytes assumes equal input length, puts X XOR Y into Z
|
||||
func XorBytes(Z, X, Y []byte) {
|
||||
for i := 0; i < len(X); i++ {
|
||||
@@ -67,10 +66,10 @@ func XorBytes(Z, X, Y []byte) {
|
||||
// RightXor XORs smaller input (assumed Y) at the right of the larger input (assumed X)
|
||||
func RightXor(X, Y []byte) []byte {
|
||||
offset := len(X) - len(Y)
|
||||
xored := make([]byte, len(X));
|
||||
xored := make([]byte, len(X))
|
||||
copy(xored, X)
|
||||
for i := 0; i < len(Y); i++ {
|
||||
xored[offset + i] ^= Y[i]
|
||||
xored[offset+i] ^= Y[i]
|
||||
}
|
||||
return xored
|
||||
}
|
||||
@@ -89,4 +88,3 @@ func SliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
tail = head[len(in):]
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
10
vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
generated
vendored
10
vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
generated
vendored
@@ -93,13 +93,13 @@ func NewOCBWithNonceAndTagSize(
|
||||
return nil, ocbError("Custom tag length exceeds blocksize")
|
||||
}
|
||||
return &ocb{
|
||||
block: block,
|
||||
tagSize: tagSize,
|
||||
nonceSize: nonceSize,
|
||||
mask: initializeMaskTable(block),
|
||||
block: block,
|
||||
tagSize: tagSize,
|
||||
nonceSize: nonceSize,
|
||||
mask: initializeMaskTable(block),
|
||||
reusableKtop: reusableKtop{
|
||||
noncePrefix: nil,
|
||||
Ktop: nil,
|
||||
Ktop: nil,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
2
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go
generated
vendored
@@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
// Test vectors from https://tools.ietf.org/html/rfc7253. Note that key is
|
||||
// shared accross tests.
|
||||
// shared across tests.
|
||||
var testKey, _ = hex.DecodeString("000102030405060708090A0B0C0D0E0F")
|
||||
|
||||
var rfc7253testVectors = []struct {
|
||||
|
||||
31
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go
generated
vendored
31
vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go
generated
vendored
@@ -4,21 +4,22 @@ package ocb
|
||||
var rfc7253TestVectorTaglen96 = struct {
|
||||
key, nonce, header, plaintext, ciphertext string
|
||||
}{"0F0E0D0C0B0A09080706050403020100",
|
||||
"BBAA9988776655443322110D",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA"}
|
||||
"BBAA9988776655443322110D",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
|
||||
"1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA"}
|
||||
|
||||
var rfc7253AlgorithmTest = []struct {
|
||||
KEYLEN, TAGLEN int
|
||||
OUTPUT string }{
|
||||
{128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"},
|
||||
{192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"},
|
||||
{256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"},
|
||||
{128, 96, "77A3D8E73589158D25D01209"},
|
||||
{192, 96, "05D56EAD2752C86BE6932C5E"},
|
||||
{256, 96, "5458359AC23B0CBA9E6330DD"},
|
||||
{128, 64, "192C9B7BD90BA06A"},
|
||||
{192, 64, "0066BC6E0EF34E24"},
|
||||
{256, 64, "7D4EA5D445501CBE"},
|
||||
}
|
||||
OUTPUT string
|
||||
}{
|
||||
{128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"},
|
||||
{192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"},
|
||||
{256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"},
|
||||
{128, 96, "77A3D8E73589158D25D01209"},
|
||||
{192, 96, "05D56EAD2752C86BE6932C5E"},
|
||||
{256, 96, "5458359AC23B0CBA9E6330DD"},
|
||||
{128, 64, "192C9B7BD90BA06A"},
|
||||
{192, 64, "0066BC6E0EF34E24"},
|
||||
{256, 64, "7D4EA5D445501CBE"},
|
||||
}
|
||||
|
||||
23
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
generated
vendored
23
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
generated
vendored
@@ -10,19 +10,22 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// A Block represents an OpenPGP armored structure.
|
||||
//
|
||||
// The encoded form is:
|
||||
// -----BEGIN Type-----
|
||||
// Headers
|
||||
//
|
||||
// base64-encoded Bytes
|
||||
// '=' base64 encoded checksum
|
||||
// -----END Type-----
|
||||
// -----BEGIN Type-----
|
||||
// Headers
|
||||
//
|
||||
// base64-encoded Bytes
|
||||
// '=' base64 encoded checksum
|
||||
// -----END Type-----
|
||||
//
|
||||
// where Headers is a possibly empty sequence of Key: Value lines.
|
||||
//
|
||||
// Since the armored data can be very large, this package presents a streaming
|
||||
@@ -206,12 +209,16 @@ TryNextBlock:
|
||||
break
|
||||
}
|
||||
|
||||
i := bytes.Index(line, []byte(": "))
|
||||
i := bytes.Index(line, []byte(":"))
|
||||
if i == -1 {
|
||||
goto TryNextBlock
|
||||
}
|
||||
lastKey = string(line[:i])
|
||||
p.Header[lastKey] = string(line[i+2:])
|
||||
var value string
|
||||
if len(line) > i+2 {
|
||||
value = string(line[i+2:])
|
||||
}
|
||||
p.Header[lastKey] = value
|
||||
}
|
||||
|
||||
p.lReader.in = r
|
||||
|
||||
3
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
generated
vendored
3
vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
generated
vendored
@@ -96,7 +96,8 @@ func (l *lineBreaker) Close() (err error) {
|
||||
// trailer.
|
||||
//
|
||||
// It's built into a stack of io.Writers:
|
||||
// encoding -> base64 encoder -> lineBreaker -> out
|
||||
//
|
||||
// encoding -> base64 encoder -> lineBreaker -> out
|
||||
type encoding struct {
|
||||
out io.Writer
|
||||
breaker *lineBreaker
|
||||
|
||||
127
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
generated
vendored
127
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
generated
vendored
@@ -8,10 +8,8 @@ package ecdh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
@@ -24,9 +22,8 @@ type KDF struct {
|
||||
}
|
||||
|
||||
type PublicKey struct {
|
||||
ecc.CurveType
|
||||
elliptic.Curve
|
||||
X, Y *big.Int
|
||||
curve ecc.ECDHCurve
|
||||
Point []byte
|
||||
KDF
|
||||
}
|
||||
|
||||
@@ -35,11 +32,56 @@ type PrivateKey struct {
|
||||
D []byte
|
||||
}
|
||||
|
||||
func GenerateKey(c elliptic.Curve, kdf KDF, rand io.Reader) (priv *PrivateKey, err error) {
|
||||
func NewPublicKey(curve ecc.ECDHCurve, kdfHash algorithm.Hash, kdfCipher algorithm.Cipher) *PublicKey {
|
||||
return &PublicKey{
|
||||
curve: curve,
|
||||
KDF: KDF{
|
||||
Hash: kdfHash,
|
||||
Cipher: kdfCipher,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewPrivateKey(key PublicKey) *PrivateKey {
|
||||
return &PrivateKey{
|
||||
PublicKey: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (pk *PublicKey) GetCurve() ecc.ECDHCurve {
|
||||
return pk.curve
|
||||
}
|
||||
|
||||
func (pk *PublicKey) MarshalPoint() []byte {
|
||||
return pk.curve.MarshalBytePoint(pk.Point)
|
||||
}
|
||||
|
||||
func (pk *PublicKey) UnmarshalPoint(p []byte) error {
|
||||
pk.Point = pk.curve.UnmarshalBytePoint(p)
|
||||
if pk.Point == nil {
|
||||
return errors.New("ecdh: failed to parse EC point")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sk *PrivateKey) MarshalByteSecret() []byte {
|
||||
return sk.curve.MarshalByteSecret(sk.D)
|
||||
}
|
||||
|
||||
func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
|
||||
sk.D = sk.curve.UnmarshalByteSecret(d)
|
||||
|
||||
if sk.D == nil {
|
||||
return errors.New("ecdh: failed to parse scalar")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateKey(rand io.Reader, c ecc.ECDHCurve, kdf KDF) (priv *PrivateKey, err error) {
|
||||
priv = new(PrivateKey)
|
||||
priv.PublicKey.Curve = c
|
||||
priv.PublicKey.curve = c
|
||||
priv.PublicKey.KDF = kdf
|
||||
priv.D, priv.PublicKey.X, priv.PublicKey.Y, err = elliptic.GenerateKey(c, rand)
|
||||
priv.PublicKey.Point, priv.D, err = c.GenerateECDH(rand)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -56,22 +98,12 @@ func Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte
|
||||
}
|
||||
m := append(msg, padding...)
|
||||
|
||||
if pub.CurveType == ecc.Curve25519 {
|
||||
return X25519Encrypt(random, pub, m, curveOID, fingerprint)
|
||||
}
|
||||
|
||||
d, x, y, err := elliptic.GenerateKey(pub.Curve, random)
|
||||
ephemeral, zb, err := pub.curve.Encaps(random, pub.Point)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
vsG = elliptic.Marshal(pub.Curve, x, y)
|
||||
zbBig, _ := pub.Curve.ScalarMult(pub.X, pub.Y, d)
|
||||
|
||||
byteLen := (pub.Curve.Params().BitSize + 7) >> 3
|
||||
zb := make([]byte, byteLen)
|
||||
zbBytes := zbBig.Bytes()
|
||||
copy(zb[byteLen-len(zbBytes):], zbBytes)
|
||||
vsG = pub.curve.MarshalBytePoint(ephemeral)
|
||||
|
||||
z, err := buildKey(pub, zb, curveOID, fingerprint, false, false)
|
||||
if err != nil {
|
||||
@@ -86,29 +118,34 @@ func Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte
|
||||
|
||||
}
|
||||
|
||||
func Decrypt(priv *PrivateKey, vsG, m, curveOID, fingerprint []byte) (msg []byte, err error) {
|
||||
if priv.PublicKey.CurveType == ecc.Curve25519 {
|
||||
return X25519Decrypt(priv, vsG, m, curveOID, fingerprint)
|
||||
func Decrypt(priv *PrivateKey, vsG, c, curveOID, fingerprint []byte) (msg []byte, err error) {
|
||||
var m []byte
|
||||
zb, err := priv.PublicKey.curve.Decaps(priv.curve.UnmarshalBytePoint(vsG), priv.D)
|
||||
|
||||
// Try buildKey three times to workaround an old bug, see comments in buildKey.
|
||||
for i := 0; i < 3; i++ {
|
||||
var z []byte
|
||||
// RFC6637 §8: "Compute Z = KDF( S, Z_len, Param );"
|
||||
z, err = buildKey(&priv.PublicKey, zb, curveOID, fingerprint, i == 1, i == 2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// RFC6637 §8: "Compute C = AESKeyWrap( Z, c ) as per [RFC3394]"
|
||||
m, err = keywrap.Unwrap(z, c)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
x, y := elliptic.Unmarshal(priv.Curve, vsG)
|
||||
zbBig, _ := priv.Curve.ScalarMult(x, y, priv.D)
|
||||
|
||||
byteLen := (priv.Curve.Params().BitSize + 7) >> 3
|
||||
zb := make([]byte, byteLen)
|
||||
zbBytes := zbBig.Bytes()
|
||||
copy(zb[byteLen-len(zbBytes):], zbBytes)
|
||||
|
||||
z, err := buildKey(&priv.PublicKey, zb, curveOID, fingerprint, false, false)
|
||||
// Only return an error after we've tried all (required) variants of buildKey.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := keywrap.Unwrap(z, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c[:len(c)-int(c[len(c)-1])], nil
|
||||
// RFC6637 §8: "m = symm_alg_ID || session key || checksum || pkcs5_padding"
|
||||
// The last byte should be the length of the padding, as per PKCS5; strip it off.
|
||||
return m[:len(m)-int(m[len(m)-1])], nil
|
||||
}
|
||||
|
||||
func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLeading, stripTrailing bool) ([]byte, error) {
|
||||
@@ -130,7 +167,7 @@ func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLead
|
||||
if _, err := param.Write(fingerprint[:20]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if param.Len() - len(curveOID) != 45 {
|
||||
if param.Len()-len(curveOID) != 45 {
|
||||
return nil, errors.New("ecdh: malformed KDF Param")
|
||||
}
|
||||
|
||||
@@ -144,15 +181,19 @@ func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLead
|
||||
j := zbLen - 1
|
||||
if stripLeading {
|
||||
// Work around old go crypto bug where the leading zeros are missing.
|
||||
for ; i < zbLen && zb[i] == 0; i++ {}
|
||||
for i < zbLen && zb[i] == 0 {
|
||||
i++
|
||||
}
|
||||
}
|
||||
if stripTrailing {
|
||||
// Work around old OpenPGP.js bug where insignificant trailing zeros in
|
||||
// this little-endian number are missing.
|
||||
// (See https://github.com/openpgpjs/openpgpjs/pull/853.)
|
||||
for ; j >= 0 && zb[j] == 0; j-- {}
|
||||
for j >= 0 && zb[j] == 0 {
|
||||
j--
|
||||
}
|
||||
}
|
||||
if _, err := h.Write(zb[i:j+1]); err != nil {
|
||||
if _, err := h.Write(zb[i : j+1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := h.Write(param.Bytes()); err != nil {
|
||||
@@ -163,3 +204,7 @@ func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLead
|
||||
return mb[:pub.KDF.Cipher.KeySize()], nil // return oBits leftmost bits of MB.
|
||||
|
||||
}
|
||||
|
||||
func Validate(priv *PrivateKey) error {
|
||||
return priv.curve.ValidateECDH(priv.Point, priv.D)
|
||||
}
|
||||
|
||||
157
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/x25519.go
generated
vendored
157
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/x25519.go
generated
vendored
@@ -1,157 +0,0 @@
|
||||
// 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 ecdh implements ECDH encryption, suitable for OpenPGP,
|
||||
// as specified in RFC 6637, section 8.
|
||||
package ecdh
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
// Generates a private-public key-pair.
|
||||
// 'priv' is a private key; a scalar belonging to the set
|
||||
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the
|
||||
// curve. 'pub' is simply 'priv' * G where G is the base point.
|
||||
// See https://cr.yp.to/ecdh.html and RFC7748, sec 5.
|
||||
func x25519GenerateKeyPairBytes(rand io.Reader) (priv [32]byte, pub [32]byte, err error) {
|
||||
var n, helper = new(big.Int), new(big.Int)
|
||||
n.SetUint64(1)
|
||||
n.Lsh(n, 252)
|
||||
helper.SetString("27742317777372353535851937790883648493", 10)
|
||||
n.Add(n, helper)
|
||||
|
||||
for true {
|
||||
_, err = io.ReadFull(rand, priv[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// The following ensures that the private key is a number of the form
|
||||
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of
|
||||
// of the curve.
|
||||
priv[0] &= 248
|
||||
priv[31] &= 127
|
||||
priv[31] |= 64
|
||||
|
||||
// If the scalar is out of range, sample another random number.
|
||||
if new(big.Int).SetBytes(priv[:]).Cmp(n) >= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
curve25519.ScalarBaseMult(&pub, &priv)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// X25519GenerateKey samples the key pair according to the correct distribution.
|
||||
// It also sets the given key-derivation function and returns the *PrivateKey
|
||||
// object along with an error.
|
||||
func X25519GenerateKey(rand io.Reader, kdf KDF) (priv *PrivateKey, err error) {
|
||||
ci := ecc.FindByName("Curve25519")
|
||||
priv = new(PrivateKey)
|
||||
priv.PublicKey.Curve = ci.Curve
|
||||
d, pubKey, err := x25519GenerateKeyPairBytes(rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv.PublicKey.KDF = kdf
|
||||
priv.D = make([]byte, 32)
|
||||
copyReversed(priv.D, d[:])
|
||||
priv.PublicKey.CurveType = ci.CurveType
|
||||
priv.PublicKey.Curve = ci.Curve
|
||||
/*
|
||||
* Note that ECPoint.point differs from the definition of public keys in
|
||||
* [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
|
||||
* more uniform with how big integers are represented in TLS, and (2) there
|
||||
* is an additional length byte (so ECpoint.point is actually 33 bytes),
|
||||
* again for uniformity (and extensibility).
|
||||
*/
|
||||
var encodedKey = make([]byte, 33)
|
||||
encodedKey[0] = 0x40
|
||||
copy(encodedKey[1:], pubKey[:])
|
||||
priv.PublicKey.X = new(big.Int).SetBytes(encodedKey[:])
|
||||
priv.PublicKey.Y = new(big.Int)
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
func X25519Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) {
|
||||
d, ephemeralKey, err := x25519GenerateKeyPairBytes(random)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var pubKey [32]byte
|
||||
|
||||
if pub.X.BitLen() > 33*264 {
|
||||
return nil, nil, errors.New("ecdh: invalid key")
|
||||
}
|
||||
copy(pubKey[:], pub.X.Bytes()[1:])
|
||||
|
||||
var zb [32]byte
|
||||
curve25519.ScalarBaseMult(&zb, &d)
|
||||
curve25519.ScalarMult(&zb, &d, &pubKey)
|
||||
z, err := buildKey(pub, zb[:], curveOID, fingerprint, false, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if c, err = keywrap.Wrap(z, msg); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var vsg [33]byte
|
||||
vsg[0] = 0x40
|
||||
copy(vsg[1:], ephemeralKey[:])
|
||||
|
||||
return vsg[:], c, nil
|
||||
}
|
||||
|
||||
func X25519Decrypt(priv *PrivateKey, vsG, m, curveOID, fingerprint []byte) (msg []byte, err error) {
|
||||
var zb, d, ephemeralKey [32]byte
|
||||
if len(vsG) != 33 || vsG[0] != 0x40 {
|
||||
return nil, errors.New("ecdh: invalid key")
|
||||
}
|
||||
copy(ephemeralKey[:], vsG[1:33])
|
||||
|
||||
copyReversed(d[:], priv.D)
|
||||
curve25519.ScalarBaseMult(&zb, &d)
|
||||
curve25519.ScalarMult(&zb, &d, &ephemeralKey)
|
||||
|
||||
var c []byte
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
// Try buildKey three times for compat, see comments in buildKey.
|
||||
z, err := buildKey(&priv.PublicKey, zb[:], curveOID, fingerprint, i == 1, i == 2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := keywrap.Unwrap(z, m)
|
||||
if i == 2 && err != nil {
|
||||
// Only return an error after we've tried all variants of buildKey.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c = res
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return c[:len(c)-int(c[len(c)-1])], nil
|
||||
}
|
||||
|
||||
func copyReversed(out []byte, in []byte) {
|
||||
l := len(in)
|
||||
for i := 0; i < l; i++ {
|
||||
out[i] = in[l-i-1]
|
||||
}
|
||||
}
|
||||
80
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdsa/ecdsa.go
generated
vendored
Normal file
80
vendor/github.com/ProtonMail/go-crypto/openpgp/ecdsa/ecdsa.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// Package ecdsa implements ECDSA signature, suitable for OpenPGP,
|
||||
// as specified in RFC 6637, section 5.
|
||||
package ecdsa
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type PublicKey struct {
|
||||
X, Y *big.Int
|
||||
curve ecc.ECDSACurve
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
D *big.Int
|
||||
}
|
||||
|
||||
func NewPublicKey(curve ecc.ECDSACurve) *PublicKey {
|
||||
return &PublicKey{
|
||||
curve: curve,
|
||||
}
|
||||
}
|
||||
|
||||
func NewPrivateKey(key PublicKey) *PrivateKey {
|
||||
return &PrivateKey{
|
||||
PublicKey: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (pk *PublicKey) GetCurve() ecc.ECDSACurve {
|
||||
return pk.curve
|
||||
}
|
||||
|
||||
func (pk *PublicKey) MarshalPoint() []byte {
|
||||
return pk.curve.MarshalIntegerPoint(pk.X, pk.Y)
|
||||
}
|
||||
|
||||
func (pk *PublicKey) UnmarshalPoint(p []byte) error {
|
||||
pk.X, pk.Y = pk.curve.UnmarshalIntegerPoint(p)
|
||||
if pk.X == nil {
|
||||
return errors.New("ecdsa: failed to parse EC point")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sk *PrivateKey) MarshalIntegerSecret() []byte {
|
||||
return sk.curve.MarshalIntegerSecret(sk.D)
|
||||
}
|
||||
|
||||
func (sk *PrivateKey) UnmarshalIntegerSecret(d []byte) error {
|
||||
sk.D = sk.curve.UnmarshalIntegerSecret(d)
|
||||
|
||||
if sk.D == nil {
|
||||
return errors.New("ecdsa: failed to parse scalar")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateKey(rand io.Reader, c ecc.ECDSACurve) (priv *PrivateKey, err error) {
|
||||
priv = new(PrivateKey)
|
||||
priv.PublicKey.curve = c
|
||||
priv.PublicKey.X, priv.PublicKey.Y, priv.D, err = c.GenerateECDSA(rand)
|
||||
return
|
||||
}
|
||||
|
||||
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
|
||||
return priv.PublicKey.curve.Sign(rand, priv.X, priv.Y, priv.D, hash)
|
||||
}
|
||||
|
||||
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
|
||||
return pub.curve.Verify(pub.X, pub.Y, hash, r, s)
|
||||
}
|
||||
|
||||
func Validate(priv *PrivateKey) error {
|
||||
return priv.curve.ValidateECDSA(priv.X, priv.Y, priv.D.Bytes())
|
||||
}
|
||||
91
vendor/github.com/ProtonMail/go-crypto/openpgp/eddsa/eddsa.go
generated
vendored
Normal file
91
vendor/github.com/ProtonMail/go-crypto/openpgp/eddsa/eddsa.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// Package eddsa implements EdDSA signature, suitable for OpenPGP, as specified in
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
|
||||
package eddsa
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"io"
|
||||
)
|
||||
|
||||
type PublicKey struct {
|
||||
X []byte
|
||||
curve ecc.EdDSACurve
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
D []byte
|
||||
}
|
||||
|
||||
func NewPublicKey(curve ecc.EdDSACurve) *PublicKey {
|
||||
return &PublicKey{
|
||||
curve: curve,
|
||||
}
|
||||
}
|
||||
|
||||
func NewPrivateKey(key PublicKey) *PrivateKey {
|
||||
return &PrivateKey{
|
||||
PublicKey: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (pk *PublicKey) GetCurve() ecc.EdDSACurve {
|
||||
return pk.curve
|
||||
}
|
||||
|
||||
func (pk *PublicKey) MarshalPoint() []byte {
|
||||
return pk.curve.MarshalBytePoint(pk.X)
|
||||
}
|
||||
|
||||
func (pk *PublicKey) UnmarshalPoint(x []byte) error {
|
||||
pk.X = pk.curve.UnmarshalBytePoint(x)
|
||||
|
||||
if pk.X == nil {
|
||||
return errors.New("eddsa: failed to parse EC point")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sk *PrivateKey) MarshalByteSecret() []byte {
|
||||
return sk.curve.MarshalByteSecret(sk.D)
|
||||
}
|
||||
|
||||
func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
|
||||
sk.D = sk.curve.UnmarshalByteSecret(d)
|
||||
|
||||
if sk.D == nil {
|
||||
return errors.New("eddsa: failed to parse scalar")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateKey(rand io.Reader, c ecc.EdDSACurve) (priv *PrivateKey, err error) {
|
||||
priv = new(PrivateKey)
|
||||
priv.PublicKey.curve = c
|
||||
priv.PublicKey.X, priv.D, err = c.GenerateEdDSA(rand)
|
||||
return
|
||||
}
|
||||
|
||||
func Sign(priv *PrivateKey, message []byte) (r, s []byte, err error) {
|
||||
sig, err := priv.PublicKey.curve.Sign(priv.PublicKey.X, priv.D, message)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
r, s = priv.PublicKey.curve.MarshalSignature(sig)
|
||||
return
|
||||
}
|
||||
|
||||
func Verify(pub *PublicKey, message, r, s []byte) bool {
|
||||
sig := pub.curve.UnmarshalSignature(r, s)
|
||||
if sig == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return pub.curve.Verify(pub.X, message, sig)
|
||||
}
|
||||
|
||||
func Validate(priv *PrivateKey) error {
|
||||
return priv.curve.ValidateEdDSA(priv.PublicKey.X, priv.D)
|
||||
}
|
||||
4
vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go
generated
vendored
4
vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go
generated
vendored
@@ -71,8 +71,8 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err
|
||||
// returns the plaintext of the message. An error can result only if the
|
||||
// ciphertext is invalid. Users should keep in mind that this is a padding
|
||||
// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
|
||||
// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks
|
||||
// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
|
||||
// be used to break the cryptosystem. See “Chosen Ciphertext Attacks
|
||||
// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel
|
||||
// Bleichenbacher, Advances in Cryptology (Crypto '98),
|
||||
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
|
||||
s := new(big.Int).Exp(c1, priv.X, priv.P)
|
||||
|
||||
24
vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go
generated
vendored
Normal file
24
vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package openpgp
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
)
|
||||
|
||||
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
|
||||
// hash id.
|
||||
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
|
||||
return algorithm.HashIdToHash(id)
|
||||
}
|
||||
|
||||
// HashIdToString returns the name of the hash function corresponding to the
|
||||
// given OpenPGP hash id.
|
||||
func HashIdToString(id byte) (name string, ok bool) {
|
||||
return algorithm.HashIdToString(id)
|
||||
}
|
||||
|
||||
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
|
||||
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
|
||||
return algorithm.HashToHashId(h)
|
||||
}
|
||||
2
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go
generated
vendored
@@ -16,7 +16,7 @@ type AEADMode uint8
|
||||
const (
|
||||
AEADModeEAX = AEADMode(1)
|
||||
AEADModeOCB = AEADMode(2)
|
||||
AEADModeGCM = AEADMode(100)
|
||||
AEADModeGCM = AEADMode(3)
|
||||
)
|
||||
|
||||
// TagLength returns the length in bytes of authentication tags.
|
||||
|
||||
99
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go
generated
vendored
99
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go
generated
vendored
@@ -32,26 +32,25 @@ type Hash interface {
|
||||
|
||||
// The following vars mirror the crypto/Hash supported hash functions.
|
||||
var (
|
||||
MD5 Hash = cryptoHash{1, crypto.MD5}
|
||||
SHA1 Hash = cryptoHash{2, crypto.SHA1}
|
||||
RIPEMD160 Hash = cryptoHash{3, crypto.RIPEMD160}
|
||||
SHA256 Hash = cryptoHash{8, crypto.SHA256}
|
||||
SHA384 Hash = cryptoHash{9, crypto.SHA384}
|
||||
SHA512 Hash = cryptoHash{10, crypto.SHA512}
|
||||
SHA224 Hash = cryptoHash{11, crypto.SHA224}
|
||||
SHA1 Hash = cryptoHash{2, crypto.SHA1}
|
||||
SHA256 Hash = cryptoHash{8, crypto.SHA256}
|
||||
SHA384 Hash = cryptoHash{9, crypto.SHA384}
|
||||
SHA512 Hash = cryptoHash{10, crypto.SHA512}
|
||||
SHA224 Hash = cryptoHash{11, crypto.SHA224}
|
||||
SHA3_256 Hash = cryptoHash{12, crypto.SHA3_256}
|
||||
SHA3_512 Hash = cryptoHash{14, crypto.SHA3_512}
|
||||
)
|
||||
|
||||
// HashById represents the different hash functions specified for OpenPGP. See
|
||||
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14
|
||||
var (
|
||||
HashById = map[uint8]Hash{
|
||||
MD5.Id(): MD5,
|
||||
SHA1.Id(): SHA1,
|
||||
RIPEMD160.Id(): RIPEMD160,
|
||||
SHA256.Id(): SHA256,
|
||||
SHA384.Id(): SHA384,
|
||||
SHA512.Id(): SHA512,
|
||||
SHA224.Id(): SHA224,
|
||||
SHA256.Id(): SHA256,
|
||||
SHA384.Id(): SHA384,
|
||||
SHA512.Id(): SHA512,
|
||||
SHA224.Id(): SHA224,
|
||||
SHA3_256.Id(): SHA3_256,
|
||||
SHA3_512.Id(): SHA3_512,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -68,13 +67,12 @@ func (h cryptoHash) Id() uint8 {
|
||||
}
|
||||
|
||||
var hashNames = map[uint8]string{
|
||||
MD5.Id(): "MD5",
|
||||
SHA1.Id(): "SHA1",
|
||||
RIPEMD160.Id(): "RIPEMD160",
|
||||
SHA256.Id(): "SHA256",
|
||||
SHA384.Id(): "SHA384",
|
||||
SHA512.Id(): "SHA512",
|
||||
SHA224.Id(): "SHA224",
|
||||
SHA256.Id(): "SHA256",
|
||||
SHA384.Id(): "SHA384",
|
||||
SHA512.Id(): "SHA512",
|
||||
SHA224.Id(): "SHA224",
|
||||
SHA3_256.Id(): "SHA3-256",
|
||||
SHA3_512.Id(): "SHA3-512",
|
||||
}
|
||||
|
||||
func (h cryptoHash) String() string {
|
||||
@@ -84,3 +82,62 @@ func (h cryptoHash) String() string {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
|
||||
// hash id.
|
||||
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
|
||||
if hash, ok := HashById[id]; ok {
|
||||
return hash.HashFunc(), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// HashIdToHashWithSha1 returns a crypto.Hash which corresponds to the given OpenPGP
|
||||
// hash id, allowing sha1.
|
||||
func HashIdToHashWithSha1(id byte) (h crypto.Hash, ok bool) {
|
||||
if hash, ok := HashById[id]; ok {
|
||||
return hash.HashFunc(), true
|
||||
}
|
||||
|
||||
if id == SHA1.Id() {
|
||||
return SHA1.HashFunc(), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// HashIdToString returns the name of the hash function corresponding to the
|
||||
// given OpenPGP hash id.
|
||||
func HashIdToString(id byte) (name string, ok bool) {
|
||||
if hash, ok := HashById[id]; ok {
|
||||
return hash.String(), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
|
||||
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
|
||||
for id, hash := range HashById {
|
||||
if hash.HashFunc() == h {
|
||||
return id, true
|
||||
}
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// HashToHashIdWithSha1 returns an OpenPGP hash id which corresponds the given Hash,
|
||||
// allowing instances of SHA1
|
||||
func HashToHashIdWithSha1(h crypto.Hash) (id byte, ok bool) {
|
||||
for id, hash := range HashById {
|
||||
if hash.HashFunc() == h {
|
||||
return id, true
|
||||
}
|
||||
}
|
||||
|
||||
if h == SHA1.HashFunc() {
|
||||
return SHA1.Id(), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
171
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go
generated
vendored
Normal file
171
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
x25519lib "github.com/cloudflare/circl/dh/x25519"
|
||||
)
|
||||
|
||||
type curve25519 struct{}
|
||||
|
||||
func NewCurve25519() *curve25519 {
|
||||
return &curve25519{}
|
||||
}
|
||||
|
||||
func (c *curve25519) GetCurveName() string {
|
||||
return "curve25519"
|
||||
}
|
||||
|
||||
// MarshalBytePoint encodes the public point from native format, adding the prefix.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
|
||||
func (c *curve25519) MarshalBytePoint(point []byte) []byte {
|
||||
return append([]byte{0x40}, point...)
|
||||
}
|
||||
|
||||
// UnmarshalBytePoint decodes the public point to native format, removing the prefix.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
|
||||
func (c *curve25519) UnmarshalBytePoint(point []byte) []byte {
|
||||
if len(point) != x25519lib.Size+1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove prefix
|
||||
return point[1:]
|
||||
}
|
||||
|
||||
// MarshalByteSecret encodes the secret scalar from native format.
|
||||
// Note that the EC secret scalar differs from the definition of public keys in
|
||||
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
|
||||
// more uniform with how big integers are represented in OpenPGP, and (2) the
|
||||
// leading zeros are truncated.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
|
||||
// Note that leading zero bytes are stripped later when encoding as an MPI.
|
||||
func (c *curve25519) MarshalByteSecret(secret []byte) []byte {
|
||||
d := make([]byte, x25519lib.Size)
|
||||
copyReversed(d, secret)
|
||||
|
||||
// The following ensures that the private key is a number of the form
|
||||
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of
|
||||
// the curve.
|
||||
//
|
||||
// This masking is done internally in the underlying lib and so is unnecessary
|
||||
// for security, but OpenPGP implementations require that private keys be
|
||||
// pre-masked.
|
||||
d[0] &= 127
|
||||
d[0] |= 64
|
||||
d[31] &= 248
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// UnmarshalByteSecret decodes the secret scalar from native format.
|
||||
// Note that the EC secret scalar differs from the definition of public keys in
|
||||
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
|
||||
// more uniform with how big integers are represented in OpenPGP, and (2) the
|
||||
// leading zeros are truncated.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
|
||||
func (c *curve25519) UnmarshalByteSecret(d []byte) []byte {
|
||||
if len(d) > x25519lib.Size {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ensure truncated leading bytes are re-added
|
||||
secret := make([]byte, x25519lib.Size)
|
||||
copyReversed(secret, d)
|
||||
|
||||
return secret
|
||||
}
|
||||
|
||||
// generateKeyPairBytes Generates a private-public key-pair.
|
||||
// 'priv' is a private key; a little-endian scalar belonging to the set
|
||||
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the
|
||||
// curve. 'pub' is simply 'priv' * G where G is the base point.
|
||||
// See https://cr.yp.to/ecdh.html and RFC7748, sec 5.
|
||||
func (c *curve25519) generateKeyPairBytes(rand io.Reader) (priv, pub x25519lib.Key, err error) {
|
||||
_, err = io.ReadFull(rand, priv[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
x25519lib.KeyGen(&pub, &priv)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *curve25519) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
|
||||
priv, pub, err := c.generateKeyPairBytes(rand)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return pub[:], priv[:], nil
|
||||
}
|
||||
|
||||
func (c *genericCurve) MaskSecret(secret []byte) []byte {
|
||||
return secret
|
||||
}
|
||||
|
||||
func (c *curve25519) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
|
||||
// RFC6637 §8: "Generate an ephemeral key pair {v, V=vG}"
|
||||
// ephemeralPrivate corresponds to `v`.
|
||||
// ephemeralPublic corresponds to `V`.
|
||||
ephemeralPrivate, ephemeralPublic, err := c.generateKeyPairBytes(rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// RFC6637 §8: "Obtain the authenticated recipient public key R"
|
||||
// pubKey corresponds to `R`.
|
||||
var pubKey x25519lib.Key
|
||||
copy(pubKey[:], point)
|
||||
|
||||
// RFC6637 §8: "Compute the shared point S = vR"
|
||||
// "VB = convert point V to the octet string"
|
||||
// sharedPoint corresponds to `VB`.
|
||||
var sharedPoint x25519lib.Key
|
||||
x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey)
|
||||
|
||||
return ephemeralPublic[:], sharedPoint[:], nil
|
||||
}
|
||||
|
||||
func (c *curve25519) Decaps(vsG, secret []byte) (sharedSecret []byte, err error) {
|
||||
var ephemeralPublic, decodedPrivate, sharedPoint x25519lib.Key
|
||||
// RFC6637 §8: "The decryption is the inverse of the method given."
|
||||
// All quoted descriptions in comments below describe encryption, and
|
||||
// the reverse is performed.
|
||||
// vsG corresponds to `VB` in RFC6637 §8 .
|
||||
|
||||
// RFC6637 §8: "VB = convert point V to the octet string"
|
||||
copy(ephemeralPublic[:], vsG)
|
||||
|
||||
// decodedPrivate corresponds to `r` in RFC6637 §8 .
|
||||
copy(decodedPrivate[:], secret)
|
||||
|
||||
// RFC6637 §8: "Note that the recipient obtains the shared secret by calculating
|
||||
// S = rV = rvG, where (r,R) is the recipient's key pair."
|
||||
// sharedPoint corresponds to `S`.
|
||||
x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic)
|
||||
|
||||
return sharedPoint[:], nil
|
||||
}
|
||||
|
||||
func (c *curve25519) ValidateECDH(point []byte, secret []byte) (err error) {
|
||||
var pk, sk x25519lib.Key
|
||||
copy(sk[:], secret)
|
||||
x25519lib.KeyGen(&pk, &sk)
|
||||
|
||||
if subtle.ConstantTimeCompare(point, pk[:]) == 0 {
|
||||
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyReversed(out []byte, in []byte) {
|
||||
l := len(in)
|
||||
for i := 0; i < l; i++ {
|
||||
out[i] = in[l-i-1]
|
||||
}
|
||||
}
|
||||
118
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveInfo.go
generated
vendored
118
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveInfo.go
generated
vendored
@@ -1,118 +0,0 @@
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"crypto/elliptic"
|
||||
"bytes"
|
||||
"github.com/ProtonMail/go-crypto/bitcurves"
|
||||
"github.com/ProtonMail/go-crypto/brainpool"
|
||||
)
|
||||
|
||||
type SignatureAlgorithm uint8
|
||||
|
||||
const (
|
||||
ECDSA SignatureAlgorithm = 1
|
||||
EdDSA SignatureAlgorithm = 2
|
||||
)
|
||||
|
||||
type CurveInfo struct {
|
||||
Name string
|
||||
Oid *encoding.OID
|
||||
Curve elliptic.Curve
|
||||
SigAlgorithm SignatureAlgorithm
|
||||
CurveType CurveType
|
||||
}
|
||||
|
||||
var curves = []CurveInfo{
|
||||
{
|
||||
Name: "NIST curve P-256",
|
||||
Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}),
|
||||
Curve: elliptic.P256(),
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "NIST curve P-384",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}),
|
||||
Curve: elliptic.P384(),
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "NIST curve P-521",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}),
|
||||
Curve: elliptic.P521(),
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "SecP256k1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}),
|
||||
Curve: bitcurves.S256(),
|
||||
CurveType: BitCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "Curve25519",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
|
||||
Curve: elliptic.P256(),// filler
|
||||
CurveType: Curve25519,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "Ed25519",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
|
||||
Curve: elliptic.P256(), // filler
|
||||
CurveType: NISTCurve,
|
||||
SigAlgorithm: EdDSA,
|
||||
},
|
||||
{
|
||||
Name: "Brainpool P256r1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}),
|
||||
Curve: brainpool.P256r1(),
|
||||
CurveType: BrainpoolCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "BrainpoolP384r1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}),
|
||||
Curve: brainpool.P384r1(),
|
||||
CurveType: BrainpoolCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
{
|
||||
Name: "BrainpoolP512r1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}),
|
||||
Curve: brainpool.P512r1(),
|
||||
CurveType: BrainpoolCurve,
|
||||
SigAlgorithm: ECDSA,
|
||||
},
|
||||
}
|
||||
|
||||
func FindByCurve(curve elliptic.Curve) *CurveInfo {
|
||||
for _, curveInfo := range curves {
|
||||
if curveInfo.Curve == curve {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindByOid(oid encoding.Field) *CurveInfo {
|
||||
var rawBytes = oid.Bytes()
|
||||
for _, curveInfo := range curves {
|
||||
if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindByName(name string) *CurveInfo {
|
||||
for _, curveInfo := range curves {
|
||||
if curveInfo.Name == name {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveType.go
generated
vendored
10
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curveType.go
generated
vendored
@@ -1,10 +0,0 @@
|
||||
package ecc
|
||||
|
||||
type CurveType uint8
|
||||
|
||||
const (
|
||||
NISTCurve CurveType = 1
|
||||
Curve25519 CurveType = 2
|
||||
BitCurve CurveType = 3
|
||||
BrainpoolCurve CurveType = 4
|
||||
)
|
||||
140
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
generated
vendored
Normal file
140
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/elliptic"
|
||||
"github.com/ProtonMail/go-crypto/bitcurves"
|
||||
"github.com/ProtonMail/go-crypto/brainpool"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
)
|
||||
|
||||
type CurveInfo struct {
|
||||
GenName string
|
||||
Oid *encoding.OID
|
||||
Curve Curve
|
||||
}
|
||||
|
||||
var Curves = []CurveInfo{
|
||||
{
|
||||
// NIST P-256
|
||||
GenName: "P256",
|
||||
Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}),
|
||||
Curve: NewGenericCurve(elliptic.P256()),
|
||||
},
|
||||
{
|
||||
// NIST P-384
|
||||
GenName: "P384",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}),
|
||||
Curve: NewGenericCurve(elliptic.P384()),
|
||||
},
|
||||
{
|
||||
// NIST P-521
|
||||
GenName: "P521",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}),
|
||||
Curve: NewGenericCurve(elliptic.P521()),
|
||||
},
|
||||
{
|
||||
// SecP256k1
|
||||
GenName: "SecP256k1",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}),
|
||||
Curve: NewGenericCurve(bitcurves.S256()),
|
||||
},
|
||||
{
|
||||
// Curve25519
|
||||
GenName: "Curve25519",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
|
||||
Curve: NewCurve25519(),
|
||||
},
|
||||
{
|
||||
// X448
|
||||
GenName: "Curve448",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x6F}),
|
||||
Curve: NewX448(),
|
||||
},
|
||||
{
|
||||
// Ed25519
|
||||
GenName: "Curve25519",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
|
||||
Curve: NewEd25519(),
|
||||
},
|
||||
{
|
||||
// Ed448
|
||||
GenName: "Curve448",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x71}),
|
||||
Curve: NewEd448(),
|
||||
},
|
||||
{
|
||||
// BrainpoolP256r1
|
||||
GenName: "BrainpoolP256",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}),
|
||||
Curve: NewGenericCurve(brainpool.P256r1()),
|
||||
},
|
||||
{
|
||||
// BrainpoolP384r1
|
||||
GenName: "BrainpoolP384",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}),
|
||||
Curve: NewGenericCurve(brainpool.P384r1()),
|
||||
},
|
||||
{
|
||||
// BrainpoolP512r1
|
||||
GenName: "BrainpoolP512",
|
||||
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}),
|
||||
Curve: NewGenericCurve(brainpool.P512r1()),
|
||||
},
|
||||
}
|
||||
|
||||
func FindByCurve(curve Curve) *CurveInfo {
|
||||
for _, curveInfo := range Curves {
|
||||
if curveInfo.Curve.GetCurveName() == curve.GetCurveName() {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindByOid(oid encoding.Field) *CurveInfo {
|
||||
var rawBytes = oid.Bytes()
|
||||
for _, curveInfo := range Curves {
|
||||
if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) {
|
||||
return &curveInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindEdDSAByGenName(curveGenName string) EdDSACurve {
|
||||
for _, curveInfo := range Curves {
|
||||
if curveInfo.GenName == curveGenName {
|
||||
curve, ok := curveInfo.Curve.(EdDSACurve)
|
||||
if ok {
|
||||
return curve
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindECDSAByGenName(curveGenName string) ECDSACurve {
|
||||
for _, curveInfo := range Curves {
|
||||
if curveInfo.GenName == curveGenName {
|
||||
curve, ok := curveInfo.Curve.(ECDSACurve)
|
||||
if ok {
|
||||
return curve
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindECDHByGenName(curveGenName string) ECDHCurve {
|
||||
for _, curveInfo := range Curves {
|
||||
if curveInfo.GenName == curveGenName {
|
||||
curve, ok := curveInfo.Curve.(ECDHCurve)
|
||||
if ok {
|
||||
return curve
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
48
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curves.go
generated
vendored
Normal file
48
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curves.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type Curve interface {
|
||||
GetCurveName() string
|
||||
}
|
||||
|
||||
type ECDSACurve interface {
|
||||
Curve
|
||||
MarshalIntegerPoint(x, y *big.Int) []byte
|
||||
UnmarshalIntegerPoint([]byte) (x, y *big.Int)
|
||||
MarshalIntegerSecret(d *big.Int) []byte
|
||||
UnmarshalIntegerSecret(d []byte) *big.Int
|
||||
GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error)
|
||||
Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error)
|
||||
Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool
|
||||
ValidateECDSA(x, y *big.Int, secret []byte) error
|
||||
}
|
||||
|
||||
type EdDSACurve interface {
|
||||
Curve
|
||||
MarshalBytePoint(x []byte) []byte
|
||||
UnmarshalBytePoint([]byte) (x []byte)
|
||||
MarshalByteSecret(d []byte) []byte
|
||||
UnmarshalByteSecret(d []byte) []byte
|
||||
MarshalSignature(sig []byte) (r, s []byte)
|
||||
UnmarshalSignature(r, s []byte) (sig []byte)
|
||||
GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error)
|
||||
Sign(publicKey, privateKey, message []byte) (sig []byte, err error)
|
||||
Verify(publicKey, message, sig []byte) bool
|
||||
ValidateEdDSA(publicKey, privateKey []byte) (err error)
|
||||
}
|
||||
type ECDHCurve interface {
|
||||
Curve
|
||||
MarshalBytePoint([]byte) (encoded []byte)
|
||||
UnmarshalBytePoint(encoded []byte) []byte
|
||||
MarshalByteSecret(d []byte) []byte
|
||||
UnmarshalByteSecret(d []byte) []byte
|
||||
GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error)
|
||||
Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error)
|
||||
Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error)
|
||||
ValidateECDH(public []byte, secret []byte) error
|
||||
}
|
||||
112
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
generated
vendored
Normal file
112
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
ed25519lib "github.com/cloudflare/circl/sign/ed25519"
|
||||
)
|
||||
|
||||
const ed25519Size = 32
|
||||
|
||||
type ed25519 struct{}
|
||||
|
||||
func NewEd25519() *ed25519 {
|
||||
return &ed25519{}
|
||||
}
|
||||
|
||||
func (c *ed25519) GetCurveName() string {
|
||||
return "ed25519"
|
||||
}
|
||||
|
||||
// MarshalBytePoint encodes the public point from native format, adding the prefix.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed25519) MarshalBytePoint(x []byte) []byte {
|
||||
return append([]byte{0x40}, x...)
|
||||
}
|
||||
|
||||
// UnmarshalBytePoint decodes a point from prefixed format to native.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed25519) UnmarshalBytePoint(point []byte) (x []byte) {
|
||||
if len(point) != ed25519lib.PublicKeySize+1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return unprefixed
|
||||
return point[1:]
|
||||
}
|
||||
|
||||
// MarshalByteSecret encodes a scalar in native format.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed25519) MarshalByteSecret(d []byte) []byte {
|
||||
return d
|
||||
}
|
||||
|
||||
// UnmarshalByteSecret decodes a scalar in native format and re-adds the stripped leading zeroes
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed25519) UnmarshalByteSecret(s []byte) (d []byte) {
|
||||
if len(s) > ed25519lib.SeedSize {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle stripped leading zeroes
|
||||
d = make([]byte, ed25519lib.SeedSize)
|
||||
copy(d[ed25519lib.SeedSize-len(s):], s)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSignature splits a signature in R and S.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
|
||||
func (c *ed25519) MarshalSignature(sig []byte) (r, s []byte) {
|
||||
return sig[:ed25519Size], sig[ed25519Size:]
|
||||
}
|
||||
|
||||
// UnmarshalSignature decodes R and S in the native format, re-adding the stripped leading zeroes
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
|
||||
func (c *ed25519) UnmarshalSignature(r, s []byte) (sig []byte) {
|
||||
// Check size
|
||||
if len(r) > 32 || len(s) > 32 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sig = make([]byte, ed25519lib.SignatureSize)
|
||||
|
||||
// Handle stripped leading zeroes
|
||||
copy(sig[ed25519Size-len(r):ed25519Size], r)
|
||||
copy(sig[ed25519lib.SignatureSize-len(s):], s)
|
||||
return sig
|
||||
}
|
||||
|
||||
func (c *ed25519) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
|
||||
pk, sk, err := ed25519lib.GenerateKey(rand)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return pk, sk[:ed25519lib.SeedSize], nil
|
||||
}
|
||||
|
||||
func getEd25519Sk(publicKey, privateKey []byte) ed25519lib.PrivateKey {
|
||||
return append(privateKey, publicKey...)
|
||||
}
|
||||
|
||||
func (c *ed25519) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
|
||||
sig = ed25519lib.Sign(getEd25519Sk(publicKey, privateKey), message)
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func (c *ed25519) Verify(publicKey, message, sig []byte) bool {
|
||||
return ed25519lib.Verify(publicKey, message, sig)
|
||||
}
|
||||
|
||||
func (c *ed25519) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
|
||||
priv := getEd25519Sk(publicKey, privateKey)
|
||||
expectedPriv := ed25519lib.NewKeyFromSeed(priv.Seed())
|
||||
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
|
||||
return errors.KeyInvalidError("ecc: invalid ed25519 secret")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
111
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
generated
vendored
Normal file
111
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
ed448lib "github.com/cloudflare/circl/sign/ed448"
|
||||
)
|
||||
|
||||
type ed448 struct{}
|
||||
|
||||
func NewEd448() *ed448 {
|
||||
return &ed448{}
|
||||
}
|
||||
|
||||
func (c *ed448) GetCurveName() string {
|
||||
return "ed448"
|
||||
}
|
||||
|
||||
// MarshalBytePoint encodes the public point from native format, adding the prefix.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed448) MarshalBytePoint(x []byte) []byte {
|
||||
// Return prefixed
|
||||
return append([]byte{0x40}, x...)
|
||||
}
|
||||
|
||||
// UnmarshalBytePoint decodes a point from prefixed format to native.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed448) UnmarshalBytePoint(point []byte) (x []byte) {
|
||||
if len(point) != ed448lib.PublicKeySize+1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Strip prefix
|
||||
return point[1:]
|
||||
}
|
||||
|
||||
// MarshalByteSecret encoded a scalar from native format to prefixed.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed448) MarshalByteSecret(d []byte) []byte {
|
||||
// Return prefixed
|
||||
return append([]byte{0x40}, d...)
|
||||
}
|
||||
|
||||
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
|
||||
func (c *ed448) UnmarshalByteSecret(s []byte) (d []byte) {
|
||||
// Check prefixed size
|
||||
if len(s) != ed448lib.SeedSize+1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Strip prefix
|
||||
return s[1:]
|
||||
}
|
||||
|
||||
// MarshalSignature splits a signature in R and S, where R is in prefixed native format and
|
||||
// S is an MPI with value zero.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
|
||||
func (c *ed448) MarshalSignature(sig []byte) (r, s []byte) {
|
||||
return append([]byte{0x40}, sig...), []byte{}
|
||||
}
|
||||
|
||||
// UnmarshalSignature decodes R and S in the native format. Only R is used, in prefixed native format.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
|
||||
func (c *ed448) UnmarshalSignature(r, s []byte) (sig []byte) {
|
||||
if len(r) != ed448lib.SignatureSize+1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return r[1:]
|
||||
}
|
||||
|
||||
func (c *ed448) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
|
||||
pk, sk, err := ed448lib.GenerateKey(rand)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return pk, sk[:ed448lib.SeedSize], nil
|
||||
}
|
||||
|
||||
func getEd448Sk(publicKey, privateKey []byte) ed448lib.PrivateKey {
|
||||
return append(privateKey, publicKey...)
|
||||
}
|
||||
|
||||
func (c *ed448) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
|
||||
// Ed448 is used with the empty string as a context string.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
|
||||
sig = ed448lib.Sign(getEd448Sk(publicKey, privateKey), message, "")
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func (c *ed448) Verify(publicKey, message, sig []byte) bool {
|
||||
// Ed448 is used with the empty string as a context string.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
|
||||
return ed448lib.Verify(publicKey, message, sig, "")
|
||||
}
|
||||
|
||||
func (c *ed448) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
|
||||
priv := getEd448Sk(publicKey, privateKey)
|
||||
expectedPriv := ed448lib.NewKeyFromSeed(priv.Seed())
|
||||
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
|
||||
return errors.KeyInvalidError("ecc: invalid ed448 secret")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
149
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go
generated
vendored
Normal file
149
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"fmt"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type genericCurve struct {
|
||||
Curve elliptic.Curve
|
||||
}
|
||||
|
||||
func NewGenericCurve(c elliptic.Curve) *genericCurve {
|
||||
return &genericCurve{
|
||||
Curve: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *genericCurve) GetCurveName() string {
|
||||
return c.Curve.Params().Name
|
||||
}
|
||||
|
||||
func (c *genericCurve) MarshalBytePoint(point []byte) []byte {
|
||||
return point
|
||||
}
|
||||
|
||||
func (c *genericCurve) UnmarshalBytePoint(point []byte) []byte {
|
||||
return point
|
||||
}
|
||||
|
||||
func (c *genericCurve) MarshalIntegerPoint(x, y *big.Int) []byte {
|
||||
return elliptic.Marshal(c.Curve, x, y)
|
||||
}
|
||||
|
||||
func (c *genericCurve) UnmarshalIntegerPoint(point []byte) (x, y *big.Int) {
|
||||
return elliptic.Unmarshal(c.Curve, point)
|
||||
}
|
||||
|
||||
func (c *genericCurve) MarshalByteSecret(d []byte) []byte {
|
||||
return d
|
||||
}
|
||||
|
||||
func (c *genericCurve) UnmarshalByteSecret(d []byte) []byte {
|
||||
return d
|
||||
}
|
||||
|
||||
func (c *genericCurve) MarshalIntegerSecret(d *big.Int) []byte {
|
||||
return d.Bytes()
|
||||
}
|
||||
|
||||
func (c *genericCurve) UnmarshalIntegerSecret(d []byte) *big.Int {
|
||||
return new(big.Int).SetBytes(d)
|
||||
}
|
||||
|
||||
func (c *genericCurve) GenerateECDH(rand io.Reader) (point, secret []byte, err error) {
|
||||
secret, x, y, err := elliptic.GenerateKey(c.Curve, rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
point = elliptic.Marshal(c.Curve, x, y)
|
||||
return point, secret, nil
|
||||
}
|
||||
|
||||
func (c *genericCurve) GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error) {
|
||||
priv, err := ecdsa.GenerateKey(c.Curve, rand)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return priv.X, priv.Y, priv.D, nil
|
||||
}
|
||||
|
||||
func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
|
||||
xP, yP := elliptic.Unmarshal(c.Curve, point)
|
||||
if xP == nil {
|
||||
panic("invalid point")
|
||||
}
|
||||
|
||||
d, x, y, err := elliptic.GenerateKey(c.Curve, rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
vsG := elliptic.Marshal(c.Curve, x, y)
|
||||
zbBig, _ := c.Curve.ScalarMult(xP, yP, d)
|
||||
|
||||
byteLen := (c.Curve.Params().BitSize + 7) >> 3
|
||||
zb := make([]byte, byteLen)
|
||||
zbBytes := zbBig.Bytes()
|
||||
copy(zb[byteLen-len(zbBytes):], zbBytes)
|
||||
|
||||
return vsG, zb, nil
|
||||
}
|
||||
|
||||
func (c *genericCurve) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
|
||||
x, y := elliptic.Unmarshal(c.Curve, ephemeral)
|
||||
zbBig, _ := c.Curve.ScalarMult(x, y, secret)
|
||||
byteLen := (c.Curve.Params().BitSize + 7) >> 3
|
||||
zb := make([]byte, byteLen)
|
||||
zbBytes := zbBig.Bytes()
|
||||
copy(zb[byteLen-len(zbBytes):], zbBytes)
|
||||
|
||||
return zb, nil
|
||||
}
|
||||
|
||||
func (c *genericCurve) Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error) {
|
||||
priv := &ecdsa.PrivateKey{D: d, PublicKey: ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}}
|
||||
return ecdsa.Sign(rand, priv, hash)
|
||||
}
|
||||
|
||||
func (c *genericCurve) Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool {
|
||||
pub := &ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}
|
||||
return ecdsa.Verify(pub, hash, r, s)
|
||||
}
|
||||
|
||||
func (c *genericCurve) validate(xP, yP *big.Int, secret []byte) error {
|
||||
// the public point should not be at infinity (0,0)
|
||||
zero := new(big.Int)
|
||||
if xP.Cmp(zero) == 0 && yP.Cmp(zero) == 0 {
|
||||
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", c.Curve.Params().Name))
|
||||
}
|
||||
|
||||
// re-derive the public point Q' = (X,Y) = dG
|
||||
// to compare to declared Q in public key
|
||||
expectedX, expectedY := c.Curve.ScalarBaseMult(secret)
|
||||
if xP.Cmp(expectedX) != 0 || yP.Cmp(expectedY) != 0 {
|
||||
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *genericCurve) ValidateECDSA(xP, yP *big.Int, secret []byte) error {
|
||||
return c.validate(xP, yP, secret)
|
||||
}
|
||||
|
||||
func (c *genericCurve) ValidateECDH(point []byte, secret []byte) error {
|
||||
xP, yP := elliptic.Unmarshal(c.Curve, point)
|
||||
if xP == nil {
|
||||
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
|
||||
}
|
||||
|
||||
return c.validate(xP, yP, secret)
|
||||
}
|
||||
105
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.go
generated
vendored
Normal file
105
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
x448lib "github.com/cloudflare/circl/dh/x448"
|
||||
)
|
||||
|
||||
type x448 struct{}
|
||||
|
||||
func NewX448() *x448 {
|
||||
return &x448{}
|
||||
}
|
||||
|
||||
func (c *x448) GetCurveName() string {
|
||||
return "x448"
|
||||
}
|
||||
|
||||
// MarshalBytePoint encodes the public point from native format, adding the prefix.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
|
||||
func (c *x448) MarshalBytePoint(point []byte) []byte {
|
||||
return append([]byte{0x40}, point...)
|
||||
}
|
||||
|
||||
// UnmarshalBytePoint decodes a point from prefixed format to native.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
|
||||
func (c *x448) UnmarshalBytePoint(point []byte) []byte {
|
||||
if len(point) != x448lib.Size+1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return point[1:]
|
||||
}
|
||||
|
||||
// MarshalByteSecret encoded a scalar from native format to prefixed.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
|
||||
func (c *x448) MarshalByteSecret(d []byte) []byte {
|
||||
return append([]byte{0x40}, d...)
|
||||
}
|
||||
|
||||
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
|
||||
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
|
||||
func (c *x448) UnmarshalByteSecret(d []byte) []byte {
|
||||
if len(d) != x448lib.Size+1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Store without prefix
|
||||
return d[1:]
|
||||
}
|
||||
|
||||
func (c *x448) generateKeyPairBytes(rand io.Reader) (sk, pk x448lib.Key, err error) {
|
||||
if _, err = rand.Read(sk[:]); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
x448lib.KeyGen(&pk, &sk)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *x448) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
|
||||
priv, pub, err := c.generateKeyPairBytes(rand)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return pub[:], priv[:], nil
|
||||
}
|
||||
|
||||
func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
|
||||
var pk, ss x448lib.Key
|
||||
seed, e, err := c.generateKeyPairBytes(rand)
|
||||
|
||||
copy(pk[:], point)
|
||||
x448lib.Shared(&ss, &seed, &pk)
|
||||
|
||||
return e[:], ss[:], nil
|
||||
}
|
||||
|
||||
func (c *x448) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
|
||||
var ss, sk, e x448lib.Key
|
||||
|
||||
copy(sk[:], secret)
|
||||
copy(e[:], ephemeral)
|
||||
x448lib.Shared(&ss, &sk, &e)
|
||||
|
||||
return ss[:], nil
|
||||
}
|
||||
|
||||
func (c *x448) ValidateECDH(point []byte, secret []byte) error {
|
||||
var sk, pk, expectedPk x448lib.Key
|
||||
|
||||
copy(pk[:], point)
|
||||
copy(sk[:], secret)
|
||||
x448lib.KeyGen(&expectedPk, &sk)
|
||||
|
||||
if subtle.ConstantTimeCompare(expectedPk[:], pk[:]) == 0 {
|
||||
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
2
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go
generated
vendored
@@ -32,7 +32,7 @@ func NewOID(bytes []byte) *OID {
|
||||
panic("encoding: NewOID argument length is reserved")
|
||||
default:
|
||||
if len(bytes) > maxOID {
|
||||
panic("encoding: NewOID argment too large")
|
||||
panic("encoding: NewOID argument too large")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
259
vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
generated
vendored
259
vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
generated
vendored
@@ -11,12 +11,15 @@ import (
|
||||
goerrors "errors"
|
||||
"io"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
|
||||
@@ -27,11 +30,6 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
||||
creationTime := config.Now()
|
||||
keyLifetimeSecs := config.KeyLifetime()
|
||||
|
||||
uid := packet.NewUserId(name, comment, email)
|
||||
if uid == nil {
|
||||
return nil, errors.InvalidArgumentError("user id field contained invalid characters")
|
||||
}
|
||||
|
||||
// Generate a primary signing key
|
||||
primaryPrivRaw, err := newSigner(config)
|
||||
if err != nil {
|
||||
@@ -42,28 +40,66 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
||||
primary.UpgradeToV5()
|
||||
}
|
||||
|
||||
isPrimaryId := true
|
||||
selfSignature := &packet.Signature{
|
||||
Version: primary.PublicKey.Version,
|
||||
SigType: packet.SigTypePositiveCert,
|
||||
PubKeyAlgo: primary.PublicKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
CreationTime: creationTime,
|
||||
KeyLifetimeSecs: &keyLifetimeSecs,
|
||||
IssuerKeyId: &primary.PublicKey.KeyId,
|
||||
IssuerFingerprint: primary.PublicKey.Fingerprint,
|
||||
IsPrimaryId: &isPrimaryId,
|
||||
FlagsValid: true,
|
||||
FlagSign: true,
|
||||
FlagCertify: true,
|
||||
MDC: true, // true by default, see 5.8 vs. 5.14
|
||||
AEAD: config.AEAD() != nil,
|
||||
V5Keys: config != nil && config.V5Keys,
|
||||
e := &Entity{
|
||||
PrimaryKey: &primary.PublicKey,
|
||||
PrivateKey: primary,
|
||||
Identities: make(map[string]*Identity),
|
||||
Subkeys: []Subkey{},
|
||||
}
|
||||
|
||||
err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// NOTE: No key expiry here, but we will not return this subkey in EncryptionKey()
|
||||
// if the primary/master key has expired.
|
||||
err = e.addEncryptionSubkey(config, creationTime, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (t *Entity) AddUserId(name, comment, email string, config *packet.Config) error {
|
||||
creationTime := config.Now()
|
||||
keyLifetimeSecs := config.KeyLifetime()
|
||||
return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs)
|
||||
}
|
||||
|
||||
func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error {
|
||||
uid := packet.NewUserId(name, comment, email)
|
||||
if uid == nil {
|
||||
return errors.InvalidArgumentError("user id field contained invalid characters")
|
||||
}
|
||||
|
||||
if _, ok := t.Identities[uid.Id]; ok {
|
||||
return errors.InvalidArgumentError("user id exist")
|
||||
}
|
||||
|
||||
primary := t.PrivateKey
|
||||
|
||||
isPrimaryId := len(t.Identities) == 0
|
||||
|
||||
selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypePositiveCert, config)
|
||||
selfSignature.CreationTime = creationTime
|
||||
selfSignature.KeyLifetimeSecs = &keyLifetimeSecs
|
||||
selfSignature.IsPrimaryId = &isPrimaryId
|
||||
selfSignature.FlagsValid = true
|
||||
selfSignature.FlagSign = true
|
||||
selfSignature.FlagCertify = true
|
||||
selfSignature.SEIPDv1 = true // true by default, see 5.8 vs. 5.14
|
||||
selfSignature.SEIPDv2 = config.AEAD() != nil
|
||||
|
||||
// Set the PreferredHash for the SelfSignature from the packet.Config.
|
||||
// If it is not the must-implement algorithm from rfc4880bis, append that.
|
||||
selfSignature.PreferredHash = []uint8{hashToHashId(config.Hash())}
|
||||
hash, ok := algorithm.HashToHashId(config.Hash())
|
||||
if !ok {
|
||||
return errors.UnsupportedError("unsupported preferred hash function")
|
||||
}
|
||||
|
||||
selfSignature.PreferredHash = []uint8{hash}
|
||||
if config.Hash() != crypto.SHA256 {
|
||||
selfSignature.PreferredHash = append(selfSignature.PreferredHash, hashToHashId(crypto.SHA256))
|
||||
}
|
||||
@@ -84,66 +120,30 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
|
||||
}
|
||||
|
||||
// And for DefaultMode.
|
||||
selfSignature.PreferredAEAD = []uint8{uint8(config.AEAD().Mode())}
|
||||
if config.AEAD().Mode() != packet.AEADModeEAX {
|
||||
selfSignature.PreferredAEAD = append(selfSignature.PreferredAEAD, uint8(packet.AEADModeEAX))
|
||||
modes := []uint8{uint8(config.AEAD().Mode())}
|
||||
if config.AEAD().Mode() != packet.AEADModeOCB {
|
||||
modes = append(modes, uint8(packet.AEADModeOCB))
|
||||
}
|
||||
|
||||
// For preferred (AES256, GCM), we'll generate (AES256, GCM), (AES256, OCB), (AES128, GCM), (AES128, OCB)
|
||||
for _, cipher := range selfSignature.PreferredSymmetric {
|
||||
for _, mode := range modes {
|
||||
selfSignature.PreferredCipherSuites = append(selfSignature.PreferredCipherSuites, [2]uint8{cipher, mode})
|
||||
}
|
||||
}
|
||||
|
||||
// User ID binding signature
|
||||
err = selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config)
|
||||
err := selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate an encryption subkey
|
||||
subPrivRaw, err := newDecrypter(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
t.Identities[uid.Id] = &Identity{
|
||||
Name: uid.Id,
|
||||
UserId: uid,
|
||||
SelfSignature: selfSignature,
|
||||
Signatures: []*packet.Signature{selfSignature},
|
||||
}
|
||||
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
|
||||
sub.IsSubkey = true
|
||||
sub.PublicKey.IsSubkey = true
|
||||
if config != nil && config.V5Keys {
|
||||
sub.UpgradeToV5()
|
||||
}
|
||||
|
||||
// NOTE: No KeyLifetimeSecs here, but we will not return this subkey in EncryptionKey()
|
||||
// if the primary/master key has expired.
|
||||
subKey := Subkey{
|
||||
PublicKey: &sub.PublicKey,
|
||||
PrivateKey: sub,
|
||||
Sig: &packet.Signature{
|
||||
Version: primary.PublicKey.Version,
|
||||
CreationTime: creationTime,
|
||||
SigType: packet.SigTypeSubkeyBinding,
|
||||
PubKeyAlgo: primary.PublicKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
FlagsValid: true,
|
||||
FlagEncryptStorage: true,
|
||||
FlagEncryptCommunications: true,
|
||||
IssuerKeyId: &primary.PublicKey.KeyId,
|
||||
},
|
||||
}
|
||||
|
||||
// Subkey binding signature
|
||||
err = subKey.Sig.SignKey(subKey.PublicKey, primary, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Entity{
|
||||
PrimaryKey: &primary.PublicKey,
|
||||
PrivateKey: primary,
|
||||
Identities: map[string]*Identity{
|
||||
uid.Id: &Identity{
|
||||
Name: uid.Id,
|
||||
UserId: uid,
|
||||
SelfSignature: selfSignature,
|
||||
Signatures: []*packet.Signature{selfSignature},
|
||||
},
|
||||
},
|
||||
Subkeys: []Subkey{subKey},
|
||||
}, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddSigningSubkey adds a signing keypair as a subkey to the Entity.
|
||||
@@ -157,42 +157,30 @@ func (e *Entity) AddSigningSubkey(config *packet.Config) error {
|
||||
return err
|
||||
}
|
||||
sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw)
|
||||
sub.IsSubkey = true
|
||||
if config != nil && config.V5Keys {
|
||||
sub.UpgradeToV5()
|
||||
}
|
||||
|
||||
subkey := Subkey{
|
||||
PublicKey: &sub.PublicKey,
|
||||
PrivateKey: sub,
|
||||
Sig: &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: creationTime,
|
||||
KeyLifetimeSecs: &keyLifetimeSecs,
|
||||
SigType: packet.SigTypeSubkeyBinding,
|
||||
PubKeyAlgo: e.PrimaryKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
FlagsValid: true,
|
||||
FlagSign: true,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
EmbeddedSignature: &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: creationTime,
|
||||
SigType: packet.SigTypePrimaryKeyBinding,
|
||||
PubKeyAlgo: sub.PublicKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
},
|
||||
},
|
||||
}
|
||||
if config != nil && config.V5Keys {
|
||||
subkey.PublicKey.UpgradeToV5()
|
||||
}
|
||||
subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
|
||||
subkey.Sig.CreationTime = creationTime
|
||||
subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
|
||||
subkey.Sig.FlagsValid = true
|
||||
subkey.Sig.FlagSign = true
|
||||
subkey.Sig.EmbeddedSignature = createSignaturePacket(subkey.PublicKey, packet.SigTypePrimaryKeyBinding, config)
|
||||
subkey.Sig.EmbeddedSignature.CreationTime = creationTime
|
||||
|
||||
err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, subkey.PrivateKey, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subkey.PublicKey.IsSubkey = true
|
||||
subkey.PrivateKey.IsSubkey = true
|
||||
if err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config); err != nil {
|
||||
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -205,36 +193,33 @@ func (e *Entity) AddSigningSubkey(config *packet.Config) error {
|
||||
func (e *Entity) AddEncryptionSubkey(config *packet.Config) error {
|
||||
creationTime := config.Now()
|
||||
keyLifetimeSecs := config.KeyLifetime()
|
||||
return e.addEncryptionSubkey(config, creationTime, keyLifetimeSecs)
|
||||
}
|
||||
|
||||
func (e *Entity) addEncryptionSubkey(config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error {
|
||||
subPrivRaw, err := newDecrypter(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
|
||||
sub.IsSubkey = true
|
||||
if config != nil && config.V5Keys {
|
||||
sub.UpgradeToV5()
|
||||
}
|
||||
|
||||
subkey := Subkey{
|
||||
PublicKey: &sub.PublicKey,
|
||||
PrivateKey: sub,
|
||||
Sig: &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: creationTime,
|
||||
KeyLifetimeSecs: &keyLifetimeSecs,
|
||||
SigType: packet.SigTypeSubkeyBinding,
|
||||
PubKeyAlgo: e.PrimaryKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
FlagsValid: true,
|
||||
FlagEncryptStorage: true,
|
||||
FlagEncryptCommunications: true,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
},
|
||||
}
|
||||
if config != nil && config.V5Keys {
|
||||
subkey.PublicKey.UpgradeToV5()
|
||||
}
|
||||
subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
|
||||
subkey.Sig.CreationTime = creationTime
|
||||
subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
|
||||
subkey.Sig.FlagsValid = true
|
||||
subkey.Sig.FlagEncryptStorage = true
|
||||
subkey.Sig.FlagEncryptCommunications = true
|
||||
|
||||
subkey.PublicKey.IsSubkey = true
|
||||
subkey.PrivateKey.IsSubkey = true
|
||||
if err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config); err != nil {
|
||||
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -243,7 +228,7 @@ func (e *Entity) AddEncryptionSubkey(config *packet.Config) error {
|
||||
}
|
||||
|
||||
// Generates a signing key
|
||||
func newSigner(config *packet.Config) (signer crypto.Signer, err error) {
|
||||
func newSigner(config *packet.Config) (signer interface{}, err error) {
|
||||
switch config.PublicKeyAlgorithm() {
|
||||
case packet.PubKeyAlgoRSA:
|
||||
bits := config.RSAModulusBits()
|
||||
@@ -257,11 +242,27 @@ func newSigner(config *packet.Config) (signer crypto.Signer, err error) {
|
||||
}
|
||||
return rsa.GenerateKey(config.Random(), bits)
|
||||
case packet.PubKeyAlgoEdDSA:
|
||||
_, priv, err := ed25519.GenerateKey(config.Random())
|
||||
curve := ecc.FindEdDSAByGenName(string(config.CurveName()))
|
||||
if curve == nil {
|
||||
return nil, errors.InvalidArgumentError("unsupported curve")
|
||||
}
|
||||
|
||||
priv, err := eddsa.GenerateKey(config.Random(), curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &priv, nil
|
||||
return priv, nil
|
||||
case packet.PubKeyAlgoECDSA:
|
||||
curve := ecc.FindECDSAByGenName(string(config.CurveName()))
|
||||
if curve == nil {
|
||||
return nil, errors.InvalidArgumentError("unsupported curve")
|
||||
}
|
||||
|
||||
priv, err := ecdsa.GenerateKey(config.Random(), curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return priv, nil
|
||||
default:
|
||||
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
|
||||
}
|
||||
@@ -281,14 +282,18 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
|
||||
return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
|
||||
}
|
||||
return rsa.GenerateKey(config.Random(), bits)
|
||||
case packet.PubKeyAlgoEdDSA:
|
||||
fallthrough // When passing EdDSA, we generate an ECDH subkey
|
||||
case packet.PubKeyAlgoEdDSA, packet.PubKeyAlgoECDSA:
|
||||
fallthrough // When passing EdDSA or ECDSA, we generate an ECDH subkey
|
||||
case packet.PubKeyAlgoECDH:
|
||||
var kdf = ecdh.KDF{
|
||||
Hash: algorithm.SHA512,
|
||||
Cipher: algorithm.AES256,
|
||||
}
|
||||
return ecdh.X25519GenerateKey(config.Random(), kdf)
|
||||
curve := ecc.FindECDHByGenName(string(config.CurveName()))
|
||||
if curve == nil {
|
||||
return nil, errors.InvalidArgumentError("unsupported curve")
|
||||
}
|
||||
return ecdh.GenerateKey(config.Random(), curve, kdf)
|
||||
default:
|
||||
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
|
||||
}
|
||||
|
||||
164
vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
generated
vendored
164
vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
generated
vendored
@@ -87,15 +87,15 @@ func (e *Entity) PrimaryIdentity() *Identity {
|
||||
}
|
||||
|
||||
func shouldPreferIdentity(existingId, potentialNewId *Identity) bool {
|
||||
if (existingId == nil) {
|
||||
if existingId == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if (len(existingId.Revocations) > len(potentialNewId.Revocations)) {
|
||||
if len(existingId.Revocations) > len(potentialNewId.Revocations) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (len(existingId.Revocations) < len(potentialNewId.Revocations)) {
|
||||
if len(existingId.Revocations) < len(potentialNewId.Revocations) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -103,13 +103,13 @@ func shouldPreferIdentity(existingId, potentialNewId *Identity) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if (existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId &&
|
||||
!(potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId)) {
|
||||
if existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId &&
|
||||
!(potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!(existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId) &&
|
||||
potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId) {
|
||||
if !(existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId) &&
|
||||
potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -150,11 +150,9 @@ func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
|
||||
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
|
||||
}
|
||||
|
||||
// If we don't have any candidate subkeys for encryption and
|
||||
// the primary key doesn't have any usage metadata then we
|
||||
// assume that the primary key is ok. Or, if the primary key is
|
||||
// marked as ok to encrypt with, then we can obviously use it.
|
||||
if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
|
||||
// If we don't have any subkeys for encryption and the primary key
|
||||
// is marked as OK to encrypt with, then we can use it.
|
||||
if i.SelfSignature.FlagsValid && i.SelfSignature.FlagEncryptCommunications &&
|
||||
e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
|
||||
return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
|
||||
}
|
||||
@@ -162,6 +160,18 @@ func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
|
||||
return Key{}, false
|
||||
}
|
||||
|
||||
// CertificationKey return the best candidate Key for certifying a key with this
|
||||
// Entity.
|
||||
func (e *Entity) CertificationKey(now time.Time) (Key, bool) {
|
||||
return e.CertificationKeyById(now, 0)
|
||||
}
|
||||
|
||||
// CertificationKeyById return the Key for key certification with this
|
||||
// Entity and keyID.
|
||||
func (e *Entity) CertificationKeyById(now time.Time, id uint64) (Key, bool) {
|
||||
return e.signingKeyByIdUsage(now, id, packet.KeyFlagCertify)
|
||||
}
|
||||
|
||||
// SigningKey return the best candidate Key for signing a message with this
|
||||
// Entity.
|
||||
func (e *Entity) SigningKey(now time.Time) (Key, bool) {
|
||||
@@ -171,6 +181,10 @@ func (e *Entity) SigningKey(now time.Time) (Key, bool) {
|
||||
// SigningKeyById return the Key for signing a message with this
|
||||
// Entity and keyID.
|
||||
func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
|
||||
return e.signingKeyByIdUsage(now, id, packet.KeyFlagSign)
|
||||
}
|
||||
|
||||
func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key, bool) {
|
||||
// Fail to find any signing key if the...
|
||||
i := e.PrimaryIdentity()
|
||||
if e.PrimaryKey.KeyExpired(i.SelfSignature, now) || // primary key has expired
|
||||
@@ -186,7 +200,8 @@ func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
|
||||
var maxTime time.Time
|
||||
for idx, subkey := range e.Subkeys {
|
||||
if subkey.Sig.FlagsValid &&
|
||||
subkey.Sig.FlagSign &&
|
||||
(flags&packet.KeyFlagCertify == 0 || subkey.Sig.FlagCertify) &&
|
||||
(flags&packet.KeyFlagSign == 0 || subkey.Sig.FlagSign) &&
|
||||
subkey.PublicKey.PubKeyAlgo.CanSign() &&
|
||||
!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
|
||||
!subkey.Sig.SigExpired(now) &&
|
||||
@@ -203,10 +218,11 @@ func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
|
||||
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
|
||||
}
|
||||
|
||||
// If we have no candidate subkey then we assume that it's ok to sign
|
||||
// with the primary key. Or, if the primary key is marked as ok to
|
||||
// sign with, then we can use it.
|
||||
if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
|
||||
// If we don't have any subkeys for signing and the primary key
|
||||
// is marked as OK to sign with, then we can use it.
|
||||
if i.SelfSignature.FlagsValid &&
|
||||
(flags&packet.KeyFlagCertify == 0 || i.SelfSignature.FlagCertify) &&
|
||||
(flags&packet.KeyFlagSign == 0 || i.SelfSignature.FlagSign) &&
|
||||
e.PrimaryKey.PubKeyAlgo.CanSign() &&
|
||||
(id == 0 || e.PrimaryKey.KeyId == id) {
|
||||
return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
|
||||
@@ -236,6 +252,44 @@ func (e *Entity) Revoked(now time.Time) bool {
|
||||
return revoked(e.Revocations, now)
|
||||
}
|
||||
|
||||
// EncryptPrivateKeys encrypts all non-encrypted keys in the entity with the same key
|
||||
// derived from the provided passphrase. Public keys and dummy keys are ignored,
|
||||
// and don't cause an error to be returned.
|
||||
func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) error {
|
||||
var keysToEncrypt []*packet.PrivateKey
|
||||
// Add entity private key to encrypt.
|
||||
if e.PrivateKey != nil && !e.PrivateKey.Dummy() && !e.PrivateKey.Encrypted {
|
||||
keysToEncrypt = append(keysToEncrypt, e.PrivateKey)
|
||||
}
|
||||
|
||||
// Add subkeys to encrypt.
|
||||
for _, sub := range e.Subkeys {
|
||||
if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && !sub.PrivateKey.Encrypted {
|
||||
keysToEncrypt = append(keysToEncrypt, sub.PrivateKey)
|
||||
}
|
||||
}
|
||||
return packet.EncryptPrivateKeys(keysToEncrypt, passphrase, config)
|
||||
}
|
||||
|
||||
// DecryptPrivateKeys decrypts all encrypted keys in the entitiy with the given passphrase.
|
||||
// Avoids recomputation of similar s2k key derivations. Public keys and dummy keys are ignored,
|
||||
// and don't cause an error to be returned.
|
||||
func (e *Entity) DecryptPrivateKeys(passphrase []byte) error {
|
||||
var keysToDecrypt []*packet.PrivateKey
|
||||
// Add entity private key to decrypt.
|
||||
if e.PrivateKey != nil && !e.PrivateKey.Dummy() && e.PrivateKey.Encrypted {
|
||||
keysToDecrypt = append(keysToDecrypt, e.PrivateKey)
|
||||
}
|
||||
|
||||
// Add subkeys to decrypt.
|
||||
for _, sub := range e.Subkeys {
|
||||
if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && sub.PrivateKey.Encrypted {
|
||||
keysToDecrypt = append(keysToDecrypt, sub.PrivateKey)
|
||||
}
|
||||
}
|
||||
return packet.DecryptPrivateKeys(keysToDecrypt, passphrase)
|
||||
}
|
||||
|
||||
// Revoked returns whether the identity has been revoked by a self-signature.
|
||||
// Note that third-party revocation signatures are not supported.
|
||||
func (i *Identity) Revoked(now time.Time) bool {
|
||||
@@ -283,7 +337,11 @@ func (el EntityList) KeysById(id uint64) (keys []Key) {
|
||||
// the bitwise-OR of packet.KeyFlag* values.
|
||||
func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
|
||||
for _, key := range el.KeysById(id) {
|
||||
if key.SelfSignature != nil && key.SelfSignature.FlagsValid && requiredUsage != 0 {
|
||||
if requiredUsage != 0 {
|
||||
if key.SelfSignature == nil || !key.SelfSignature.FlagsValid {
|
||||
continue
|
||||
}
|
||||
|
||||
var usage byte
|
||||
if key.SelfSignature.FlagCertify {
|
||||
usage |= packet.KeyFlagCertify
|
||||
@@ -311,7 +369,7 @@ func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
|
||||
func (el EntityList) DecryptionKeys() (keys []Key) {
|
||||
for _, e := range el {
|
||||
for _, subKey := range e.Subkeys {
|
||||
if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
|
||||
if subKey.PrivateKey != nil && subKey.Sig.FlagsValid && (subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
|
||||
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
|
||||
}
|
||||
}
|
||||
@@ -446,7 +504,7 @@ EachPacket:
|
||||
// Else, ignoring the signature as it does not follow anything
|
||||
// we would know to attach it to.
|
||||
case *packet.PrivateKey:
|
||||
if pkt.IsSubkey == false {
|
||||
if !pkt.IsSubkey {
|
||||
packets.Unread(p)
|
||||
break EachPacket
|
||||
}
|
||||
@@ -455,7 +513,7 @@ EachPacket:
|
||||
return nil, err
|
||||
}
|
||||
case *packet.PublicKey:
|
||||
if pkt.IsSubkey == false {
|
||||
if !pkt.IsSubkey {
|
||||
packets.Unread(p)
|
||||
break EachPacket
|
||||
}
|
||||
@@ -515,7 +573,6 @@ func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error {
|
||||
return errors.StructuralError("user ID signature with wrong type")
|
||||
}
|
||||
|
||||
|
||||
if sig.CheckKeyIdOrFingerprint(e.PrimaryKey) {
|
||||
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
|
||||
return errors.StructuralError("user ID self-signature invalid: " + err.Error())
|
||||
@@ -629,18 +686,12 @@ func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign boo
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, revocation := range ident.Revocations {
|
||||
err := revocation.Serialize(w)
|
||||
for _, sig := range ident.Signatures {
|
||||
err = sig.Serialize(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ident.SelfSignature != nil {
|
||||
err = ident.SelfSignature.Serialize(w)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, subkey := range e.Subkeys {
|
||||
err = subkey.PrivateKey.Serialize(w)
|
||||
@@ -724,26 +775,31 @@ func (e *Entity) Serialize(w io.Writer) error {
|
||||
// necessary.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
|
||||
if signer.PrivateKey == nil {
|
||||
return errors.InvalidArgumentError("signing Entity must have a private key")
|
||||
certificationKey, ok := signer.CertificationKey(config.Now())
|
||||
if !ok {
|
||||
return errors.InvalidArgumentError("no valid certification key found")
|
||||
}
|
||||
if signer.PrivateKey.Encrypted {
|
||||
|
||||
if certificationKey.PrivateKey.Encrypted {
|
||||
return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
|
||||
}
|
||||
|
||||
ident, ok := e.Identities[identity]
|
||||
if !ok {
|
||||
return errors.InvalidArgumentError("given identity string not found in Entity")
|
||||
}
|
||||
|
||||
sig := &packet.Signature{
|
||||
Version: signer.PrivateKey.Version,
|
||||
SigType: packet.SigTypeGenericCert,
|
||||
PubKeyAlgo: signer.PrivateKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
CreationTime: config.Now(),
|
||||
IssuerKeyId: &signer.PrivateKey.KeyId,
|
||||
sig := createSignaturePacket(certificationKey.PublicKey, packet.SigTypeGenericCert, config)
|
||||
|
||||
signingUserID := config.SigningUserId()
|
||||
if signingUserID != "" {
|
||||
if _, ok := signer.Identities[signingUserID]; !ok {
|
||||
return errors.InvalidArgumentError("signer identity string not found in signer Entity")
|
||||
}
|
||||
sig.SignerUserId = &signingUserID
|
||||
}
|
||||
if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
|
||||
|
||||
if err := sig.SignUserId(identity, e.PrimaryKey, certificationKey.PrivateKey, config); err != nil {
|
||||
return err
|
||||
}
|
||||
ident.Signatures = append(ident.Signatures, sig)
|
||||
@@ -754,16 +810,9 @@ func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Co
|
||||
// specified reason code and text (RFC4880 section-5.2.3.23).
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
|
||||
revSig := &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: config.Now(),
|
||||
SigType: packet.SigTypeKeyRevocation,
|
||||
PubKeyAlgo: e.PrimaryKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
RevocationReason: &reason,
|
||||
RevocationReasonText: reasonText,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
}
|
||||
revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeKeyRevocation, config)
|
||||
revSig.RevocationReason = &reason
|
||||
revSig.RevocationReasonText = reasonText
|
||||
|
||||
if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil {
|
||||
return err
|
||||
@@ -780,16 +829,9 @@ func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, rea
|
||||
return errors.InvalidArgumentError("given subkey is not associated with this key")
|
||||
}
|
||||
|
||||
revSig := &packet.Signature{
|
||||
Version: e.PrimaryKey.Version,
|
||||
CreationTime: config.Now(),
|
||||
SigType: packet.SigTypeSubkeyRevocation,
|
||||
PubKeyAlgo: e.PrimaryKey.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
RevocationReason: &reason,
|
||||
RevocationReasonText: reasonText,
|
||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
||||
}
|
||||
revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyRevocation, config)
|
||||
revSig.RevocationReason = &reason
|
||||
revSig.RevocationReasonText = reasonText
|
||||
|
||||
if err := revSig.RevokeSubkey(sk.PublicKey, e.PrivateKey, config); err != nil {
|
||||
return err
|
||||
|
||||
138
vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go
generated
vendored
138
vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go
generated
vendored
@@ -398,3 +398,141 @@ sr92MA2+k901WeISR7qEzcI0Fdg8AyFAExaEK6VyjP7SXGLwvfisw34OxuZr3qmx
|
||||
I+KgLycyeDvGoBj0HCLO3gVaBe4ubVrj5KjhX2PVNEJd3XZRzaXZE2aAMQ==
|
||||
=AmgT
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
const rsa2048PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Comment: gpg (GnuPG) 2.2.27 with libgcrypt 1.9.4
|
||||
|
||||
lQPGBGL07P0BCADL0etN8efyAXA6sL2WfQvHe5wEKYXPWeN2+jiqSppfeRZAOlzP
|
||||
kZ3U+cloeJriplYvVJwI3ID2aw52Z/TRn8iKRP5eOUFrEgcgl06lazLtOndK7o7p
|
||||
oBV5mLtHEirFHm6W61fNt10jzM0jx0PV6nseLhFB2J42F1cmU/aBgFo41wjLSZYr
|
||||
owR+v+O9S5sUXblQF6sEDcY01sBEu09zrIgT49VFwQ1Cvdh9XZEOTQBfdiugoj5a
|
||||
DS3fAqAka3r1VoQK4eR7/upnYSgSACGeaQ4pUelKku5rpm50gdWTY8ppq0k9e1eT
|
||||
y2x0OQcW3hWE+j4os1ca0ZEADMdqr/99MOxrABEBAAH+BwMCJWxU4VOZOJ7/I6vX
|
||||
FxdfBhIBEXlJ52FM3S/oYtXqLhkGyrtmZOeEazVvUtuCe3M3ScHI8xCthcmE8E0j
|
||||
bi+ZEHPS2NiBZtgHFF27BLn7zZuTc+oD5WKduZdK3463egnyThTqIIMl25WZBuab
|
||||
k5ycwYrWwBH0jfA4gwJ13ai4pufKC2RM8qIu6YAVPglYBKFLKGvvJHa5vI+LuA0E
|
||||
K+k35hIic7yVUcQneNnAF2598X5yWiieYnOZpmHlRw1zfbMwOJr3ZNj2v94u7b+L
|
||||
sTa/1Uv9887Vb6sJp0c2Sh4cwEccoPYkvMqFn3ZrJUr3UdDu1K2vWohPtswzhrYV
|
||||
+RdPZE5RLoCQufKvlPezk0Pzhzb3bBU7XjUbdGY1nH/EyQeBNp+Gw6qldKvzcBaB
|
||||
cyOK1c6hPSszpJX93m5UxCN55IeifmcNjmbDh8vGCCdajy6d56qV2n4F3k7vt1J1
|
||||
0UlxIGhqijJoaTCX66xjLMC6VXkSz6aHQ35rnXosm/cqPcQshsZTdlfSyWkorfdr
|
||||
4Hj8viBER26mjYurTMLBKDtUN724ZrR0Ev5jorX9uoKlgl87bDZHty2Ku2S+vR68
|
||||
VAvnj6Fi1BYNclnDoqxdRB2z5T9JbWE52HuG83/QsplhEqXxESDxriTyTHMbNxEe
|
||||
88soVCDh4tgflZFa2ucUr6gEKJKij7jgahARnyaXfPZlQBUAS1YUeILYmN+VR+M/
|
||||
sHENpwDWc7TInn8VN638nJV+ScZGMih3AwWZTIoiLju3MMt1K0YZ3NuiqwGH4Jwg
|
||||
/BbEdTWeCci9y3NEQHQ3uZZ5p6j2CwFVlK11idemCMvAiTVxF+gKdaLMkeCwKxru
|
||||
J3YzhKEo+iDVYbPYBYizx/EHBn2U5kITQ5SBXzjTaaFMNZJEf9JYsL1ybPB6HOFY
|
||||
VNVB2KT8CGVwtCJHb2xhbmcgR29waGVyIDxnb2xhbmdAZXhhbXBsZS5vcmc+iQFO
|
||||
BBMBCgA4FiEEC6K7U7f4qesybTnqSkra7gHusm0FAmL07P0CGwMFCwkIBwIGFQoJ
|
||||
CAsCBBYCAwECHgECF4AACgkQSkra7gHusm1MvwgAxpClWkeSqIhMQfbiuz0+lOkE
|
||||
89y1DCFw8bHjZoUf4/4K8hFA3dGkk+q72XFgiyaCpfXxMt6Gi+dN47t+tTv9NIqC
|
||||
sukbaoJBmJDhN6+djmJOgOYy+FWsW2LAk2LOwKYulpnBZdcA5rlMAhBg7gevQpF+
|
||||
ruSU69P7UUaFJl/DC7hDmaIcj+4cjBE/HO26SnVQjoTfjZT82rDh1Wsuf8LnkJUk
|
||||
b3wezBLpXKjDvdHikdv4gdlR4AputVM38aZntYYglh/EASo5TneyZ7ZscdLNRdcF
|
||||
r5O2fKqrOJLOdaoYRFZZWOvP5GtEVFDU7WGivOSVfiszBE0wZR3dgZRJipHCXJ0D
|
||||
xgRi9Oz9AQgAtMJcJqLLVANJHl90tWuoizDkm+Imcwq2ubQAjpclnNrODnDK+7o4
|
||||
pBsWmXbZSdkC4gY+LhOQA6bPDD0JEHM58DOnrm49BddxXAyK0HPsk4sGGt2SS86B
|
||||
OawWNdfJVyqw4bAiHWDmQg4PcjBbt3ocOIxAR6I5kBSiQVxuGQs9T+Zvg3G1r3Or
|
||||
fS6DzlgY3HFUML5YsGH4lOxNSOoKAP68GIH/WNdUZ+feiRg9knIib6I3Hgtf5eO8
|
||||
JRH7aWE/TD7eNu36bLLjT5TZPq5r6xaD2plbtPOyXbNPWs9qI1yG+VnErfaLY0w8
|
||||
Qo0aqzbgID+CTZVomXSOpOcQseaFKw8ZfQARAQAB/gcDArha6+/+d4OY/w9N32K9
|
||||
hFNYt4LufTETMQ+k/sBeaMuAVzmT47DlAXzkrZhGW4dZOtXMu1rXaUwHlqkhEyzL
|
||||
L4MYEWVXfD+LbZNEK3MEFss6RK+UAMeT/PTV9aA8cXQVPcSJYzfBXHQ1U1hnOgrO
|
||||
apn92MN8RmkhX8wJLyeWTMMuP4lXByJMmmGo8WvifeRD2kFY4y0WVBDAXJAV4Ljf
|
||||
Di/bBiwoc5a+gxHuZT2W9ZSxBQJNXdt4Un2IlyZuo58s5MLx2N0EaNJ8PwRUE6fM
|
||||
RZYO8aZCEPUtINE4njbvsWOMCtrblsMPwZ1B0SiIaWmLaNyGdCNKea+fCIW7kasC
|
||||
JYMhnLumpUTXg5HNexkCsl7ABWj0PYBflOE61h8EjWpnQ7JBBVKS2ua4lMjwHRX7
|
||||
5o5yxym9k5UZNFdGoXVL7xpizCcdGawxTJvwhs3vBqu1ZWYCegOAZWDrOkCyhUpq
|
||||
8uKMROZFbn+FwE+7tjt+v2ed62FVEvD6g4V3ThCA6mQqeOARfJWN8GZY8BDm8lht
|
||||
crOXriUkrx+FlrgGtm2CkwjW5/9Xd7AhFpHnQdFeozOHyq1asNSgJF9sNi9Lz94W
|
||||
skQSVRi0IExxSXYGI3Y0nnAZUe2BAQflYPJdEveSr3sKlUqXiETTA1VXsTPK3kOC
|
||||
92CbLzj/Hz199jZvywwyu53I+GKMpF42rMq7zxr2oa61YWY4YE/GDezwwys/wLx/
|
||||
QpCW4X3ppI7wJjCSSqEV0baYZSSli1ayheS6dxi8QnSpX1Bmpz6gU7m/M9Sns+hl
|
||||
J7ZvgpjCAiV7KJTjtclr5/S02zP78LTVkoTWoz/6MOTROwaP63VBUXX8pbJhf/vu
|
||||
DLmNnDk8joMJxoDXWeNU0EnNl4hP7Z/jExRBOEO4oAnUf/Sf6gCWQhL5qcajtg6w
|
||||
tGv7vx3f2IkBNgQYAQoAIBYhBAuiu1O3+KnrMm056kpK2u4B7rJtBQJi9Oz9AhsM
|
||||
AAoJEEpK2u4B7rJt6lgIAMBWqP4BCOGnQXBbgJ0+ACVghpkFUXZTb/tXJc8UUvTM
|
||||
8uov6k/RsqDGZrvhhufD7Wwt7j9v7dD7VPp7bPyjVWyimglQzWguTUUqLDGlstYH
|
||||
5uYv1pzma0ZsAGNqFeGlTLsKOSGKFMH4rB2KfN2n51L8POvtp1y7GKZQbWIWneaB
|
||||
cZr3BINU5GMvYYU7pAYcoR+mJPdJx5Up3Ocn+bn8Tu1sy9C/ArtCQucazGnoE9u1
|
||||
HhNLrh0CdzzX7TNH6TQ8LwPOvq0K5l/WqbN9lE0WBBhMv2HydxhluO8AhU+A5GqC
|
||||
C+wET7nVDnhoOm/fstIeb7/LN7OYejKPeHdFBJEL9GA=
|
||||
=u442
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const curve25519PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Comment: gpg (GnuPG) 2.2.27 with libgcrypt 1.9.4
|
||||
|
||||
lFgEYvTtQBYJKwYBBAHaRw8BAQdAxsNXLbrk5xOjpO24VhOMvQ0/F+JcyIkckMDH
|
||||
X3FIGxcAAQDFOlunZWYuPsCx5JLp78vKqUTfgef9TGG4oD6I/Sa0zBMstCJHb2xh
|
||||
bmcgR29waGVyIDxnb2xhbmdAZXhhbXBsZS5vcmc+iJAEExYIADgWIQSFQHEOazmo
|
||||
h1ldII4MvfnLQ4JBNwUCYvTtQAIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAK
|
||||
CRAMvfnLQ4JBN5yeAQCKdry8B5ScCPrev2+UByMCss7Sdu5RhomCFsHdNPLcKAEA
|
||||
8ugei+1owHsV+3cGwWWzKk6sLa8ZN87i3SKuOGp9DQycXQRi9O1AEgorBgEEAZdV
|
||||
AQUBAQdA5CubPp8l7lrVQ25h7Hx5XN2C8xanRnnpcjzEooCaEA0DAQgHAAD/Rpc+
|
||||
sOZUXrFk9HOWB1XU41LoWbDBoG8sP8RWAVYwD5AQRYh4BBgWCAAgFiEEhUBxDms5
|
||||
qIdZXSCODL35y0OCQTcFAmL07UACGwwACgkQDL35y0OCQTcvdwEA7lb5g/YisrEf
|
||||
iq660uwMGoepLUfvtqKzuQ6heYe83y0BAN65Ffg5HYOJzUEi0kZQRf7OhdtuL2kJ
|
||||
SRXn8DmCTfEB
|
||||
=cELM
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const curve448PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Comment: C1DB 65D5 80D7 B922 7254 4B1E A699 9895 FABA CE52
|
||||
|
||||
xYUEYV2UmRYDK2VxAc9AFyxgh5xnSbyt50TWl558mw9xdMN+/UBLr5+UMP8IsrvV
|
||||
MdXuTIE8CyaUQKSotHtH2RkYEXj5nsMAAAHPQIbTMSzjIWug8UFECzAex5FHgAgH
|
||||
gYF3RK+TS8D24wX8kOu2C/NoVxwGY+p+i0JHaB+7yljriSKAGxs6wsBEBB8WCgCD
|
||||
BYJhXZSZBYkFpI+9AwsJBwkQppmYlfq6zlJHFAAAAAAAHgAgc2FsdEBub3RhdGlv
|
||||
bnMuc2VxdW9pYS1wZ3Aub3Jn5wSpIutJ5HncJWk4ruUV8GzQF390rR5+qWEAnAoY
|
||||
akcDFQoIApsBAh4BFiEEwdtl1YDXuSJyVEseppmYlfq6zlIAALzdA5dA/fsgYg/J
|
||||
qaQriYKaPUkyHL7EB3BXhV2d1h/gk+qJLvXQuU2WEJ/XSs3GrsBRiiZwvPH4o+7b
|
||||
mleAxjy5wpS523vqrrBR2YZ5FwIku7WS4litSdn4AtVam/TlLdMNIf41CtFeZKBe
|
||||
c5R5VNdQy8y7qy8AAADNEUN1cnZlNDQ4IE9wdGlvbiA4wsBHBBMWCgCGBYJhXZSZ
|
||||
BYkFpI+9AwsJBwkQppmYlfq6zlJHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2Vx
|
||||
dW9pYS1wZ3Aub3JnD55UsYMzE6OACP+mgw5zvT+BBgol8/uFQjHg4krjUCMDFQoI
|
||||
ApkBApsBAh4BFiEEwdtl1YDXuSJyVEseppmYlfq6zlIAAPQJA5dA0Xqwzn/0uwCq
|
||||
RlsOVCB3f5NOj1exKnlBvRw0xT1VBee1yxvlUt5eIAoCxWoRlWBJob3TTkhm9AEA
|
||||
8dyhwPmyGfWHzPw5NFG3xsXrZdNXNvit9WMVAPcmsyR7teXuDlJItxRAdJJc/qfJ
|
||||
YVbBFoaNrhYAAADHhQRhXZSZFgMrZXEBz0BL7THZ9MnCLfSPJ1FMLim9eGkQ3Bfn
|
||||
M3he5rOwO3t14QI1LjI96OjkeJipMgcFAmEP1Bq/ZHGO7oAAAc9AFnE8iNBaT3OU
|
||||
EFtxkmWHXtdaYMmGGRdopw9JPXr/UxuunDln5o9dxPxf7q7z26zXrZen+qed/Isa
|
||||
HsDCwSwEGBYKAWsFgmFdlJkFiQWkj70JEKaZmJX6us5SRxQAAAAAAB4AIHNhbHRA
|
||||
bm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZxREUizdTcepBzgSMOv2VWQCWbl++3CZ
|
||||
EbgAWDryvSsyApsCwDGgBBkWCgBvBYJhXZSZCRBKo3SL4S5djkcUAAAAAAAeACBz
|
||||
YWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmemoGTDjmNQiIzw6HOEddvS0OB7
|
||||
UZ/P07jM/EVmnYxTlBYhBAxsnkGpx1UCiH6gUUqjdIvhLl2OAAALYQOXQAMB1oKq
|
||||
OWxSFmvmgCKNcbAAyA3piF5ERIqs4z07oJvqDYrOWt75UsEIH/04gU/vHc4EmfG2
|
||||
JDLJgOLlyTUPkL/08f0ydGZPofFQBhn8HkuFFjnNtJ5oz3GIP4cdWMQFaUw0uvjb
|
||||
PM9Tm3ptENGd6Ts1AAAAFiEEwdtl1YDXuSJyVEseppmYlfq6zlIAAGpTA5dATR6i
|
||||
U2GrpUcQgpG+JqfAsGmF4yAOhgFxc1UfidFk3nTup3fLgjipkYY170WLRNbyKkVO
|
||||
Sodx93GAs58rizO1acDAWiLq3cyEPBFXbyFThbcNPcLl+/77Uk/mgkYrPQFAQWdK
|
||||
1kSRm4SizDBK37K8ChAAAADHhwRhXZSZEgMrZW8Bx0DMhzvhQo+OsXeqQ6QVw4sF
|
||||
CaexHh6rLohh7TzL3hQSjoJ27fV6JBkIWdn0LfrMlJIDbSv2SLdlgQMBCgkAAcdA
|
||||
MO7Dc1myF6Co1fAH+EuP+OxhxP/7V6ljuSCZENDfA49tQkzTta+PniG+pOVB2LHb
|
||||
huyaKBkqiaogo8LAOQQYFgoAeAWCYV2UmQWJBaSPvQkQppmYlfq6zlJHFAAAAAAA
|
||||
HgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3JnEjBMQAmc/2u45u5FQGmB
|
||||
QAytjSG2LM3JQN+PPVl5vEkCmwwWIQTB22XVgNe5InJUSx6mmZiV+rrOUgAASdYD
|
||||
l0DXEHQ9ykNP2rZP35ET1dmiFagFtTj/hLQcWlg16LqvJNGqOgYXuqTerbiOOt02
|
||||
XLCBln+wdewpU4ChEffMUDRBfqfQco/YsMqWV7bHJHAO0eC/DMKCjyU90xdH7R/d
|
||||
QgqsfguR1PqPuJxpXV4bSr6CGAAAAA==
|
||||
=MSvh
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
||||
const keyWithNotation = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
xVgEY9gIshYJKwYBBAHaRw8BAQdAF25fSM8OpFlXZhop4Qpqo5ywGZ4jgWlR
|
||||
ppjhIKDthREAAQC+LFpzFcMJYcjxGKzBGHN0Px2jU4d04YSRnFAik+lVVQ6u
|
||||
zRdUZXN0IDx0ZXN0QGV4YW1wbGUuY29tPsLACgQQFgoAfAUCY9gIsgQLCQcI
|
||||
CRD/utJOCym8pR0UgAAAAAAQAAR0ZXh0QGV4YW1wbGUuY29tdGVzdB8UAAAA
|
||||
AAASAARiaW5hcnlAZXhhbXBsZS5jb20AAQIDAxUICgQWAAIBAhkBAhsDAh4B
|
||||
FiEEEMCQTUVGKgCX5rDQ/7rSTgspvKUAAPl5AP9Npz90LxzrB97Qr2DrGwfG
|
||||
wuYn4FSYwtuPfZHHeoIabwD/QEbvpQJ/NBb9EAZuow4Rirlt1yv19mmnF+j5
|
||||
8yUzhQjHXQRj2AiyEgorBgEEAZdVAQUBAQdARXAo30DmKcyUg6co7OUm0RNT
|
||||
z9iqFbDBzA8A47JEt1MDAQgHAAD/XKK3lBm0SqMR558HLWdBrNG6NqKuqb5X
|
||||
joCML987ZNgRD8J4BBgWCAAqBQJj2AiyCRD/utJOCym8pQIbDBYhBBDAkE1F
|
||||
RioAl+aw0P+60k4LKbylAADRxgEAg7UfBDiDPp5LHcW9D+SgFHk6+GyEU4ev
|
||||
VppQxdtxPvAA/34snHBX7Twnip1nMt7P4e2hDiw/hwQ7oqioOvc6jMkP
|
||||
=Z8YJ
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
`
|
||||
|
||||
21
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
21
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
@@ -4,6 +4,14 @@ package packet
|
||||
|
||||
import "math/bits"
|
||||
|
||||
// CipherSuite contains a combination of Cipher and Mode
|
||||
type CipherSuite struct {
|
||||
// The cipher function
|
||||
Cipher CipherFunction
|
||||
// The AEAD mode of operation.
|
||||
Mode AEADMode
|
||||
}
|
||||
|
||||
// AEADConfig collects a number of AEAD parameters along with sensible defaults.
|
||||
// A nil AEADConfig is valid and results in all default values.
|
||||
type AEADConfig struct {
|
||||
@@ -15,12 +23,13 @@ type AEADConfig struct {
|
||||
|
||||
// Mode returns the AEAD mode of operation.
|
||||
func (conf *AEADConfig) Mode() AEADMode {
|
||||
// If no preference is specified, OCB is used (which is mandatory to implement).
|
||||
if conf == nil || conf.DefaultMode == 0 {
|
||||
return AEADModeEAX
|
||||
return AEADModeOCB
|
||||
}
|
||||
|
||||
mode := conf.DefaultMode
|
||||
if mode != AEADModeEAX && mode != AEADModeOCB &&
|
||||
mode != AEADModeExperimentalGCM {
|
||||
if mode != AEADModeEAX && mode != AEADModeOCB && mode != AEADModeGCM {
|
||||
panic("AEAD mode unsupported")
|
||||
}
|
||||
return mode
|
||||
@@ -28,6 +37,8 @@ func (conf *AEADConfig) Mode() AEADMode {
|
||||
|
||||
// ChunkSizeByte returns the byte indicating the chunk size. The effective
|
||||
// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6)
|
||||
// limit to 16 = 4 MiB
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
|
||||
func (conf *AEADConfig) ChunkSizeByte() byte {
|
||||
if conf == nil || conf.ChunkSize == 0 {
|
||||
return 12 // 1 << (12 + 6) == 262144 bytes
|
||||
@@ -38,8 +49,8 @@ func (conf *AEADConfig) ChunkSizeByte() byte {
|
||||
switch {
|
||||
case exponent < 6:
|
||||
exponent = 6
|
||||
case exponent > 27:
|
||||
exponent = 27
|
||||
case exponent > 16:
|
||||
exponent = 16
|
||||
}
|
||||
|
||||
return byte(exponent - 6)
|
||||
|
||||
264
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
generated
vendored
Normal file
264
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
// Copyright (C) 2019 ProtonTech AG
|
||||
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// aeadCrypter is an AEAD opener/sealer, its configuration, and data for en/decryption.
|
||||
type aeadCrypter struct {
|
||||
aead cipher.AEAD
|
||||
chunkSize int
|
||||
initialNonce []byte
|
||||
associatedData []byte // Chunk-independent associated data
|
||||
chunkIndex []byte // Chunk counter
|
||||
packetTag packetType // SEIP packet (v2) or AEAD Encrypted Data packet
|
||||
bytesProcessed int // Amount of plaintext bytes encrypted/decrypted
|
||||
buffer bytes.Buffer // Buffered bytes across chunks
|
||||
}
|
||||
|
||||
// computeNonce takes the incremental index and computes an eXclusive OR with
|
||||
// the least significant 8 bytes of the receivers' initial nonce (see sec.
|
||||
// 5.16.1 and 5.16.2). It returns the resulting nonce.
|
||||
func (wo *aeadCrypter) computeNextNonce() (nonce []byte) {
|
||||
if wo.packetTag == packetTypeSymmetricallyEncryptedIntegrityProtected {
|
||||
return append(wo.initialNonce, wo.chunkIndex...)
|
||||
}
|
||||
|
||||
nonce = make([]byte, len(wo.initialNonce))
|
||||
copy(nonce, wo.initialNonce)
|
||||
offset := len(wo.initialNonce) - 8
|
||||
for i := 0; i < 8; i++ {
|
||||
nonce[i+offset] ^= wo.chunkIndex[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// incrementIndex performs an integer increment by 1 of the integer represented by the
|
||||
// slice, modifying it accordingly.
|
||||
func (wo *aeadCrypter) incrementIndex() error {
|
||||
index := wo.chunkIndex
|
||||
if len(index) == 0 {
|
||||
return errors.AEADError("Index has length 0")
|
||||
}
|
||||
for i := len(index) - 1; i >= 0; i-- {
|
||||
if index[i] < 255 {
|
||||
index[i]++
|
||||
return nil
|
||||
}
|
||||
index[i] = 0
|
||||
}
|
||||
return errors.AEADError("cannot further increment index")
|
||||
}
|
||||
|
||||
// aeadDecrypter reads and decrypts bytes. It buffers extra decrypted bytes when
|
||||
// necessary, similar to aeadEncrypter.
|
||||
type aeadDecrypter struct {
|
||||
aeadCrypter // Embedded ciphertext opener
|
||||
reader io.Reader // 'reader' is a partialLengthReader
|
||||
peekedBytes []byte // Used to detect last chunk
|
||||
eof bool
|
||||
}
|
||||
|
||||
// Read decrypts bytes and reads them into dst. It decrypts when necessary and
|
||||
// buffers extra decrypted bytes. It returns the number of bytes copied into dst
|
||||
// and an error.
|
||||
func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
|
||||
// Return buffered plaintext bytes from previous calls
|
||||
if ar.buffer.Len() > 0 {
|
||||
return ar.buffer.Read(dst)
|
||||
}
|
||||
|
||||
// Return EOF if we've previously validated the final tag
|
||||
if ar.eof {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
// Read a chunk
|
||||
tagLen := ar.aead.Overhead()
|
||||
cipherChunkBuf := new(bytes.Buffer)
|
||||
_, errRead := io.CopyN(cipherChunkBuf, ar.reader, int64(ar.chunkSize+tagLen))
|
||||
cipherChunk := cipherChunkBuf.Bytes()
|
||||
if errRead != nil && errRead != io.EOF {
|
||||
return 0, errRead
|
||||
}
|
||||
decrypted, errChunk := ar.openChunk(cipherChunk)
|
||||
if errChunk != nil {
|
||||
return 0, errChunk
|
||||
}
|
||||
|
||||
// Return decrypted bytes, buffering if necessary
|
||||
if len(dst) < len(decrypted) {
|
||||
n = copy(dst, decrypted[:len(dst)])
|
||||
ar.buffer.Write(decrypted[len(dst):])
|
||||
} else {
|
||||
n = copy(dst, decrypted)
|
||||
}
|
||||
|
||||
// Check final authentication tag
|
||||
if errRead == io.EOF {
|
||||
errChunk := ar.validateFinalTag(ar.peekedBytes)
|
||||
if errChunk != nil {
|
||||
return n, errChunk
|
||||
}
|
||||
ar.eof = true // Mark EOF for when we've returned all buffered data
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close is noOp. The final authentication tag of the stream was already
|
||||
// checked in the last Read call. In the future, this function could be used to
|
||||
// wipe the reader and peeked, decrypted bytes, if necessary.
|
||||
func (ar *aeadDecrypter) Close() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// openChunk decrypts and checks integrity of an encrypted chunk, returning
|
||||
// the underlying plaintext and an error. It accesses peeked bytes from next
|
||||
// chunk, to identify the last chunk and decrypt/validate accordingly.
|
||||
func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) {
|
||||
tagLen := ar.aead.Overhead()
|
||||
// Restore carried bytes from last call
|
||||
chunkExtra := append(ar.peekedBytes, data...)
|
||||
// 'chunk' contains encrypted bytes, followed by an authentication tag.
|
||||
chunk := chunkExtra[:len(chunkExtra)-tagLen]
|
||||
ar.peekedBytes = chunkExtra[len(chunkExtra)-tagLen:]
|
||||
|
||||
adata := ar.associatedData
|
||||
if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted {
|
||||
adata = append(ar.associatedData, ar.chunkIndex...)
|
||||
}
|
||||
|
||||
nonce := ar.computeNextNonce()
|
||||
plainChunk, err := ar.aead.Open(nil, nonce, chunk, adata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ar.bytesProcessed += len(plainChunk)
|
||||
if err = ar.aeadCrypter.incrementIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plainChunk, nil
|
||||
}
|
||||
|
||||
// Checks the summary tag. It takes into account the total decrypted bytes into
|
||||
// the associated data. It returns an error, or nil if the tag is valid.
|
||||
func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
|
||||
// Associated: tag, version, cipher, aead, chunk size, ...
|
||||
amountBytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(amountBytes, uint64(ar.bytesProcessed))
|
||||
|
||||
adata := ar.associatedData
|
||||
if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted {
|
||||
// ... index ...
|
||||
adata = append(ar.associatedData, ar.chunkIndex...)
|
||||
}
|
||||
|
||||
// ... and total number of encrypted octets
|
||||
adata = append(adata, amountBytes...)
|
||||
nonce := ar.computeNextNonce()
|
||||
_, err := ar.aead.Open(nil, nonce, tag, adata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// aeadEncrypter encrypts and writes bytes. It encrypts when necessary according
|
||||
// to the AEAD block size, and buffers the extra encrypted bytes for next write.
|
||||
type aeadEncrypter struct {
|
||||
aeadCrypter // Embedded plaintext sealer
|
||||
writer io.WriteCloser // 'writer' is a partialLengthWriter
|
||||
}
|
||||
|
||||
// Write encrypts and writes bytes. It encrypts when necessary and buffers extra
|
||||
// plaintext bytes for next call. When the stream is finished, Close() MUST be
|
||||
// called to append the final tag.
|
||||
func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) {
|
||||
// Append plaintextBytes to existing buffered bytes
|
||||
n, err = aw.buffer.Write(plaintextBytes)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
// Encrypt and write chunks
|
||||
for aw.buffer.Len() >= aw.chunkSize {
|
||||
plainChunk := aw.buffer.Next(aw.chunkSize)
|
||||
encryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
_, err = aw.writer.Write(encryptedChunk)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close encrypts and writes the remaining buffered plaintext if any, appends
|
||||
// the final authentication tag, and closes the embedded writer. This function
|
||||
// MUST be called at the end of a stream.
|
||||
func (aw *aeadEncrypter) Close() (err error) {
|
||||
// Encrypt and write a chunk if there's buffered data left, or if we haven't
|
||||
// written any chunks yet.
|
||||
if aw.buffer.Len() > 0 || aw.bytesProcessed == 0 {
|
||||
plainChunk := aw.buffer.Bytes()
|
||||
lastEncryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = aw.writer.Write(lastEncryptedChunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Compute final tag (associated data: packet tag, version, cipher, aead,
|
||||
// chunk size...
|
||||
adata := aw.associatedData
|
||||
|
||||
if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted {
|
||||
// ... index ...
|
||||
adata = append(aw.associatedData, aw.chunkIndex...)
|
||||
}
|
||||
|
||||
// ... and total number of encrypted octets
|
||||
amountBytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(amountBytes, uint64(aw.bytesProcessed))
|
||||
adata = append(adata, amountBytes...)
|
||||
|
||||
nonce := aw.computeNextNonce()
|
||||
finalTag := aw.aead.Seal(nil, nonce, nil, adata)
|
||||
_, err = aw.writer.Write(finalTag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return aw.writer.Close()
|
||||
}
|
||||
|
||||
// sealChunk Encrypts and authenticates the given chunk.
|
||||
func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) {
|
||||
if len(data) > aw.chunkSize {
|
||||
return nil, errors.AEADError("chunk exceeds maximum length")
|
||||
}
|
||||
if aw.associatedData == nil {
|
||||
return nil, errors.AEADError("can't seal without headers")
|
||||
}
|
||||
adata := aw.associatedData
|
||||
if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted {
|
||||
adata = append(aw.associatedData, aw.chunkIndex...)
|
||||
}
|
||||
|
||||
nonce := aw.computeNextNonce()
|
||||
encrypted := aw.aead.Seal(nil, nonce, data, adata)
|
||||
aw.bytesProcessed += len(data)
|
||||
if err := aw.aeadCrypter.incrementIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encrypted, nil
|
||||
}
|
||||
290
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go
generated
vendored
290
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go
generated
vendored
@@ -3,17 +3,14 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
)
|
||||
|
||||
// AEADEncrypted represents an AEAD Encrypted Packet (tag 20, RFC4880bis-5.16).
|
||||
// AEADEncrypted represents an AEAD Encrypted Packet.
|
||||
// See https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t
|
||||
type AEADEncrypted struct {
|
||||
cipher CipherFunction
|
||||
mode AEADMode
|
||||
@@ -25,33 +22,6 @@ type AEADEncrypted struct {
|
||||
// Only currently defined version
|
||||
const aeadEncryptedVersion = 1
|
||||
|
||||
// An AEAD opener/sealer, its configuration, and data for en/decryption.
|
||||
type aeadCrypter struct {
|
||||
aead cipher.AEAD
|
||||
chunkSize int
|
||||
initialNonce []byte
|
||||
associatedData []byte // Chunk-independent associated data
|
||||
chunkIndex []byte // Chunk counter
|
||||
bytesProcessed int // Amount of plaintext bytes encrypted/decrypted
|
||||
buffer bytes.Buffer // Buffered bytes accross chunks
|
||||
}
|
||||
|
||||
// aeadEncrypter encrypts and writes bytes. It encrypts when necessary according
|
||||
// to the AEAD block size, and buffers the extra encrypted bytes for next write.
|
||||
type aeadEncrypter struct {
|
||||
aeadCrypter // Embedded plaintext sealer
|
||||
writer io.WriteCloser // 'writer' is a partialLengthWriter
|
||||
}
|
||||
|
||||
// aeadDecrypter reads and decrypts bytes. It buffers extra decrypted bytes when
|
||||
// necessary, similar to aeadEncrypter.
|
||||
type aeadDecrypter struct {
|
||||
aeadCrypter // Embedded ciphertext opener
|
||||
reader io.Reader // 'reader' is a partialLengthReader
|
||||
peekedBytes []byte // Used to detect last chunk
|
||||
eof bool
|
||||
}
|
||||
|
||||
func (ae *AEADEncrypted) parse(buf io.Reader) error {
|
||||
headerData := make([]byte, 4)
|
||||
if n, err := io.ReadFull(buf, headerData); n < 4 {
|
||||
@@ -59,10 +29,14 @@ func (ae *AEADEncrypted) parse(buf io.Reader) error {
|
||||
}
|
||||
// Read initial nonce
|
||||
mode := AEADMode(headerData[2])
|
||||
nonceLen := mode.NonceLength()
|
||||
if nonceLen == 0 {
|
||||
nonceLen := mode.IvLength()
|
||||
|
||||
// This packet supports only EAX and OCB
|
||||
// https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t
|
||||
if nonceLen == 0 || mode > AEADModeOCB {
|
||||
return errors.AEADError("unknown mode")
|
||||
}
|
||||
|
||||
initialNonce := make([]byte, nonceLen)
|
||||
if n, err := io.ReadFull(buf, initialNonce); n < nonceLen {
|
||||
return errors.AEADError("could not read aead nonce:" + err.Error())
|
||||
@@ -75,7 +49,7 @@ func (ae *AEADEncrypted) parse(buf io.Reader) error {
|
||||
}
|
||||
ae.cipher = CipherFunction(c)
|
||||
ae.mode = mode
|
||||
ae.chunkSizeByte = byte(headerData[3])
|
||||
ae.chunkSizeByte = headerData[3]
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -105,225 +79,13 @@ func (ae *AEADEncrypted) decrypt(key []byte) (io.ReadCloser, error) {
|
||||
initialNonce: ae.initialNonce,
|
||||
associatedData: ae.associatedData(),
|
||||
chunkIndex: make([]byte, 8),
|
||||
packetTag: packetTypeAEADEncrypted,
|
||||
},
|
||||
reader: ae.Contents,
|
||||
peekedBytes: peekedBytes}, nil
|
||||
}
|
||||
|
||||
// Read decrypts bytes and reads them into dst. It decrypts when necessary and
|
||||
// buffers extra decrypted bytes. It returns the number of bytes copied into dst
|
||||
// and an error.
|
||||
func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
|
||||
// Return buffered plaintext bytes from previous calls
|
||||
if ar.buffer.Len() > 0 {
|
||||
return ar.buffer.Read(dst)
|
||||
}
|
||||
|
||||
// Return EOF if we've previously validated the final tag
|
||||
if ar.eof {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
// Read a chunk
|
||||
tagLen := ar.aead.Overhead()
|
||||
cipherChunkBuf := new(bytes.Buffer)
|
||||
_, errRead := io.CopyN(cipherChunkBuf, ar.reader, int64(ar.chunkSize + tagLen))
|
||||
cipherChunk := cipherChunkBuf.Bytes()
|
||||
if errRead != nil && errRead != io.EOF {
|
||||
return 0, errRead
|
||||
}
|
||||
decrypted, errChunk := ar.openChunk(cipherChunk)
|
||||
if errChunk != nil {
|
||||
return 0, errChunk
|
||||
}
|
||||
|
||||
// Return decrypted bytes, buffering if necessary
|
||||
if len(dst) < len(decrypted) {
|
||||
n = copy(dst, decrypted[:len(dst)])
|
||||
ar.buffer.Write(decrypted[len(dst):])
|
||||
} else {
|
||||
n = copy(dst, decrypted)
|
||||
}
|
||||
|
||||
// Check final authentication tag
|
||||
if errRead == io.EOF {
|
||||
errChunk := ar.validateFinalTag(ar.peekedBytes)
|
||||
if errChunk != nil {
|
||||
return n, errChunk
|
||||
}
|
||||
ar.eof = true // Mark EOF for when we've returned all buffered data
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close is noOp. The final authentication tag of the stream was already
|
||||
// checked in the last Read call. In the future, this function could be used to
|
||||
// wipe the reader and peeked, decrypted bytes, if necessary.
|
||||
func (ar *aeadDecrypter) Close() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeAEADEncrypted initializes the aeadCrypter and returns a writer.
|
||||
// This writer encrypts and writes bytes (see aeadEncrypter.Write()).
|
||||
func SerializeAEADEncrypted(w io.Writer, key []byte, cipher CipherFunction, mode AEADMode, config *Config) (io.WriteCloser, error) {
|
||||
writeCloser := noOpCloser{w}
|
||||
writer, err := serializeStreamHeader(writeCloser, packetTypeAEADEncrypted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Data for en/decryption: tag, version, cipher, aead mode, chunk size
|
||||
aeadConf := config.AEAD()
|
||||
prefix := []byte{
|
||||
0xD4,
|
||||
aeadEncryptedVersion,
|
||||
byte(config.Cipher()),
|
||||
byte(aeadConf.Mode()),
|
||||
aeadConf.ChunkSizeByte(),
|
||||
}
|
||||
n, err := writer.Write(prefix[1:])
|
||||
if err != nil || n < 4 {
|
||||
return nil, errors.AEADError("could not write AEAD headers")
|
||||
}
|
||||
// Sample nonce
|
||||
nonceLen := aeadConf.Mode().NonceLength()
|
||||
nonce := make([]byte, nonceLen)
|
||||
n, err = rand.Read(nonce)
|
||||
if err != nil {
|
||||
panic("Could not sample random nonce")
|
||||
}
|
||||
_, err = writer.Write(nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockCipher := CipherFunction(config.Cipher()).new(key)
|
||||
alg := AEADMode(aeadConf.Mode()).new(blockCipher)
|
||||
|
||||
chunkSize := decodeAEADChunkSize(aeadConf.ChunkSizeByte())
|
||||
return &aeadEncrypter{
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: alg,
|
||||
chunkSize: chunkSize,
|
||||
associatedData: prefix,
|
||||
chunkIndex: make([]byte, 8),
|
||||
initialNonce: nonce,
|
||||
},
|
||||
writer: writer}, nil
|
||||
}
|
||||
|
||||
// Write encrypts and writes bytes. It encrypts when necessary and buffers extra
|
||||
// plaintext bytes for next call. When the stream is finished, Close() MUST be
|
||||
// called to append the final tag.
|
||||
func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) {
|
||||
// Append plaintextBytes to existing buffered bytes
|
||||
n, err = aw.buffer.Write(plaintextBytes)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
// Encrypt and write chunks
|
||||
for aw.buffer.Len() >= aw.chunkSize {
|
||||
plainChunk := aw.buffer.Next(aw.chunkSize)
|
||||
encryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
_, err = aw.writer.Write(encryptedChunk)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close encrypts and writes the remaining buffered plaintext if any, appends
|
||||
// the final authentication tag, and closes the embedded writer. This function
|
||||
// MUST be called at the end of a stream.
|
||||
func (aw *aeadEncrypter) Close() (err error) {
|
||||
// Encrypt and write a chunk if there's buffered data left, or if we haven't
|
||||
// written any chunks yet.
|
||||
if aw.buffer.Len() > 0 || aw.bytesProcessed == 0 {
|
||||
plainChunk := aw.buffer.Bytes()
|
||||
lastEncryptedChunk, err := aw.sealChunk(plainChunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = aw.writer.Write(lastEncryptedChunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Compute final tag (associated data: packet tag, version, cipher, aead,
|
||||
// chunk size, index, total number of encrypted octets).
|
||||
adata := append(aw.associatedData[:], aw.chunkIndex[:]...)
|
||||
adata = append(adata, make([]byte, 8)...)
|
||||
binary.BigEndian.PutUint64(adata[13:], uint64(aw.bytesProcessed))
|
||||
nonce := aw.computeNextNonce()
|
||||
finalTag := aw.aead.Seal(nil, nonce, nil, adata)
|
||||
_, err = aw.writer.Write(finalTag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return aw.writer.Close()
|
||||
}
|
||||
|
||||
// sealChunk Encrypts and authenticates the given chunk.
|
||||
func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) {
|
||||
if len(data) > aw.chunkSize {
|
||||
return nil, errors.AEADError("chunk exceeds maximum length")
|
||||
}
|
||||
if aw.associatedData == nil {
|
||||
return nil, errors.AEADError("can't seal without headers")
|
||||
}
|
||||
adata := append(aw.associatedData, aw.chunkIndex...)
|
||||
nonce := aw.computeNextNonce()
|
||||
encrypted := aw.aead.Seal(nil, nonce, data, adata)
|
||||
aw.bytesProcessed += len(data)
|
||||
if err := aw.aeadCrypter.incrementIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encrypted, nil
|
||||
}
|
||||
|
||||
// openChunk decrypts and checks integrity of an encrypted chunk, returning
|
||||
// the underlying plaintext and an error. It access peeked bytes from next
|
||||
// chunk, to identify the last chunk and decrypt/validate accordingly.
|
||||
func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) {
|
||||
tagLen := ar.aead.Overhead()
|
||||
// Restore carried bytes from last call
|
||||
chunkExtra := append(ar.peekedBytes, data...)
|
||||
// 'chunk' contains encrypted bytes, followed by an authentication tag.
|
||||
chunk := chunkExtra[:len(chunkExtra)-tagLen]
|
||||
ar.peekedBytes = chunkExtra[len(chunkExtra)-tagLen:]
|
||||
adata := append(ar.associatedData, ar.chunkIndex...)
|
||||
nonce := ar.computeNextNonce()
|
||||
plainChunk, err := ar.aead.Open(nil, nonce, chunk, adata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ar.bytesProcessed += len(plainChunk)
|
||||
if err = ar.aeadCrypter.incrementIndex(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plainChunk, nil
|
||||
}
|
||||
|
||||
// Checks the summary tag. It takes into account the total decrypted bytes into
|
||||
// the associated data. It returns an error, or nil if the tag is valid.
|
||||
func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
|
||||
// Associated: tag, version, cipher, aead, chunk size, index, and octets
|
||||
amountBytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(amountBytes, uint64(ar.bytesProcessed))
|
||||
adata := append(ar.associatedData, ar.chunkIndex...)
|
||||
adata = append(adata, amountBytes...)
|
||||
nonce := ar.computeNextNonce()
|
||||
_, err := ar.aead.Open(nil, nonce, tag, adata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Associated data for chunks: tag, version, cipher, mode, chunk size byte
|
||||
// associatedData for chunks: tag, version, cipher, mode, chunk size byte
|
||||
func (ae *AEADEncrypted) associatedData() []byte {
|
||||
return []byte{
|
||||
0xD4,
|
||||
@@ -332,33 +94,3 @@ func (ae *AEADEncrypted) associatedData() []byte {
|
||||
byte(ae.mode),
|
||||
ae.chunkSizeByte}
|
||||
}
|
||||
|
||||
// computeNonce takes the incremental index and computes an eXclusive OR with
|
||||
// the least significant 8 bytes of the receivers' initial nonce (see sec.
|
||||
// 5.16.1 and 5.16.2). It returns the resulting nonce.
|
||||
func (wo *aeadCrypter) computeNextNonce() (nonce []byte) {
|
||||
nonce = make([]byte, len(wo.initialNonce))
|
||||
copy(nonce, wo.initialNonce)
|
||||
offset := len(wo.initialNonce) - 8
|
||||
for i := 0; i < 8; i++ {
|
||||
nonce[i+offset] ^= wo.chunkIndex[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// incrementIndex perfoms an integer increment by 1 of the integer represented by the
|
||||
// slice, modifying it accordingly.
|
||||
func (wo *aeadCrypter) incrementIndex() error {
|
||||
index := wo.chunkIndex
|
||||
if len(index) == 0 {
|
||||
return errors.AEADError("Index has length 0")
|
||||
}
|
||||
for i := len(index) - 1; i >= 0; i-- {
|
||||
if index[i] < 255 {
|
||||
index[i]++
|
||||
return nil
|
||||
}
|
||||
index[i] = 0
|
||||
}
|
||||
return errors.AEADError("cannot further increment index")
|
||||
}
|
||||
|
||||
2
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
generated
vendored
@@ -47,6 +47,8 @@ func (c *Compressed) parse(r io.Reader) error {
|
||||
}
|
||||
|
||||
switch buf[0] {
|
||||
case 0:
|
||||
c.Body = r
|
||||
case 1:
|
||||
c.Body = flate.NewReader(r)
|
||||
case 2:
|
||||
|
||||
107
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
107
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
@@ -10,6 +10,8 @@ import (
|
||||
"io"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
)
|
||||
|
||||
// Config collects a number of parameters along with sensible defaults.
|
||||
@@ -33,16 +35,24 @@ type Config struct {
|
||||
DefaultCompressionAlgo CompressionAlgo
|
||||
// CompressionConfig configures the compression settings.
|
||||
CompressionConfig *CompressionConfig
|
||||
// S2KCount is only used for symmetric encryption. It
|
||||
// determines the strength of the passphrase stretching when
|
||||
// S2K (String to Key) config, used for key derivation in the context of secret key encryption
|
||||
// and password-encrypted data.
|
||||
// If nil, the default configuration is used
|
||||
S2KConfig *s2k.Config
|
||||
// Iteration count for Iterated S2K (String to Key).
|
||||
// Only used if sk2.Mode is nil.
|
||||
// This value is duplicated here from s2k.Config for backwards compatibility.
|
||||
// It determines the strength of the passphrase stretching when
|
||||
// the said passphrase is hashed to produce a key. S2KCount
|
||||
// should be between 1024 and 65011712, inclusive. If Config
|
||||
// is nil or S2KCount is 0, the value 65536 used. Not all
|
||||
// should be between 65536 and 65011712, inclusive. If Config
|
||||
// is nil or S2KCount is 0, the value 16777216 used. Not all
|
||||
// values in the above range can be represented. S2KCount will
|
||||
// be rounded up to the next representable value if it cannot
|
||||
// be encoded exactly. When set, it is strongly encrouraged to
|
||||
// use a value that is at least 65536. See RFC 4880 Section
|
||||
// 3.7.1.3.
|
||||
//
|
||||
// Deprecated: SK2Count should be configured in S2KConfig instead.
|
||||
S2KCount int
|
||||
// RSABits is the number of bits in new RSA keys made with NewEntity.
|
||||
// If zero, then 2048 bit keys are created.
|
||||
@@ -52,6 +62,9 @@ type Config struct {
|
||||
Algorithm PublicKeyAlgorithm
|
||||
// Some known primes that are optionally prepopulated by the caller
|
||||
RSAPrimes []*big.Int
|
||||
// Curve configures the desired packet.Curve if the Algorithm is PubKeyAlgoECDSA,
|
||||
// PubKeyAlgoEdDSA, or PubKeyAlgoECDH. If empty Curve25519 is used.
|
||||
Curve Curve
|
||||
// AEADConfig configures the use of the new AEAD Encrypted Data Packet,
|
||||
// defined in the draft of the next version of the OpenPGP specification.
|
||||
// If a non-nil AEADConfig is passed, usage of this packet is enabled. By
|
||||
@@ -78,6 +91,25 @@ type Config struct {
|
||||
// By default, the signing key is selected automatically, preferring
|
||||
// signing subkeys if available.
|
||||
SigningKeyId uint64
|
||||
// SigningIdentity is used to specify a user ID (packet Signer's User ID, type 28)
|
||||
// when producing a generic certification signature onto an existing user ID.
|
||||
// The identity must be present in the signer Entity.
|
||||
SigningIdentity string
|
||||
// InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read
|
||||
// encrypted messages without Modification Detection Code (MDC).
|
||||
// MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented
|
||||
// in most OpenPGP implementations. Messages without MDC are considered unnecessarily
|
||||
// insecure and should be prevented whenever possible.
|
||||
// In case one needs to deal with messages from very old OpenPGP implementations, there
|
||||
// might be no other way than to tolerate the missing MDC. Setting this flag, allows this
|
||||
// mode of operation. It should be considered a measure of last resort.
|
||||
InsecureAllowUnauthenticatedMessages bool
|
||||
// KnownNotations is a map of Notation Data names to bools, which controls
|
||||
// the notation names that are allowed to be present in critical Notation Data
|
||||
// signature subpackets.
|
||||
KnownNotations map[string]bool
|
||||
// SignatureNotations is a list of Notations to be added to any signatures.
|
||||
SignatureNotations []*Notation
|
||||
}
|
||||
|
||||
func (c *Config) Random() io.Reader {
|
||||
@@ -103,9 +135,9 @@ func (c *Config) Cipher() CipherFunction {
|
||||
|
||||
func (c *Config) Now() time.Time {
|
||||
if c == nil || c.Time == nil {
|
||||
return time.Now()
|
||||
return time.Now().Truncate(time.Second)
|
||||
}
|
||||
return c.Time()
|
||||
return c.Time().Truncate(time.Second)
|
||||
}
|
||||
|
||||
// KeyLifetime returns the validity period of the key.
|
||||
@@ -131,13 +163,6 @@ func (c *Config) Compression() CompressionAlgo {
|
||||
return c.DefaultCompressionAlgo
|
||||
}
|
||||
|
||||
func (c *Config) PasswordHashIterations() int {
|
||||
if c == nil || c.S2KCount == 0 {
|
||||
return 0
|
||||
}
|
||||
return c.S2KCount
|
||||
}
|
||||
|
||||
func (c *Config) RSAModulusBits() int {
|
||||
if c == nil || c.RSABits == 0 {
|
||||
return 2048
|
||||
@@ -152,6 +177,34 @@ func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm {
|
||||
return c.Algorithm
|
||||
}
|
||||
|
||||
func (c *Config) CurveName() Curve {
|
||||
if c == nil || c.Curve == "" {
|
||||
return Curve25519
|
||||
}
|
||||
return c.Curve
|
||||
}
|
||||
|
||||
// Deprecated: The hash iterations should now be queried via the S2K() method.
|
||||
func (c *Config) PasswordHashIterations() int {
|
||||
if c == nil || c.S2KCount == 0 {
|
||||
return 0
|
||||
}
|
||||
return c.S2KCount
|
||||
}
|
||||
|
||||
func (c *Config) S2K() *s2k.Config {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
// for backwards compatibility
|
||||
if c != nil && c.S2KCount > 0 && c.S2KConfig == nil {
|
||||
return &s2k.Config{
|
||||
S2KCount: c.S2KCount,
|
||||
}
|
||||
}
|
||||
return c.S2KConfig
|
||||
}
|
||||
|
||||
func (c *Config) AEAD() *AEADConfig {
|
||||
if c == nil {
|
||||
return nil
|
||||
@@ -165,3 +218,31 @@ func (c *Config) SigningKey() uint64 {
|
||||
}
|
||||
return c.SigningKeyId
|
||||
}
|
||||
|
||||
func (c *Config) SigningUserId() string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
return c.SigningIdentity
|
||||
}
|
||||
|
||||
func (c *Config) AllowUnauthenticatedMessages() bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
return c.InsecureAllowUnauthenticatedMessages
|
||||
}
|
||||
|
||||
func (c *Config) KnownNotation(notationName string) bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
return c.KnownNotations[notationName]
|
||||
}
|
||||
|
||||
func (c *Config) Notations() []*Notation {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.SignatureNotations
|
||||
}
|
||||
|
||||
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
generated
vendored
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
generated
vendored
@@ -25,7 +25,7 @@ const encryptedKeyVersion = 3
|
||||
type EncryptedKey struct {
|
||||
KeyId uint64
|
||||
Algo PublicKeyAlgorithm
|
||||
CipherFunc CipherFunction // only valid after a successful Decrypt
|
||||
CipherFunc CipherFunction // only valid after a successful Decrypt for a v3 packet
|
||||
Key []byte // only valid after a successful Decrypt
|
||||
|
||||
encryptedMPI1, encryptedMPI2 encoding.Field
|
||||
@@ -123,6 +123,10 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
||||
}
|
||||
|
||||
e.CipherFunc = CipherFunction(b[0])
|
||||
if !e.CipherFunc.IsSupported() {
|
||||
return errors.UnsupportedError("unsupported encryption function")
|
||||
}
|
||||
|
||||
e.Key = b[1 : len(b)-2]
|
||||
expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
|
||||
checksum := checksumKeyMaterial(e.Key)
|
||||
|
||||
29
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/notation.go
generated
vendored
Normal file
29
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/notation.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package packet
|
||||
|
||||
// Notation type represents a Notation Data subpacket
|
||||
// see https://tools.ietf.org/html/rfc4880#section-5.2.3.16
|
||||
type Notation struct {
|
||||
Name string
|
||||
Value []byte
|
||||
IsCritical bool
|
||||
IsHumanReadable bool
|
||||
}
|
||||
|
||||
func (notation *Notation) getData() []byte {
|
||||
nameData := []byte(notation.Name)
|
||||
nameLen := len(nameData)
|
||||
valueLen := len(notation.Value)
|
||||
|
||||
data := make([]byte, 8+nameLen+valueLen)
|
||||
if notation.IsHumanReadable {
|
||||
data[0] = 0x80
|
||||
}
|
||||
|
||||
data[4] = byte(nameLen >> 8)
|
||||
data[5] = byte(nameLen)
|
||||
data[6] = byte(valueLen >> 8)
|
||||
data[7] = byte(valueLen)
|
||||
copy(data[8:8+nameLen], nameData)
|
||||
copy(data[8+nameLen:], notation.Value)
|
||||
return data
|
||||
}
|
||||
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
generated
vendored
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
generated
vendored
@@ -8,7 +8,7 @@ import (
|
||||
"crypto"
|
||||
"encoding/binary"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
@@ -37,7 +37,7 @@ func (ops *OnePassSignature) parse(r io.Reader) (err error) {
|
||||
}
|
||||
|
||||
var ok bool
|
||||
ops.Hash, ok = s2k.HashIdToHash(buf[2])
|
||||
ops.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2])
|
||||
if !ok {
|
||||
return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func (ops *OnePassSignature) Serialize(w io.Writer) error {
|
||||
buf[0] = onePassSignatureVersion
|
||||
buf[1] = uint8(ops.SigType)
|
||||
var ok bool
|
||||
buf[2], ok = s2k.HashToHashId(ops.Hash)
|
||||
buf[2], ok = algorithm.HashToHashIdWithSha1(ops.Hash)
|
||||
if !ok {
|
||||
return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
|
||||
}
|
||||
|
||||
15
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
generated
vendored
15
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
generated
vendored
@@ -84,8 +84,9 @@ func (or *OpaqueReader) Next() (op *OpaquePacket, err error) {
|
||||
// OpaqueSubpacket represents an unparsed OpenPGP subpacket,
|
||||
// as found in signature and user attribute packets.
|
||||
type OpaqueSubpacket struct {
|
||||
SubType uint8
|
||||
Contents []byte
|
||||
SubType uint8
|
||||
EncodedLength []byte // Store the original encoded length for signature verifications.
|
||||
Contents []byte
|
||||
}
|
||||
|
||||
// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from
|
||||
@@ -109,6 +110,7 @@ func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) {
|
||||
func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) {
|
||||
// RFC 4880, section 5.2.3.1
|
||||
var subLen uint32
|
||||
var encodedLength []byte
|
||||
if len(contents) < 1 {
|
||||
goto Truncated
|
||||
}
|
||||
@@ -119,6 +121,7 @@ func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacke
|
||||
if len(contents) < subHeaderLen {
|
||||
goto Truncated
|
||||
}
|
||||
encodedLength = contents[0:1]
|
||||
subLen = uint32(contents[0])
|
||||
contents = contents[1:]
|
||||
case contents[0] < 255:
|
||||
@@ -126,6 +129,7 @@ func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacke
|
||||
if len(contents) < subHeaderLen {
|
||||
goto Truncated
|
||||
}
|
||||
encodedLength = contents[0:2]
|
||||
subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192
|
||||
contents = contents[2:]
|
||||
default:
|
||||
@@ -133,16 +137,19 @@ func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacke
|
||||
if len(contents) < subHeaderLen {
|
||||
goto Truncated
|
||||
}
|
||||
encodedLength = contents[0:5]
|
||||
subLen = uint32(contents[1])<<24 |
|
||||
uint32(contents[2])<<16 |
|
||||
uint32(contents[3])<<8 |
|
||||
uint32(contents[4])
|
||||
contents = contents[5:]
|
||||
|
||||
}
|
||||
if subLen > uint32(len(contents)) || subLen == 0 {
|
||||
goto Truncated
|
||||
}
|
||||
subPacket.SubType = contents[0]
|
||||
subPacket.EncodedLength = encodedLength
|
||||
subPacket.Contents = contents[1:subLen]
|
||||
return
|
||||
Truncated:
|
||||
@@ -152,7 +159,9 @@ Truncated:
|
||||
|
||||
func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) {
|
||||
buf := make([]byte, 6)
|
||||
n := serializeSubpacketLength(buf, len(osp.Contents)+1)
|
||||
copy(buf, osp.EncodedLength)
|
||||
n := len(osp.EncodedLength)
|
||||
|
||||
buf[n] = osp.SubType
|
||||
if _, err = w.Write(buf[:n+1]); err != nil {
|
||||
return
|
||||
|
||||
96
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
generated
vendored
96
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
generated
vendored
@@ -302,21 +302,21 @@ func consumeAll(r io.Reader) (n int64, err error) {
|
||||
type packetType uint8
|
||||
|
||||
const (
|
||||
packetTypeEncryptedKey packetType = 1
|
||||
packetTypeSignature packetType = 2
|
||||
packetTypeSymmetricKeyEncrypted packetType = 3
|
||||
packetTypeOnePassSignature packetType = 4
|
||||
packetTypePrivateKey packetType = 5
|
||||
packetTypePublicKey packetType = 6
|
||||
packetTypePrivateSubkey packetType = 7
|
||||
packetTypeCompressed packetType = 8
|
||||
packetTypeSymmetricallyEncrypted packetType = 9
|
||||
packetTypeLiteralData packetType = 11
|
||||
packetTypeUserId packetType = 13
|
||||
packetTypePublicSubkey packetType = 14
|
||||
packetTypeUserAttribute packetType = 17
|
||||
packetTypeSymmetricallyEncryptedMDC packetType = 18
|
||||
packetTypeAEADEncrypted packetType = 20
|
||||
packetTypeEncryptedKey packetType = 1
|
||||
packetTypeSignature packetType = 2
|
||||
packetTypeSymmetricKeyEncrypted packetType = 3
|
||||
packetTypeOnePassSignature packetType = 4
|
||||
packetTypePrivateKey packetType = 5
|
||||
packetTypePublicKey packetType = 6
|
||||
packetTypePrivateSubkey packetType = 7
|
||||
packetTypeCompressed packetType = 8
|
||||
packetTypeSymmetricallyEncrypted packetType = 9
|
||||
packetTypeLiteralData packetType = 11
|
||||
packetTypeUserId packetType = 13
|
||||
packetTypePublicSubkey packetType = 14
|
||||
packetTypeUserAttribute packetType = 17
|
||||
packetTypeSymmetricallyEncryptedIntegrityProtected packetType = 18
|
||||
packetTypeAEADEncrypted packetType = 20
|
||||
)
|
||||
|
||||
// EncryptedDataPacket holds encrypted data. It is currently implemented by
|
||||
@@ -354,16 +354,16 @@ func Read(r io.Reader) (p Packet, err error) {
|
||||
case packetTypeCompressed:
|
||||
p = new(Compressed)
|
||||
case packetTypeSymmetricallyEncrypted:
|
||||
err = errors.UnsupportedError("Symmetrically encrypted packets without MDC are not supported")
|
||||
p = new(SymmetricallyEncrypted)
|
||||
case packetTypeLiteralData:
|
||||
p = new(LiteralData)
|
||||
case packetTypeUserId:
|
||||
p = new(UserId)
|
||||
case packetTypeUserAttribute:
|
||||
p = new(UserAttribute)
|
||||
case packetTypeSymmetricallyEncryptedMDC:
|
||||
case packetTypeSymmetricallyEncryptedIntegrityProtected:
|
||||
se := new(SymmetricallyEncrypted)
|
||||
se.MDC = true
|
||||
se.IntegrityProtected = true
|
||||
p = se
|
||||
case packetTypeAEADEncrypted:
|
||||
p = new(AEADEncrypted)
|
||||
@@ -384,18 +384,18 @@ func Read(r io.Reader) (p Packet, err error) {
|
||||
type SignatureType uint8
|
||||
|
||||
const (
|
||||
SigTypeBinary SignatureType = 0x00
|
||||
SigTypeText = 0x01
|
||||
SigTypeGenericCert = 0x10
|
||||
SigTypePersonaCert = 0x11
|
||||
SigTypeCasualCert = 0x12
|
||||
SigTypePositiveCert = 0x13
|
||||
SigTypeSubkeyBinding = 0x18
|
||||
SigTypePrimaryKeyBinding = 0x19
|
||||
SigTypeDirectSignature = 0x1F
|
||||
SigTypeKeyRevocation = 0x20
|
||||
SigTypeSubkeyRevocation = 0x28
|
||||
SigTypeCertificationRevocation = 0x30
|
||||
SigTypeBinary SignatureType = 0x00
|
||||
SigTypeText = 0x01
|
||||
SigTypeGenericCert = 0x10
|
||||
SigTypePersonaCert = 0x11
|
||||
SigTypeCasualCert = 0x12
|
||||
SigTypePositiveCert = 0x13
|
||||
SigTypeSubkeyBinding = 0x18
|
||||
SigTypePrimaryKeyBinding = 0x19
|
||||
SigTypeDirectSignature = 0x1F
|
||||
SigTypeKeyRevocation = 0x20
|
||||
SigTypeSubkeyRevocation = 0x28
|
||||
SigTypeCertificationRevocation = 0x30
|
||||
)
|
||||
|
||||
// PublicKeyAlgorithm represents the different public key system specified for
|
||||
@@ -455,6 +455,11 @@ func (cipher CipherFunction) KeySize() int {
|
||||
return algorithm.CipherFunction(cipher).KeySize()
|
||||
}
|
||||
|
||||
// IsSupported returns true if the cipher is supported from the library
|
||||
func (cipher CipherFunction) IsSupported() bool {
|
||||
return algorithm.CipherFunction(cipher).KeySize() > 0
|
||||
}
|
||||
|
||||
// blockSize returns the block size, in bytes, of cipher.
|
||||
func (cipher CipherFunction) blockSize() int {
|
||||
return algorithm.CipherFunction(cipher).BlockSize()
|
||||
@@ -490,15 +495,16 @@ const (
|
||||
|
||||
// AEADMode represents the different Authenticated Encryption with Associated
|
||||
// Data specified for OpenPGP.
|
||||
// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.6
|
||||
type AEADMode algorithm.AEADMode
|
||||
|
||||
const (
|
||||
AEADModeEAX AEADMode = 1
|
||||
AEADModeOCB AEADMode = 2
|
||||
AEADModeExperimentalGCM AEADMode = 100
|
||||
AEADModeEAX AEADMode = 1
|
||||
AEADModeOCB AEADMode = 2
|
||||
AEADModeGCM AEADMode = 3
|
||||
)
|
||||
|
||||
func (mode AEADMode) NonceLength() int {
|
||||
func (mode AEADMode) IvLength() int {
|
||||
return algorithm.AEADMode(mode).NonceLength()
|
||||
}
|
||||
|
||||
@@ -521,3 +527,25 @@ const (
|
||||
KeyCompromised ReasonForRevocation = 2
|
||||
KeyRetired ReasonForRevocation = 3
|
||||
)
|
||||
|
||||
// Curve is a mapping to supported ECC curves for key generation.
|
||||
// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-06.html#name-curve-specific-wire-formats
|
||||
type Curve string
|
||||
|
||||
const (
|
||||
Curve25519 Curve = "Curve25519"
|
||||
Curve448 Curve = "Curve448"
|
||||
CurveNistP256 Curve = "P256"
|
||||
CurveNistP384 Curve = "P384"
|
||||
CurveNistP521 Curve = "P521"
|
||||
CurveSecP256k1 Curve = "SecP256k1"
|
||||
CurveBrainpoolP256 Curve = "BrainpoolP256"
|
||||
CurveBrainpoolP384 Curve = "BrainpoolP384"
|
||||
CurveBrainpoolP512 Curve = "BrainpoolP512"
|
||||
)
|
||||
|
||||
// TrustLevel represents a trust level per RFC4880 5.2.3.13
|
||||
type TrustLevel uint8
|
||||
|
||||
// TrustAmount represents a trust amount per RFC4880 5.2.3.13
|
||||
type TrustAmount uint8
|
||||
|
||||
313
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
generated
vendored
313
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
generated
vendored
@@ -9,27 +9,22 @@ import (
|
||||
"crypto"
|
||||
"crypto/cipher"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
|
||||
@@ -54,7 +49,7 @@ type PrivateKey struct {
|
||||
s2kParams *s2k.Params
|
||||
}
|
||||
|
||||
//S2KType s2k packet type
|
||||
// S2KType s2k packet type
|
||||
type S2KType uint8
|
||||
|
||||
const (
|
||||
@@ -94,10 +89,9 @@ func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *Private
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEdDSAPrivateKey(creationTime time.Time, priv *ed25519.PrivateKey) *PrivateKey {
|
||||
func NewEdDSAPrivateKey(creationTime time.Time, priv *eddsa.PrivateKey) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
pub := priv.Public().(ed25519.PublicKey)
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pub)
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &priv.PublicKey)
|
||||
pk.PrivateKey = priv
|
||||
return pk
|
||||
}
|
||||
@@ -111,25 +105,25 @@ func NewECDHPrivateKey(creationTime time.Time, priv *ecdh.PrivateKey) *PrivateKe
|
||||
|
||||
// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
|
||||
// implements RSA, ECDSA or EdDSA.
|
||||
func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey {
|
||||
func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey {
|
||||
pk := new(PrivateKey)
|
||||
// In general, the public Keys should be used as pointers. We still
|
||||
// type-switch on the values, for backwards-compatibility.
|
||||
switch pubkey := signer.Public().(type) {
|
||||
case *rsa.PublicKey:
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey)
|
||||
case rsa.PublicKey:
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey)
|
||||
case *ecdsa.PublicKey:
|
||||
pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey)
|
||||
case ecdsa.PublicKey:
|
||||
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey)
|
||||
case *ed25519.PublicKey:
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, pubkey)
|
||||
case ed25519.PublicKey:
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey)
|
||||
switch pubkey := signer.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
case rsa.PrivateKey:
|
||||
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
case *ecdsa.PrivateKey:
|
||||
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
case ecdsa.PrivateKey:
|
||||
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
case *eddsa.PrivateKey:
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
case eddsa.PrivateKey:
|
||||
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
|
||||
default:
|
||||
panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
|
||||
panic("openpgp: unknown signer type in NewSignerPrivateKey")
|
||||
}
|
||||
pk.PrivateKey = signer
|
||||
return pk
|
||||
@@ -185,6 +179,9 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
pk.cipher = CipherFunction(buf[0])
|
||||
if pk.cipher != 0 && !pk.cipher.IsSupported() {
|
||||
return errors.UnsupportedError("unsupported cipher function in private key")
|
||||
}
|
||||
pk.s2kParams, err = s2k.ParseIntoParams(r)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -239,6 +236,18 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
||||
}
|
||||
}
|
||||
if !pk.Encrypted {
|
||||
if len(privateKeyData) < 2 {
|
||||
return errors.StructuralError("truncated private key data")
|
||||
}
|
||||
var sum uint16
|
||||
for i := 0; i < len(privateKeyData)-2; i++ {
|
||||
sum += uint16(privateKeyData[i])
|
||||
}
|
||||
if privateKeyData[len(privateKeyData)-2] != uint8(sum>>8) ||
|
||||
privateKeyData[len(privateKeyData)-1] != uint8(sum) {
|
||||
return errors.StructuralError("private key checksum failure")
|
||||
}
|
||||
privateKeyData = privateKeyData[:len(privateKeyData)-2]
|
||||
return pk.parsePrivateKey(privateKeyData)
|
||||
}
|
||||
|
||||
@@ -294,14 +303,8 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
|
||||
return err
|
||||
}
|
||||
l = buf.Len()
|
||||
if pk.sha1Checksum {
|
||||
h := sha1.New()
|
||||
h.Write(buf.Bytes())
|
||||
buf.Write(h.Sum(nil))
|
||||
} else {
|
||||
checksum := mod64kHash(buf.Bytes())
|
||||
buf.Write([]byte{byte(checksum >> 8), byte(checksum)})
|
||||
}
|
||||
checksum := mod64kHash(buf.Bytes())
|
||||
buf.Write([]byte{byte(checksum >> 8), byte(checksum)})
|
||||
priv = buf.Bytes()
|
||||
} else {
|
||||
priv, l = pk.encryptedData, len(pk.encryptedData)
|
||||
@@ -353,23 +356,22 @@ func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
|
||||
}
|
||||
|
||||
func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
|
||||
_, err := w.Write(new(encoding.MPI).SetBig(priv.D).EncodedBytes())
|
||||
_, err := w.Write(encoding.NewMPI(priv.MarshalIntegerSecret()).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeEdDSAPrivateKey(w io.Writer, priv *ed25519.PrivateKey) error {
|
||||
keySize := ed25519.PrivateKeySize - ed25519.PublicKeySize
|
||||
_, err := w.Write(encoding.NewMPI((*priv)[:keySize]).EncodedBytes())
|
||||
func serializeEdDSAPrivateKey(w io.Writer, priv *eddsa.PrivateKey) error {
|
||||
_, err := w.Write(encoding.NewMPI(priv.MarshalByteSecret()).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error {
|
||||
_, err := w.Write(encoding.NewMPI(priv.D).EncodedBytes())
|
||||
_, err := w.Write(encoding.NewMPI(priv.MarshalByteSecret()).EncodedBytes())
|
||||
return err
|
||||
}
|
||||
|
||||
// Decrypt decrypts an encrypted private key using a passphrase.
|
||||
func (pk *PrivateKey) Decrypt(passphrase []byte) error {
|
||||
// decrypt decrypts an encrypted private key using a decryption key.
|
||||
func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
|
||||
if pk.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
@@ -377,9 +379,7 @@ func (pk *PrivateKey) Decrypt(passphrase []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
key := make([]byte, pk.cipher.KeySize())
|
||||
pk.s2k(key, passphrase)
|
||||
block := pk.cipher.new(key)
|
||||
block := pk.cipher.new(decryptionKey)
|
||||
cfb := cipher.NewCFBDecrypter(block, pk.iv)
|
||||
|
||||
data := make([]byte, len(pk.encryptedData))
|
||||
@@ -428,35 +428,79 @@ func (pk *PrivateKey) Decrypt(passphrase []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encrypt encrypts an unencrypted private key using a passphrase.
|
||||
func (pk *PrivateKey) Encrypt(passphrase []byte) error {
|
||||
func (pk *PrivateKey) decryptWithCache(passphrase []byte, keyCache *s2k.Cache) error {
|
||||
if pk.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
if !pk.Encrypted {
|
||||
return nil
|
||||
}
|
||||
|
||||
key, err := keyCache.GetOrComputeDerivedKey(passphrase, pk.s2kParams, pk.cipher.KeySize())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pk.decrypt(key)
|
||||
}
|
||||
|
||||
// Decrypt decrypts an encrypted private key using a passphrase.
|
||||
func (pk *PrivateKey) Decrypt(passphrase []byte) error {
|
||||
if pk.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
if !pk.Encrypted {
|
||||
return nil
|
||||
}
|
||||
|
||||
key := make([]byte, pk.cipher.KeySize())
|
||||
pk.s2k(key, passphrase)
|
||||
return pk.decrypt(key)
|
||||
}
|
||||
|
||||
// DecryptPrivateKeys decrypts all encrypted keys with the given config and passphrase.
|
||||
// Avoids recomputation of similar s2k key derivations.
|
||||
func DecryptPrivateKeys(keys []*PrivateKey, passphrase []byte) error {
|
||||
// Create a cache to avoid recomputation of key derviations for the same passphrase.
|
||||
s2kCache := &s2k.Cache{}
|
||||
for _, key := range keys {
|
||||
if key != nil && !key.Dummy() && key.Encrypted {
|
||||
err := key.decryptWithCache(passphrase, s2kCache)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// encrypt encrypts an unencrypted private key.
|
||||
func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, cipherFunction CipherFunction) error {
|
||||
if pk.Dummy() {
|
||||
return errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
if pk.Encrypted {
|
||||
return nil
|
||||
}
|
||||
// check if encryptionKey has the correct size
|
||||
if len(key) != cipherFunction.KeySize() {
|
||||
return errors.InvalidArgumentError("supplied encryption key has the wrong size")
|
||||
}
|
||||
|
||||
priv := bytes.NewBuffer(nil)
|
||||
err := pk.serializePrivateKey(priv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Default config of private key encryption
|
||||
pk.cipher = CipherAES256
|
||||
s2kConfig := &s2k.Config{
|
||||
S2KMode: 3, //Iterated
|
||||
S2KCount: 65536,
|
||||
Hash: crypto.SHA256,
|
||||
}
|
||||
|
||||
pk.s2kParams, err = s2k.Generate(rand.Reader, s2kConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
privateKeyBytes := priv.Bytes()
|
||||
key := make([]byte, pk.cipher.KeySize())
|
||||
|
||||
pk.sha1Checksum = true
|
||||
pk.cipher = cipherFunction
|
||||
pk.s2kParams = params
|
||||
pk.s2k, err = pk.s2kParams.Function()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk.s2k(key, passphrase)
|
||||
}
|
||||
|
||||
privateKeyBytes := priv.Bytes()
|
||||
pk.sha1Checksum = true
|
||||
block := pk.cipher.new(key)
|
||||
pk.iv = make([]byte, pk.cipher.blockSize())
|
||||
_, err = rand.Read(pk.iv)
|
||||
@@ -487,6 +531,62 @@ func (pk *PrivateKey) Encrypt(passphrase []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// EncryptWithConfig encrypts an unencrypted private key using the passphrase and the config.
|
||||
func (pk *PrivateKey) EncryptWithConfig(passphrase []byte, config *Config) error {
|
||||
params, err := s2k.Generate(config.Random(), config.S2K())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Derive an encryption key with the configured s2k function.
|
||||
key := make([]byte, config.Cipher().KeySize())
|
||||
s2k, err := params.Function()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s2k(key, passphrase)
|
||||
// Encrypt the private key with the derived encryption key.
|
||||
return pk.encrypt(key, params, config.Cipher())
|
||||
}
|
||||
|
||||
// EncryptPrivateKeys encrypts all unencrypted keys with the given config and passphrase.
|
||||
// Only derives one key from the passphrase, which is then used to encrypt each key.
|
||||
func EncryptPrivateKeys(keys []*PrivateKey, passphrase []byte, config *Config) error {
|
||||
params, err := s2k.Generate(config.Random(), config.S2K())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Derive an encryption key with the configured s2k function.
|
||||
encryptionKey := make([]byte, config.Cipher().KeySize())
|
||||
s2k, err := params.Function()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s2k(encryptionKey, passphrase)
|
||||
for _, key := range keys {
|
||||
if key != nil && !key.Dummy() && !key.Encrypted {
|
||||
err = key.encrypt(encryptionKey, params, config.Cipher())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encrypt encrypts an unencrypted private key using a passphrase.
|
||||
func (pk *PrivateKey) Encrypt(passphrase []byte) error {
|
||||
// Default config of private key encryption
|
||||
config := &Config{
|
||||
S2KConfig: &s2k.Config{
|
||||
S2KMode: s2k.IteratedSaltedS2K,
|
||||
S2KCount: 65536,
|
||||
Hash: crypto.SHA256,
|
||||
} ,
|
||||
DefaultCipher: CipherAES256,
|
||||
}
|
||||
return pk.EncryptWithConfig(passphrase, config)
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
|
||||
switch priv := pk.PrivateKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
@@ -497,7 +597,7 @@ func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
|
||||
err = serializeElGamalPrivateKey(w, priv)
|
||||
case *ecdsa.PrivateKey:
|
||||
err = serializeECDSAPrivateKey(w, priv)
|
||||
case *ed25519.PrivateKey:
|
||||
case *eddsa.PrivateKey:
|
||||
err = serializeEdDSAPrivateKey(w, priv)
|
||||
case *ecdh.PrivateKey:
|
||||
err = serializeECDHPrivateKey(w, priv)
|
||||
@@ -601,8 +701,7 @@ func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
|
||||
|
||||
func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
|
||||
ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
|
||||
ecdsaPriv := new(ecdsa.PrivateKey)
|
||||
ecdsaPriv.PublicKey = *ecdsaPub
|
||||
ecdsaPriv := ecdsa.NewPrivateKey(*ecdsaPub)
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
d := new(encoding.MPI)
|
||||
@@ -610,8 +709,10 @@ func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
ecdsaPriv.D = new(big.Int).SetBytes(d.Bytes())
|
||||
if err := validateECDSAParameters(ecdsaPriv); err != nil {
|
||||
if err := ecdsaPriv.UnmarshalIntegerSecret(d.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ecdsa.Validate(ecdsaPriv); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = ecdsaPriv
|
||||
@@ -621,8 +722,7 @@ func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
|
||||
|
||||
func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
|
||||
ecdhPub := pk.PublicKey.PublicKey.(*ecdh.PublicKey)
|
||||
ecdhPriv := new(ecdh.PrivateKey)
|
||||
ecdhPriv.PublicKey = *ecdhPub
|
||||
ecdhPriv := ecdh.NewPrivateKey(*ecdhPub)
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
d := new(encoding.MPI)
|
||||
@@ -630,18 +730,23 @@ func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
ecdhPriv.D = d.Bytes()
|
||||
if err := validateECDHParameters(ecdhPriv); err != nil {
|
||||
if err := ecdhPriv.UnmarshalByteSecret(d.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ecdh.Validate(ecdhPriv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pk.PrivateKey = ecdhPriv
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
|
||||
eddsaPub := pk.PublicKey.PublicKey.(*ed25519.PublicKey)
|
||||
eddsaPriv := make(ed25519.PrivateKey, ed25519.PrivateKeySize)
|
||||
eddsaPub := pk.PublicKey.PublicKey.(*eddsa.PublicKey)
|
||||
eddsaPriv := eddsa.NewPrivateKey(*eddsaPub)
|
||||
eddsaPriv.PublicKey = *eddsaPub
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
d := new(encoding.MPI)
|
||||
@@ -649,64 +754,16 @@ func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
priv := d.Bytes()
|
||||
copy(eddsaPriv[32-len(priv):32], priv)
|
||||
copy(eddsaPriv[32:], (*eddsaPub)[:])
|
||||
if err := validateEdDSAParameters(&eddsaPriv); err != nil {
|
||||
if err = eddsaPriv.UnmarshalByteSecret(d.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
pk.PrivateKey = &eddsaPriv
|
||||
|
||||
return nil
|
||||
}
|
||||
if err := eddsa.Validate(eddsaPriv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func validateECDSAParameters(priv *ecdsa.PrivateKey) error {
|
||||
return validateCommonECC(priv.Curve, priv.D.Bytes(), priv.X, priv.Y)
|
||||
}
|
||||
pk.PrivateKey = eddsaPriv
|
||||
|
||||
func validateECDHParameters(priv *ecdh.PrivateKey) error {
|
||||
if priv.CurveType != ecc.Curve25519 {
|
||||
return validateCommonECC(priv.Curve, priv.D, priv.X, priv.Y)
|
||||
}
|
||||
// Handle Curve25519
|
||||
Q := priv.X.Bytes()[1:]
|
||||
var d [32]byte
|
||||
// Copy reversed d
|
||||
l := len(priv.D)
|
||||
for i := 0; i < l; i++ {
|
||||
d[i] = priv.D[l-i-1]
|
||||
}
|
||||
var expectedQ [32]byte
|
||||
curve25519.ScalarBaseMult(&expectedQ, &d)
|
||||
if !bytes.Equal(Q, expectedQ[:]) {
|
||||
return errors.KeyInvalidError("ECDH curve25519: invalid point")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateCommonECC(curve elliptic.Curve, d []byte, X, Y *big.Int) error {
|
||||
// the public point should not be at infinity (0,0)
|
||||
zero := new(big.Int)
|
||||
if X.Cmp(zero) == 0 && Y.Cmp(zero) == 0 {
|
||||
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", curve.Params().Name))
|
||||
}
|
||||
// re-derive the public point Q' = (X,Y) = dG
|
||||
// to compare to declared Q in public key
|
||||
expectedX, expectedY := curve.ScalarBaseMult(d)
|
||||
if X.Cmp(expectedX) != 0 || Y.Cmp(expectedY) != 0 {
|
||||
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", curve.Params().Name))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateEdDSAParameters(priv *ed25519.PrivateKey) error {
|
||||
// In EdDSA, the serialized public point is stored as part of private key (together with the seed),
|
||||
// hence we can re-derive the key from the seed
|
||||
seed := priv.Seed()
|
||||
expectedPriv := ed25519.NewKeyFromSeed(seed)
|
||||
if !bytes.Equal(*priv, expectedPriv) {
|
||||
return errors.KeyInvalidError("eddsa: invalid point")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
133
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
generated
vendored
133
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
generated
vendored
@@ -7,8 +7,6 @@ package packet
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
@@ -22,12 +20,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
type kdfHashFunction byte
|
||||
@@ -124,10 +123,10 @@ func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDSA,
|
||||
PublicKey: pub,
|
||||
p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)),
|
||||
p: encoding.NewMPI(pub.MarshalPoint()),
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByCurve(pub.Curve)
|
||||
curveInfo := ecc.FindByCurve(pub.GetCurve())
|
||||
if curveInfo == nil {
|
||||
panic("unknown elliptic curve")
|
||||
}
|
||||
@@ -138,39 +137,29 @@ func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey
|
||||
|
||||
func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey {
|
||||
var pk *PublicKey
|
||||
var curveInfo *ecc.CurveInfo
|
||||
var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()})
|
||||
if pub.CurveType == ecc.Curve25519 {
|
||||
pk = &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDH,
|
||||
PublicKey: pub,
|
||||
p: encoding.NewMPI(pub.X.Bytes()),
|
||||
kdf: kdf,
|
||||
}
|
||||
curveInfo = ecc.FindByName("Curve25519")
|
||||
} else {
|
||||
pk = &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDH,
|
||||
PublicKey: pub,
|
||||
p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)),
|
||||
kdf: kdf,
|
||||
}
|
||||
curveInfo = ecc.FindByCurve(pub.Curve)
|
||||
pk = &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
PubKeyAlgo: PubKeyAlgoECDH,
|
||||
PublicKey: pub,
|
||||
p: encoding.NewMPI(pub.MarshalPoint()),
|
||||
kdf: kdf,
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByCurve(pub.GetCurve())
|
||||
|
||||
if curveInfo == nil {
|
||||
panic("unknown elliptic curve")
|
||||
}
|
||||
|
||||
pk.oid = curveInfo.Oid
|
||||
pk.setFingerprintAndKeyId()
|
||||
return pk
|
||||
}
|
||||
|
||||
func NewEdDSAPublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey {
|
||||
curveInfo := ecc.FindByName("Ed25519")
|
||||
func NewEdDSAPublicKey(creationTime time.Time, pub *eddsa.PublicKey) *PublicKey {
|
||||
curveInfo := ecc.FindByCurve(pub.GetCurve())
|
||||
pk := &PublicKey{
|
||||
Version: 4,
|
||||
CreationTime: creationTime,
|
||||
@@ -178,7 +167,7 @@ func NewEdDSAPublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKe
|
||||
PublicKey: pub,
|
||||
oid: curveInfo.Oid,
|
||||
// Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B
|
||||
p: encoding.NewMPI(append([]byte{0x40}, *pub...)),
|
||||
p: encoding.NewMPI(pub.MarshalPoint()),
|
||||
}
|
||||
|
||||
pk.setFingerprintAndKeyId()
|
||||
@@ -340,17 +329,20 @@ func (pk *PublicKey) parseECDSA(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
var c elliptic.Curve
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil || curveInfo.SigAlgorithm != ecc.ECDSA {
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
c, ok := curveInfo.Curve.(ecc.ECDSACurve)
|
||||
if !ok {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
}
|
||||
c = curveInfo.Curve
|
||||
x, y := elliptic.Unmarshal(c, pk.p.Bytes())
|
||||
if x == nil {
|
||||
return errors.UnsupportedError("failed to parse EC point")
|
||||
}
|
||||
pk.PublicKey = &ecdsa.PublicKey{Curve: c, X: x, Y: y}
|
||||
|
||||
ecdsaKey := ecdsa.NewPublicKey(c)
|
||||
err = ecdsaKey.UnmarshalPoint(pk.p.Bytes())
|
||||
pk.PublicKey = ecdsaKey
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -371,24 +363,16 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
|
||||
}
|
||||
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
c, ok := curveInfo.Curve.(ecc.ECDHCurve)
|
||||
if !ok {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
c := curveInfo.Curve
|
||||
cType := curveInfo.CurveType
|
||||
|
||||
var x, y *big.Int
|
||||
if cType == ecc.Curve25519 {
|
||||
x = new(big.Int)
|
||||
x.SetBytes(pk.p.Bytes())
|
||||
} else {
|
||||
x, y = elliptic.Unmarshal(c, pk.p.Bytes())
|
||||
}
|
||||
if x == nil {
|
||||
return errors.UnsupportedError("failed to parse EC point")
|
||||
}
|
||||
|
||||
if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 {
|
||||
return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
|
||||
}
|
||||
@@ -404,16 +388,10 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
|
||||
return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2])))
|
||||
}
|
||||
|
||||
pk.PublicKey = &ecdh.PublicKey{
|
||||
CurveType: cType,
|
||||
Curve: c,
|
||||
X: x,
|
||||
Y: y,
|
||||
KDF: ecdh.KDF{
|
||||
Hash: kdfHash,
|
||||
Cipher: kdfCipher,
|
||||
},
|
||||
}
|
||||
ecdhKey := ecdh.NewPublicKey(c, kdfHash, kdfCipher)
|
||||
err = ecdhKey.UnmarshalPoint(pk.p.Bytes())
|
||||
pk.PublicKey = ecdhKey
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -423,26 +401,37 @@ func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
curveInfo := ecc.FindByOid(pk.oid)
|
||||
if curveInfo == nil || curveInfo.SigAlgorithm != ecc.EdDSA {
|
||||
if curveInfo == nil {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
c, ok := curveInfo.Curve.(ecc.EdDSACurve)
|
||||
if !ok {
|
||||
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
|
||||
}
|
||||
|
||||
pk.p = new(encoding.MPI)
|
||||
if _, err = pk.p.ReadFrom(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
eddsa := make(ed25519.PublicKey, ed25519.PublicKeySize)
|
||||
if len(pk.p.Bytes()) == 0 {
|
||||
return errors.StructuralError("empty EdDSA public key")
|
||||
}
|
||||
|
||||
pub := eddsa.NewPublicKey(c)
|
||||
|
||||
switch flag := pk.p.Bytes()[0]; flag {
|
||||
case 0x04:
|
||||
// TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt
|
||||
return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
|
||||
case 0x40:
|
||||
copy(eddsa[:], pk.p.Bytes()[1:])
|
||||
err = pub.UnmarshalPoint(pk.p.Bytes())
|
||||
default:
|
||||
return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
|
||||
}
|
||||
|
||||
pk.PublicKey = &eddsa
|
||||
pk.PublicKey = pub
|
||||
return
|
||||
}
|
||||
|
||||
@@ -611,7 +600,7 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
|
||||
}
|
||||
signed.Write(sig.HashSuffix)
|
||||
hashBytes := signed.Sum(nil)
|
||||
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
|
||||
if sig.Version == 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) {
|
||||
return errors.SignatureError("hash tag doesn't match")
|
||||
}
|
||||
|
||||
@@ -645,16 +634,8 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
|
||||
}
|
||||
return nil
|
||||
case PubKeyAlgoEdDSA:
|
||||
eddsaPublicKey := pk.PublicKey.(*ed25519.PublicKey)
|
||||
|
||||
sigR := sig.EdDSASigR.Bytes()
|
||||
sigS := sig.EdDSASigS.Bytes()
|
||||
|
||||
eddsaSig := make([]byte, ed25519.SignatureSize)
|
||||
copy(eddsaSig[32-len(sigR):32], sigR)
|
||||
copy(eddsaSig[64-len(sigS):], sigS)
|
||||
|
||||
if !ed25519.Verify(*eddsaPublicKey, hashBytes, eddsaSig) {
|
||||
eddsaPublicKey := pk.PublicKey.(*eddsa.PublicKey)
|
||||
if !eddsa.Verify(eddsaPublicKey, hashBytes, sig.EdDSASigR.Bytes(), sig.EdDSASigS.Bytes()) {
|
||||
return errors.SignatureError("EdDSA verification failure")
|
||||
}
|
||||
return nil
|
||||
|
||||
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
generated
vendored
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
generated
vendored
@@ -44,9 +44,17 @@ func (r *Reader) Next() (p Packet, err error) {
|
||||
continue
|
||||
}
|
||||
// TODO: Add strict mode that rejects unknown packets, instead of ignoring them.
|
||||
if _, ok := err.(errors.UnknownPacketTypeError); !ok {
|
||||
return nil, err
|
||||
if _, ok := err.(errors.UnknownPacketTypeError); ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := err.(errors.UnsupportedError); ok {
|
||||
switch p.(type) {
|
||||
case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, io.EOF
|
||||
|
||||
261
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
generated
vendored
261
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
generated
vendored
@@ -8,18 +8,17 @@ import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"encoding/asn1"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -67,10 +66,24 @@ type Signature struct {
|
||||
|
||||
SigLifetimeSecs, KeyLifetimeSecs *uint32
|
||||
PreferredSymmetric, PreferredHash, PreferredCompression []uint8
|
||||
PreferredAEAD []uint8
|
||||
PreferredCipherSuites [][2]uint8
|
||||
IssuerKeyId *uint64
|
||||
IssuerFingerprint []byte
|
||||
SignerUserId *string
|
||||
IsPrimaryId *bool
|
||||
Notations []*Notation
|
||||
|
||||
// TrustLevel and TrustAmount can be set by the signer to assert that
|
||||
// the key is not only valid but also trustworthy at the specified
|
||||
// level.
|
||||
// See RFC 4880, section 5.2.3.13 for details.
|
||||
TrustLevel TrustLevel
|
||||
TrustAmount TrustAmount
|
||||
|
||||
// TrustRegularExpression can be used in conjunction with trust Signature
|
||||
// packets to limit the scope of the trust that is extended.
|
||||
// See RFC 4880, section 5.2.3.14 for details.
|
||||
TrustRegularExpression *string
|
||||
|
||||
// PolicyURI can be set to the URI of a document that describes the
|
||||
// policy under which the signature was issued. See RFC 4880, section
|
||||
@@ -89,8 +102,8 @@ type Signature struct {
|
||||
|
||||
// In a self-signature, these flags are set there is a features subpacket
|
||||
// indicating that the issuer implementation supports these features
|
||||
// (section 5.2.5.25).
|
||||
MDC, AEAD, V5Keys bool
|
||||
// see https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#features-subpacket
|
||||
SEIPDv1, SEIPDv2 bool
|
||||
|
||||
// EmbeddedSignature, if non-nil, is a signature of the parent key, by
|
||||
// this key. This prevents an attacker from claiming another's signing
|
||||
@@ -126,7 +139,13 @@ func (sig *Signature) parse(r io.Reader) (err error) {
|
||||
}
|
||||
|
||||
var ok bool
|
||||
sig.Hash, ok = s2k.HashIdToHash(buf[2])
|
||||
|
||||
if sig.Version < 5 {
|
||||
sig.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2])
|
||||
} else {
|
||||
sig.Hash, ok = algorithm.HashIdToHash(buf[2])
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
|
||||
}
|
||||
@@ -137,7 +156,11 @@ func (sig *Signature) parse(r io.Reader) (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sig.buildHashSuffix(hashedSubpackets)
|
||||
err = sig.buildHashSuffix(hashedSubpackets)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = parseSignatureSubpackets(sig, hashedSubpackets, true)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -221,19 +244,23 @@ type signatureSubpacketType uint8
|
||||
const (
|
||||
creationTimeSubpacket signatureSubpacketType = 2
|
||||
signatureExpirationSubpacket signatureSubpacketType = 3
|
||||
trustSubpacket signatureSubpacketType = 5
|
||||
regularExpressionSubpacket signatureSubpacketType = 6
|
||||
keyExpirationSubpacket signatureSubpacketType = 9
|
||||
prefSymmetricAlgosSubpacket signatureSubpacketType = 11
|
||||
issuerSubpacket signatureSubpacketType = 16
|
||||
notationDataSubpacket signatureSubpacketType = 20
|
||||
prefHashAlgosSubpacket signatureSubpacketType = 21
|
||||
prefCompressionSubpacket signatureSubpacketType = 22
|
||||
primaryUserIdSubpacket signatureSubpacketType = 25
|
||||
policyUriSubpacket signatureSubpacketType = 26
|
||||
keyFlagsSubpacket signatureSubpacketType = 27
|
||||
signerUserIdSubpacket signatureSubpacketType = 28
|
||||
reasonForRevocationSubpacket signatureSubpacketType = 29
|
||||
featuresSubpacket signatureSubpacketType = 30
|
||||
embeddedSignatureSubpacket signatureSubpacketType = 32
|
||||
issuerFingerprintSubpacket signatureSubpacketType = 33
|
||||
prefAeadAlgosSubpacket signatureSubpacketType = 34
|
||||
prefCipherSuitesSubpacket signatureSubpacketType = 39
|
||||
)
|
||||
|
||||
// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
|
||||
@@ -244,6 +271,10 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
packetType signatureSubpacketType
|
||||
isCritical bool
|
||||
)
|
||||
if len(subpacket) == 0 {
|
||||
err = errors.StructuralError("zero length signature subpacket")
|
||||
return
|
||||
}
|
||||
switch {
|
||||
case subpacket[0] < 192:
|
||||
length = uint32(subpacket[0])
|
||||
@@ -277,12 +308,14 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
isCritical = subpacket[0]&0x80 == 0x80
|
||||
subpacket = subpacket[1:]
|
||||
sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
|
||||
if !isHashed &&
|
||||
packetType != issuerSubpacket &&
|
||||
packetType != issuerFingerprintSubpacket &&
|
||||
packetType != embeddedSignatureSubpacket {
|
||||
return
|
||||
}
|
||||
switch packetType {
|
||||
case creationTimeSubpacket:
|
||||
if !isHashed {
|
||||
err = errors.StructuralError("signature creation time in non-hashed area")
|
||||
return
|
||||
}
|
||||
if len(subpacket) != 4 {
|
||||
err = errors.StructuralError("signature creation time not four bytes")
|
||||
return
|
||||
@@ -291,20 +324,35 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
sig.CreationTime = time.Unix(int64(t), 0)
|
||||
case signatureExpirationSubpacket:
|
||||
// Signature expiration time, section 5.2.3.10
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
if len(subpacket) != 4 {
|
||||
err = errors.StructuralError("expiration subpacket with bad length")
|
||||
return
|
||||
}
|
||||
sig.SigLifetimeSecs = new(uint32)
|
||||
*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
|
||||
case keyExpirationSubpacket:
|
||||
// Key expiration time, section 5.2.3.6
|
||||
if !isHashed {
|
||||
case trustSubpacket:
|
||||
if len(subpacket) != 2 {
|
||||
err = errors.StructuralError("trust subpacket with bad length")
|
||||
return
|
||||
}
|
||||
// Trust level and amount, section 5.2.3.13
|
||||
sig.TrustLevel = TrustLevel(subpacket[0])
|
||||
sig.TrustAmount = TrustAmount(subpacket[1])
|
||||
case regularExpressionSubpacket:
|
||||
if len(subpacket) == 0 {
|
||||
err = errors.StructuralError("regexp subpacket with bad length")
|
||||
return
|
||||
}
|
||||
// Trust regular expression, section 5.2.3.14
|
||||
// RFC specifies the string should be null-terminated; remove a null byte from the end
|
||||
if subpacket[len(subpacket)-1] != 0x00 {
|
||||
err = errors.StructuralError("expected regular expression to be null-terminated")
|
||||
return
|
||||
}
|
||||
trustRegularExpression := string(subpacket[:len(subpacket)-1])
|
||||
sig.TrustRegularExpression = &trustRegularExpression
|
||||
case keyExpirationSubpacket:
|
||||
// Key expiration time, section 5.2.3.6
|
||||
if len(subpacket) != 4 {
|
||||
err = errors.StructuralError("key expiration subpacket with bad length")
|
||||
return
|
||||
@@ -313,41 +361,52 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
|
||||
case prefSymmetricAlgosSubpacket:
|
||||
// Preferred symmetric algorithms, section 5.2.3.7
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
sig.PreferredSymmetric = make([]byte, len(subpacket))
|
||||
copy(sig.PreferredSymmetric, subpacket)
|
||||
case issuerSubpacket:
|
||||
// Issuer, section 5.2.3.5
|
||||
if sig.Version > 4 {
|
||||
err = errors.StructuralError("issuer subpacket found in v5 key")
|
||||
return
|
||||
}
|
||||
// Issuer, section 5.2.3.5
|
||||
if len(subpacket) != 8 {
|
||||
err = errors.StructuralError("issuer subpacket with bad length")
|
||||
return
|
||||
}
|
||||
sig.IssuerKeyId = new(uint64)
|
||||
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
|
||||
case prefHashAlgosSubpacket:
|
||||
// Preferred hash algorithms, section 5.2.3.8
|
||||
if !isHashed {
|
||||
case notationDataSubpacket:
|
||||
// Notation data, section 5.2.3.16
|
||||
if len(subpacket) < 8 {
|
||||
err = errors.StructuralError("notation data subpacket with bad length")
|
||||
return
|
||||
}
|
||||
|
||||
nameLength := uint32(subpacket[4])<<8 | uint32(subpacket[5])
|
||||
valueLength := uint32(subpacket[6])<<8 | uint32(subpacket[7])
|
||||
if len(subpacket) != int(nameLength)+int(valueLength)+8 {
|
||||
err = errors.StructuralError("notation data subpacket with bad length")
|
||||
return
|
||||
}
|
||||
|
||||
notation := Notation{
|
||||
IsHumanReadable: (subpacket[0] & 0x80) == 0x80,
|
||||
Name: string(subpacket[8:(nameLength + 8)]),
|
||||
Value: subpacket[(nameLength + 8):(valueLength + nameLength + 8)],
|
||||
IsCritical: isCritical,
|
||||
}
|
||||
|
||||
sig.Notations = append(sig.Notations, ¬ation)
|
||||
case prefHashAlgosSubpacket:
|
||||
// Preferred hash algorithms, section 5.2.3.8
|
||||
sig.PreferredHash = make([]byte, len(subpacket))
|
||||
copy(sig.PreferredHash, subpacket)
|
||||
case prefCompressionSubpacket:
|
||||
// Preferred compression algorithms, section 5.2.3.9
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
sig.PreferredCompression = make([]byte, len(subpacket))
|
||||
copy(sig.PreferredCompression, subpacket)
|
||||
case primaryUserIdSubpacket:
|
||||
// Primary User ID, section 5.2.3.19
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
if len(subpacket) != 1 {
|
||||
err = errors.StructuralError("primary user id subpacket with bad length")
|
||||
return
|
||||
@@ -358,9 +417,6 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
}
|
||||
case keyFlagsSubpacket:
|
||||
// Key flags, section 5.2.3.21
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
if len(subpacket) == 0 {
|
||||
err = errors.StructuralError("empty key flags subpacket")
|
||||
return
|
||||
@@ -387,11 +443,11 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
if subpacket[0]&KeyFlagGroupKey != 0 {
|
||||
sig.FlagGroupKey = true
|
||||
}
|
||||
case signerUserIdSubpacket:
|
||||
userId := string(subpacket)
|
||||
sig.SignerUserId = &userId
|
||||
case reasonForRevocationSubpacket:
|
||||
// Reason For Revocation, section 5.2.3.23
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
if len(subpacket) == 0 {
|
||||
err = errors.StructuralError("empty revocation reason subpacket")
|
||||
return
|
||||
@@ -403,18 +459,13 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
// Features subpacket, section 5.2.3.24 specifies a very general
|
||||
// mechanism for OpenPGP implementations to signal support for new
|
||||
// features.
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
if len(subpacket) > 0 {
|
||||
if subpacket[0]&0x01 != 0 {
|
||||
sig.MDC = true
|
||||
sig.SEIPDv1 = true
|
||||
}
|
||||
if subpacket[0]&0x02 != 0 {
|
||||
sig.AEAD = true
|
||||
}
|
||||
if subpacket[0]&0x04 != 0 {
|
||||
sig.V5Keys = true
|
||||
// 0x02 and 0x04 are reserved
|
||||
if subpacket[0]&0x08 != 0 {
|
||||
sig.SEIPDv2 = true
|
||||
}
|
||||
}
|
||||
case embeddedSignatureSubpacket:
|
||||
@@ -437,11 +488,12 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
}
|
||||
case policyUriSubpacket:
|
||||
// Policy URI, section 5.2.3.20
|
||||
if !isHashed {
|
||||
return
|
||||
}
|
||||
sig.PolicyURI = string(subpacket)
|
||||
case issuerFingerprintSubpacket:
|
||||
if len(subpacket) == 0 {
|
||||
err = errors.StructuralError("empty issuer fingerprint subpacket")
|
||||
return
|
||||
}
|
||||
v, l := subpacket[0], len(subpacket[1:])
|
||||
if v == 5 && l != 32 || v != 5 && l != 20 {
|
||||
return nil, errors.StructuralError("bad fingerprint length")
|
||||
@@ -454,13 +506,19 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
|
||||
} else {
|
||||
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[13:21])
|
||||
}
|
||||
case prefAeadAlgosSubpacket:
|
||||
// Preferred symmetric algorithms, section 5.2.3.8
|
||||
if !isHashed {
|
||||
case prefCipherSuitesSubpacket:
|
||||
// Preferred AEAD cipher suites
|
||||
// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#name-preferred-aead-ciphersuites
|
||||
if len(subpacket)%2 != 0 {
|
||||
err = errors.StructuralError("invalid aead cipher suite length")
|
||||
return
|
||||
}
|
||||
sig.PreferredAEAD = make([]byte, len(subpacket))
|
||||
copy(sig.PreferredAEAD, subpacket)
|
||||
|
||||
sig.PreferredCipherSuites = make([][2]byte, len(subpacket)/2)
|
||||
|
||||
for i := 0; i < len(subpacket)/2; i++ {
|
||||
sig.PreferredCipherSuites[i] = [2]uint8{subpacket[2*i], subpacket[2*i+1]}
|
||||
}
|
||||
default:
|
||||
if isCritical {
|
||||
err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
|
||||
@@ -558,7 +616,15 @@ func (sig *Signature) SigExpired(currentTime time.Time) bool {
|
||||
|
||||
// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
|
||||
func (sig *Signature) buildHashSuffix(hashedSubpackets []byte) (err error) {
|
||||
hash, ok := s2k.HashToHashId(sig.Hash)
|
||||
var hashId byte
|
||||
var ok bool
|
||||
|
||||
if sig.Version < 5 {
|
||||
hashId, ok = algorithm.HashToHashIdWithSha1(sig.Hash)
|
||||
} else {
|
||||
hashId, ok = algorithm.HashToHashId(sig.Hash)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
sig.HashSuffix = nil
|
||||
return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
|
||||
@@ -568,7 +634,7 @@ func (sig *Signature) buildHashSuffix(hashedSubpackets []byte) (err error) {
|
||||
uint8(sig.Version),
|
||||
uint8(sig.SigType),
|
||||
uint8(sig.PubKeyAlgo),
|
||||
uint8(hash),
|
||||
uint8(hashId),
|
||||
uint8(len(hashedSubpackets) >> 8),
|
||||
uint8(len(hashedSubpackets)),
|
||||
})
|
||||
@@ -649,26 +715,19 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
||||
sig.DSASigS = new(encoding.MPI).SetBig(s)
|
||||
}
|
||||
case PubKeyAlgoECDSA:
|
||||
var r, s *big.Int
|
||||
if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
|
||||
// direct support, avoid asn1 wrapping/unwrapping
|
||||
r, s, err = ecdsa.Sign(config.Random(), pk, digest)
|
||||
} else {
|
||||
var b []byte
|
||||
b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
|
||||
if err == nil {
|
||||
r, s, err = unwrapECDSASig(b)
|
||||
}
|
||||
}
|
||||
sk := priv.PrivateKey.(*ecdsa.PrivateKey)
|
||||
r, s, err := ecdsa.Sign(config.Random(), sk, digest)
|
||||
|
||||
if err == nil {
|
||||
sig.ECDSASigR = new(encoding.MPI).SetBig(r)
|
||||
sig.ECDSASigS = new(encoding.MPI).SetBig(s)
|
||||
}
|
||||
case PubKeyAlgoEdDSA:
|
||||
sigdata, err := priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, crypto.Hash(0))
|
||||
sk := priv.PrivateKey.(*eddsa.PrivateKey)
|
||||
r, s, err := eddsa.Sign(sk, digest)
|
||||
if err == nil {
|
||||
sig.EdDSASigR = encoding.NewMPI(sigdata[:32])
|
||||
sig.EdDSASigS = encoding.NewMPI(sigdata[32:])
|
||||
sig.EdDSASigR = encoding.NewMPI(r)
|
||||
sig.EdDSASigS = encoding.NewMPI(s)
|
||||
}
|
||||
default:
|
||||
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
||||
@@ -677,19 +736,6 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
|
||||
return
|
||||
}
|
||||
|
||||
// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA
|
||||
// signature.
|
||||
func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
|
||||
var ecsdaSig struct {
|
||||
R, S *big.Int
|
||||
}
|
||||
_, err = asn1.Unmarshal(b, &ecsdaSig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return ecsdaSig.R, ecsdaSig.S, nil
|
||||
}
|
||||
|
||||
// SignUserId computes a signature from priv, asserting that pub is a valid
|
||||
// key for the identity id. On success, the signature is stored in sig. Call
|
||||
// Serialize to write it out.
|
||||
@@ -858,12 +904,15 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp
|
||||
if sig.IssuerKeyId != nil && sig.Version == 4 {
|
||||
keyId := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
|
||||
subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, true, keyId})
|
||||
subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
|
||||
}
|
||||
if sig.IssuerFingerprint != nil {
|
||||
contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...)
|
||||
subpackets = append(subpackets, outputSubpacket{true, issuerFingerprintSubpacket, sig.Version == 5, contents})
|
||||
}
|
||||
if sig.SignerUserId != nil {
|
||||
subpackets = append(subpackets, outputSubpacket{true, signerUserIdSubpacket, false, []byte(*sig.SignerUserId)})
|
||||
}
|
||||
if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
|
||||
sigLifetime := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
|
||||
@@ -898,23 +947,40 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp
|
||||
subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
|
||||
}
|
||||
|
||||
for _, notation := range sig.Notations {
|
||||
subpackets = append(
|
||||
subpackets,
|
||||
outputSubpacket{
|
||||
true,
|
||||
notationDataSubpacket,
|
||||
notation.IsCritical,
|
||||
notation.getData(),
|
||||
})
|
||||
}
|
||||
|
||||
// The following subpackets may only appear in self-signatures.
|
||||
|
||||
var features = byte(0x00)
|
||||
if sig.MDC {
|
||||
if sig.SEIPDv1 {
|
||||
features |= 0x01
|
||||
}
|
||||
if sig.AEAD {
|
||||
features |= 0x02
|
||||
}
|
||||
if sig.V5Keys {
|
||||
features |= 0x04
|
||||
if sig.SEIPDv2 {
|
||||
features |= 0x08
|
||||
}
|
||||
|
||||
if features != 0x00 {
|
||||
subpackets = append(subpackets, outputSubpacket{true, featuresSubpacket, false, []byte{features}})
|
||||
}
|
||||
|
||||
if sig.TrustLevel != 0 {
|
||||
subpackets = append(subpackets, outputSubpacket{true, trustSubpacket, true, []byte{byte(sig.TrustLevel), byte(sig.TrustAmount)}})
|
||||
}
|
||||
|
||||
if sig.TrustRegularExpression != nil {
|
||||
// RFC specifies the string should be null-terminated; add a null byte to the end
|
||||
subpackets = append(subpackets, outputSubpacket{true, regularExpressionSubpacket, true, []byte(*sig.TrustRegularExpression + "\000")})
|
||||
}
|
||||
|
||||
if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
|
||||
keyLifetime := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
|
||||
@@ -941,8 +1007,13 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp
|
||||
subpackets = append(subpackets, outputSubpacket{true, policyUriSubpacket, false, []uint8(sig.PolicyURI)})
|
||||
}
|
||||
|
||||
if len(sig.PreferredAEAD) > 0 {
|
||||
subpackets = append(subpackets, outputSubpacket{true, prefAeadAlgosSubpacket, false, sig.PreferredAEAD})
|
||||
if len(sig.PreferredCipherSuites) > 0 {
|
||||
serialized := make([]byte, len(sig.PreferredCipherSuites)*2)
|
||||
for i, cipherSuite := range sig.PreferredCipherSuites {
|
||||
serialized[2*i] = cipherSuite[0]
|
||||
serialized[2*i+1] = cipherSuite[1]
|
||||
}
|
||||
subpackets = append(subpackets, outputSubpacket{true, prefCipherSuitesSubpacket, false, serialized})
|
||||
}
|
||||
|
||||
// Revocation reason appears only in revocation signatures and is serialized as per section 5.2.3.23.
|
||||
@@ -984,7 +1055,7 @@ func (sig *Signature) AddMetadataToHashSuffix() {
|
||||
n := sig.HashSuffix[len(sig.HashSuffix)-8:]
|
||||
l := uint64(
|
||||
uint64(n[0])<<56 | uint64(n[1])<<48 | uint64(n[2])<<40 | uint64(n[3])<<32 |
|
||||
uint64(n[4])<<24 | uint64(n[5])<<16 | uint64(n[6])<<8 | uint64(n[7]))
|
||||
uint64(n[4])<<24 | uint64(n[5])<<16 | uint64(n[6])<<8 | uint64(n[7]))
|
||||
|
||||
suffix := bytes.NewBuffer(nil)
|
||||
suffix.Write(sig.HashSuffix[:l])
|
||||
|
||||
109
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
109
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
@@ -14,8 +14,8 @@ import (
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
)
|
||||
|
||||
// This is the largest session key that we'll support. Since no 512-bit cipher
|
||||
// has even been seriously used, this is comfortably large.
|
||||
// This is the largest session key that we'll support. Since at most 256-bit cipher
|
||||
// is supported in OpenPGP, this is large enough to contain also the auth tag.
|
||||
const maxSessionKeySizeInBytes = 64
|
||||
|
||||
// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
|
||||
@@ -25,13 +25,16 @@ type SymmetricKeyEncrypted struct {
|
||||
CipherFunc CipherFunction
|
||||
Mode AEADMode
|
||||
s2k func(out, in []byte)
|
||||
aeadNonce []byte
|
||||
encryptedKey []byte
|
||||
iv []byte
|
||||
encryptedKey []byte // Contains also the authentication tag for AEAD
|
||||
}
|
||||
|
||||
// parse parses an SymmetricKeyEncrypted packet as specified in
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#name-symmetric-key-encrypted-ses
|
||||
func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
// RFC 4880, section 5.3.
|
||||
var buf [2]byte
|
||||
var buf [1]byte
|
||||
|
||||
// Version
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,17 +42,22 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
if ske.Version != 4 && ske.Version != 5 {
|
||||
return errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
|
||||
}
|
||||
ske.CipherFunc = CipherFunction(buf[1])
|
||||
if ske.CipherFunc.KeySize() == 0 {
|
||||
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
|
||||
|
||||
// Cipher function
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
ske.CipherFunc = CipherFunction(buf[0])
|
||||
if !ske.CipherFunc.IsSupported() {
|
||||
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[0])))
|
||||
}
|
||||
|
||||
if ske.Version == 5 {
|
||||
mode := make([]byte, 1)
|
||||
if _, err := r.Read(mode); err != nil {
|
||||
return errors.StructuralError("cannot read AEAD octect from packet")
|
||||
// AEAD mode
|
||||
if _, err := readFull(r, buf[:]); err != nil {
|
||||
return errors.StructuralError("cannot read AEAD octet from packet")
|
||||
}
|
||||
ske.Mode = AEADMode(mode[0])
|
||||
ske.Mode = AEADMode(buf[0])
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -61,13 +69,14 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
||||
}
|
||||
|
||||
if ske.Version == 5 {
|
||||
// AEAD nonce
|
||||
nonce := make([]byte, ske.Mode.NonceLength())
|
||||
_, err := readFull(r, nonce)
|
||||
if err != nil && err != io.ErrUnexpectedEOF {
|
||||
return err
|
||||
// AEAD IV
|
||||
iv := make([]byte, ske.Mode.IvLength())
|
||||
_, err := readFull(r, iv)
|
||||
if err != nil {
|
||||
return errors.StructuralError("cannot read AEAD IV")
|
||||
}
|
||||
ske.aeadNonce = nonce
|
||||
|
||||
ske.iv = iv
|
||||
}
|
||||
|
||||
encryptedKey := make([]byte, maxSessionKeySizeInBytes)
|
||||
@@ -128,11 +137,10 @@ func (ske *SymmetricKeyEncrypted) decryptV4(key []byte) ([]byte, CipherFunction,
|
||||
}
|
||||
|
||||
func (ske *SymmetricKeyEncrypted) decryptV5(key []byte) ([]byte, error) {
|
||||
blockCipher := CipherFunction(ske.CipherFunc).new(key)
|
||||
aead := ske.Mode.new(blockCipher)
|
||||
|
||||
adata := []byte{0xc3, byte(5), byte(ske.CipherFunc), byte(ske.Mode)}
|
||||
plaintextKey, err := aead.Open(nil, ske.aeadNonce, ske.encryptedKey, adata)
|
||||
aead := getEncryptedKeyAeadInstance(ske.CipherFunc, ske.Mode, key, adata)
|
||||
|
||||
plaintextKey, err := aead.Open(nil, ske.iv, ske.encryptedKey, adata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,17 +150,12 @@ func (ske *SymmetricKeyEncrypted) decryptV5(key []byte) ([]byte, error) {
|
||||
// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w.
|
||||
// The packet contains a random session key, encrypted by a key derived from
|
||||
// the given passphrase. The session key is returned and must be passed to
|
||||
// SerializeSymmetricallyEncrypted or SerializeAEADEncrypted, depending on
|
||||
// whether config.AEADConfig != nil.
|
||||
// SerializeSymmetricallyEncrypted.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
|
||||
cipherFunc := config.Cipher()
|
||||
keySize := cipherFunc.KeySize()
|
||||
if keySize == 0 {
|
||||
return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
||||
}
|
||||
|
||||
sessionKey := make([]byte, keySize)
|
||||
sessionKey := make([]byte, cipherFunc.KeySize())
|
||||
_, err = io.ReadFull(config.Random(), sessionKey)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -169,9 +172,8 @@ func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Conf
|
||||
|
||||
// SerializeSymmetricKeyEncryptedReuseKey serializes a symmetric key packet to w.
|
||||
// The packet contains the given session key, encrypted by a key derived from
|
||||
// the given passphrase. The session key must be passed to
|
||||
// SerializeSymmetricallyEncrypted or SerializeAEADEncrypted, depending on
|
||||
// whether config.AEADConfig != nil.
|
||||
// the given passphrase. The returned session key must be passed to
|
||||
// SerializeSymmetricallyEncrypted.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, config *Config) (err error) {
|
||||
var version int
|
||||
@@ -181,16 +183,17 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
version = 4
|
||||
}
|
||||
cipherFunc := config.Cipher()
|
||||
keySize := cipherFunc.KeySize()
|
||||
if keySize == 0 {
|
||||
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
||||
// cipherFunc must be AES
|
||||
if !cipherFunc.IsSupported() || cipherFunc < CipherAES128 || cipherFunc > CipherAES256 {
|
||||
return errors.UnsupportedError("unsupported cipher: " + strconv.Itoa(int(cipherFunc)))
|
||||
}
|
||||
|
||||
keySize := cipherFunc.KeySize()
|
||||
s2kBuf := new(bytes.Buffer)
|
||||
keyEncryptingKey := make([]byte, keySize)
|
||||
// s2k.Serialize salts and stretches the passphrase, and writes the
|
||||
// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
|
||||
err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
|
||||
err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, config.S2K())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -201,20 +204,20 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
case 4:
|
||||
packetLength = 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
|
||||
case 5:
|
||||
nonceLen := config.AEAD().Mode().NonceLength()
|
||||
ivLen := config.AEAD().Mode().IvLength()
|
||||
tagLen := config.AEAD().Mode().TagLength()
|
||||
packetLength = 3 + len(s2kBytes) + nonceLen + keySize + tagLen
|
||||
packetLength = 3 + len(s2kBytes) + ivLen + keySize + tagLen
|
||||
}
|
||||
err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf := make([]byte, 2)
|
||||
// Symmetric Key Encrypted Version
|
||||
buf[0] = byte(version)
|
||||
buf := []byte{byte(version)}
|
||||
|
||||
// Cipher function
|
||||
buf[1] = byte(cipherFunc)
|
||||
buf = append(buf, byte(cipherFunc))
|
||||
|
||||
if version == 5 {
|
||||
// AEAD mode
|
||||
@@ -241,19 +244,20 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
return
|
||||
}
|
||||
case 5:
|
||||
blockCipher := cipherFunc.new(keyEncryptingKey)
|
||||
mode := config.AEAD().Mode()
|
||||
aead := mode.new(blockCipher)
|
||||
// Sample nonce using random reader
|
||||
nonce := make([]byte, config.AEAD().Mode().NonceLength())
|
||||
_, err = io.ReadFull(config.Random(), nonce)
|
||||
adata := []byte{0xc3, byte(5), byte(cipherFunc), byte(mode)}
|
||||
aead := getEncryptedKeyAeadInstance(cipherFunc, mode, keyEncryptingKey, adata)
|
||||
|
||||
// Sample iv using random reader
|
||||
iv := make([]byte, config.AEAD().Mode().IvLength())
|
||||
_, err = io.ReadFull(config.Random(), iv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Seal and write (encryptedData includes auth. tag)
|
||||
adata := []byte{0xc3, byte(5), byte(cipherFunc), byte(mode)}
|
||||
encryptedData := aead.Seal(nil, nonce, sessionKey, adata)
|
||||
_, err = w.Write(nonce)
|
||||
|
||||
encryptedData := aead.Seal(nil, iv, sessionKey, adata)
|
||||
_, err = w.Write(iv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -265,3 +269,8 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte) (aead cipher.AEAD) {
|
||||
blockCipher := c.new(inputKey)
|
||||
return mode.new(blockCipher)
|
||||
}
|
||||
|
||||
274
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
generated
vendored
274
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
generated
vendored
@@ -5,36 +5,54 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/sha1"
|
||||
"crypto/subtle"
|
||||
"hash"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
const aeadSaltSize = 32
|
||||
|
||||
// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
|
||||
// encrypted Contents will consist of more OpenPGP packets. See RFC 4880,
|
||||
// sections 5.7 and 5.13.
|
||||
type SymmetricallyEncrypted struct {
|
||||
MDC bool // true iff this is a type 18 packet and thus has an embedded MAC.
|
||||
Contents io.Reader
|
||||
prefix []byte
|
||||
Version int
|
||||
Contents io.Reader // contains tag for version 2
|
||||
IntegrityProtected bool // If true it is type 18 (with MDC or AEAD). False is packet type 9
|
||||
|
||||
// Specific to version 1
|
||||
prefix []byte
|
||||
|
||||
// Specific to version 2
|
||||
Cipher CipherFunction
|
||||
Mode AEADMode
|
||||
ChunkSizeByte byte
|
||||
Salt [aeadSaltSize]byte
|
||||
}
|
||||
|
||||
const symmetricallyEncryptedVersion = 1
|
||||
const (
|
||||
symmetricallyEncryptedVersionMdc = 1
|
||||
symmetricallyEncryptedVersionAead = 2
|
||||
)
|
||||
|
||||
func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
|
||||
if se.MDC {
|
||||
if se.IntegrityProtected {
|
||||
// See RFC 4880, section 5.13.
|
||||
var buf [1]byte
|
||||
_, err := readFull(r, buf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if buf[0] != symmetricallyEncryptedVersion {
|
||||
|
||||
switch buf[0] {
|
||||
case symmetricallyEncryptedVersionMdc:
|
||||
se.Version = symmetricallyEncryptedVersionMdc
|
||||
case symmetricallyEncryptedVersionAead:
|
||||
se.Version = symmetricallyEncryptedVersionAead
|
||||
if err := se.parseAead(r); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
|
||||
}
|
||||
}
|
||||
@@ -46,245 +64,27 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
|
||||
// packet can be read. An incorrect key will only be detected after trying
|
||||
// to decrypt the entire data.
|
||||
func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
|
||||
keySize := c.KeySize()
|
||||
if keySize == 0 {
|
||||
return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
|
||||
}
|
||||
if len(key) != keySize {
|
||||
return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
|
||||
if se.Version == symmetricallyEncryptedVersionAead {
|
||||
return se.decryptAead(key)
|
||||
}
|
||||
|
||||
if se.prefix == nil {
|
||||
se.prefix = make([]byte, c.blockSize()+2)
|
||||
_, err := readFull(se.Contents, se.prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if len(se.prefix) != c.blockSize()+2 {
|
||||
return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
|
||||
}
|
||||
|
||||
ocfbResync := OCFBResync
|
||||
if se.MDC {
|
||||
// MDC packets use a different form of OCFB mode.
|
||||
ocfbResync = OCFBNoResync
|
||||
}
|
||||
|
||||
s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
|
||||
|
||||
plaintext := cipher.StreamReader{S: s, R: se.Contents}
|
||||
|
||||
if se.MDC {
|
||||
// MDC packets have an embedded hash that we need to check.
|
||||
h := sha1.New()
|
||||
h.Write(se.prefix)
|
||||
return &seMDCReader{in: plaintext, h: h}, nil
|
||||
}
|
||||
|
||||
// Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
|
||||
return seReader{plaintext}, nil
|
||||
}
|
||||
|
||||
// seReader wraps an io.Reader with a no-op Close method.
|
||||
type seReader struct {
|
||||
in io.Reader
|
||||
}
|
||||
|
||||
func (ser seReader) Read(buf []byte) (int, error) {
|
||||
return ser.in.Read(buf)
|
||||
}
|
||||
|
||||
func (ser seReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
|
||||
|
||||
// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
|
||||
// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
|
||||
// MDC packet containing a hash of the previous Contents which is checked
|
||||
// against the running hash. See RFC 4880, section 5.13.
|
||||
type seMDCReader struct {
|
||||
in io.Reader
|
||||
h hash.Hash
|
||||
trailer [mdcTrailerSize]byte
|
||||
scratch [mdcTrailerSize]byte
|
||||
trailerUsed int
|
||||
error bool
|
||||
eof bool
|
||||
}
|
||||
|
||||
func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
|
||||
if ser.error {
|
||||
err = io.ErrUnexpectedEOF
|
||||
return
|
||||
}
|
||||
if ser.eof {
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
|
||||
// If we haven't yet filled the trailer buffer then we must do that
|
||||
// first.
|
||||
for ser.trailerUsed < mdcTrailerSize {
|
||||
n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
|
||||
ser.trailerUsed += n
|
||||
if err == io.EOF {
|
||||
if ser.trailerUsed != mdcTrailerSize {
|
||||
n = 0
|
||||
err = io.ErrUnexpectedEOF
|
||||
ser.error = true
|
||||
return
|
||||
}
|
||||
ser.eof = true
|
||||
n = 0
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
n = 0
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a short read then we read into a temporary buffer and shift
|
||||
// the data into the caller's buffer.
|
||||
if len(buf) <= mdcTrailerSize {
|
||||
n, err = readFull(ser.in, ser.scratch[:len(buf)])
|
||||
copy(buf, ser.trailer[:n])
|
||||
ser.h.Write(buf[:n])
|
||||
copy(ser.trailer[:], ser.trailer[n:])
|
||||
copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
|
||||
if n < len(buf) {
|
||||
ser.eof = true
|
||||
err = io.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
n, err = ser.in.Read(buf[mdcTrailerSize:])
|
||||
copy(buf, ser.trailer[:])
|
||||
ser.h.Write(buf[:n])
|
||||
copy(ser.trailer[:], buf[n:])
|
||||
|
||||
if err == io.EOF {
|
||||
ser.eof = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// This is a new-format packet tag byte for a type 19 (MDC) packet.
|
||||
const mdcPacketTagByte = byte(0x80) | 0x40 | 19
|
||||
|
||||
func (ser *seMDCReader) Close() error {
|
||||
if ser.error {
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
|
||||
for !ser.eof {
|
||||
// We haven't seen EOF so we need to read to the end
|
||||
var buf [1024]byte
|
||||
_, err := ser.Read(buf[:])
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
}
|
||||
|
||||
ser.h.Write(ser.trailer[:2])
|
||||
|
||||
final := ser.h.Sum(nil)
|
||||
if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
|
||||
return errors.ErrMDCHashMismatch
|
||||
}
|
||||
// The hash already includes the MDC header, but we still check its value
|
||||
// to confirm encryption correctness
|
||||
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// An seMDCWriter writes through to an io.WriteCloser while maintains a running
|
||||
// hash of the data written. On close, it emits an MDC packet containing the
|
||||
// running hash.
|
||||
type seMDCWriter struct {
|
||||
w io.WriteCloser
|
||||
h hash.Hash
|
||||
}
|
||||
|
||||
func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
|
||||
w.h.Write(buf)
|
||||
return w.w.Write(buf)
|
||||
}
|
||||
|
||||
func (w *seMDCWriter) Close() (err error) {
|
||||
var buf [mdcTrailerSize]byte
|
||||
|
||||
buf[0] = mdcPacketTagByte
|
||||
buf[1] = sha1.Size
|
||||
w.h.Write(buf[:2])
|
||||
digest := w.h.Sum(nil)
|
||||
copy(buf[2:], digest)
|
||||
|
||||
_, err = w.w.Write(buf[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return w.w.Close()
|
||||
}
|
||||
|
||||
// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
|
||||
type noOpCloser struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (c noOpCloser) Write(data []byte) (n int, err error) {
|
||||
return c.w.Write(data)
|
||||
}
|
||||
|
||||
func (c noOpCloser) Close() error {
|
||||
return nil
|
||||
return se.decryptMdc(c, key)
|
||||
}
|
||||
|
||||
// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
|
||||
// to w and returns a WriteCloser to which the to-be-encrypted packets can be
|
||||
// written.
|
||||
// If config is nil, sensible defaults will be used.
|
||||
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (Contents io.WriteCloser, err error) {
|
||||
if c.KeySize() != len(key) {
|
||||
return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
|
||||
}
|
||||
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, aeadSupported bool, cipherSuite CipherSuite, key []byte, config *Config) (Contents io.WriteCloser, err error) {
|
||||
writeCloser := noOpCloser{w}
|
||||
ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
|
||||
ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedIntegrityProtected)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
|
||||
if err != nil {
|
||||
return
|
||||
if aeadSupported {
|
||||
return serializeSymmetricallyEncryptedAead(ciphertext, cipherSuite, config.AEADConfig.ChunkSizeByte(), config.Random(), key)
|
||||
}
|
||||
|
||||
block := c.new(key)
|
||||
blockSize := block.BlockSize()
|
||||
iv := make([]byte, blockSize)
|
||||
_, err = config.Random().Read(iv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
|
||||
_, err = ciphertext.Write(prefix)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plaintext := cipher.StreamWriter{S: s, W: ciphertext}
|
||||
|
||||
h := sha1.New()
|
||||
h.Write(iv)
|
||||
h.Write(iv[blockSize-2:])
|
||||
Contents = &seMDCWriter{w: plaintext, h: h}
|
||||
return
|
||||
return serializeSymmetricallyEncryptedMdc(ciphertext, c, key, config)
|
||||
}
|
||||
|
||||
156
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
generated
vendored
Normal file
156
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright 2023 Proton AG. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package packet
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
// parseAead parses a V2 SEIPD packet (AEAD) as specified in
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
|
||||
func (se *SymmetricallyEncrypted) parseAead(r io.Reader) error {
|
||||
headerData := make([]byte, 3)
|
||||
if n, err := io.ReadFull(r, headerData); n < 3 {
|
||||
return errors.StructuralError("could not read aead header: " + err.Error())
|
||||
}
|
||||
|
||||
// Cipher
|
||||
se.Cipher = CipherFunction(headerData[0])
|
||||
// cipherFunc must have block size 16 to use AEAD
|
||||
if se.Cipher.blockSize() != 16 {
|
||||
return errors.UnsupportedError("invalid aead cipher: " + string(se.Cipher))
|
||||
}
|
||||
|
||||
// Mode
|
||||
se.Mode = AEADMode(headerData[1])
|
||||
if se.Mode.TagLength() == 0 {
|
||||
return errors.UnsupportedError("unknown aead mode: " + string(se.Mode))
|
||||
}
|
||||
|
||||
// Chunk size
|
||||
se.ChunkSizeByte = headerData[2]
|
||||
if se.ChunkSizeByte > 16 {
|
||||
return errors.UnsupportedError("invalid aead chunk size byte: " + string(se.ChunkSizeByte))
|
||||
}
|
||||
|
||||
// Salt
|
||||
if n, err := io.ReadFull(r, se.Salt[:]); n < aeadSaltSize {
|
||||
return errors.StructuralError("could not read aead salt: " + err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// associatedData for chunks: tag, version, cipher, mode, chunk size byte
|
||||
func (se *SymmetricallyEncrypted) associatedData() []byte {
|
||||
return []byte{
|
||||
0xD2,
|
||||
symmetricallyEncryptedVersionAead,
|
||||
byte(se.Cipher),
|
||||
byte(se.Mode),
|
||||
se.ChunkSizeByte,
|
||||
}
|
||||
}
|
||||
|
||||
// decryptAead decrypts a V2 SEIPD packet (AEAD) as specified in
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
|
||||
func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, error) {
|
||||
aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData())
|
||||
|
||||
// Carry the first tagLen bytes
|
||||
tagLen := se.Mode.TagLength()
|
||||
peekedBytes := make([]byte, tagLen)
|
||||
n, err := io.ReadFull(se.Contents, peekedBytes)
|
||||
if n < tagLen || (err != nil && err != io.EOF) {
|
||||
return nil, errors.StructuralError("not enough data to decrypt:" + err.Error())
|
||||
}
|
||||
|
||||
return &aeadDecrypter{
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: aead,
|
||||
chunkSize: decodeAEADChunkSize(se.ChunkSizeByte),
|
||||
initialNonce: nonce,
|
||||
associatedData: se.associatedData(),
|
||||
chunkIndex: make([]byte, 8),
|
||||
packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected,
|
||||
},
|
||||
reader: se.Contents,
|
||||
peekedBytes: peekedBytes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// serializeSymmetricallyEncryptedAead encrypts to a writer a V2 SEIPD packet (AEAD) as specified in
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
|
||||
func serializeSymmetricallyEncryptedAead(ciphertext io.WriteCloser, cipherSuite CipherSuite, chunkSizeByte byte, rand io.Reader, inputKey []byte) (Contents io.WriteCloser, err error) {
|
||||
// cipherFunc must have block size 16 to use AEAD
|
||||
if cipherSuite.Cipher.blockSize() != 16 {
|
||||
return nil, errors.InvalidArgumentError("invalid aead cipher function")
|
||||
}
|
||||
|
||||
if cipherSuite.Cipher.KeySize() != len(inputKey) {
|
||||
return nil, errors.InvalidArgumentError("error in aead serialization: bad key length")
|
||||
}
|
||||
|
||||
// Data for en/decryption: tag, version, cipher, aead mode, chunk size
|
||||
prefix := []byte{
|
||||
0xD2,
|
||||
symmetricallyEncryptedVersionAead,
|
||||
byte(cipherSuite.Cipher),
|
||||
byte(cipherSuite.Mode),
|
||||
chunkSizeByte,
|
||||
}
|
||||
|
||||
// Write header (that correspond to prefix except first byte)
|
||||
n, err := ciphertext.Write(prefix[1:])
|
||||
if err != nil || n < 4 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Random salt
|
||||
salt := make([]byte, aeadSaltSize)
|
||||
if _, err := rand.Read(salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := ciphertext.Write(salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aead, nonce := getSymmetricallyEncryptedAeadInstance(cipherSuite.Cipher, cipherSuite.Mode, inputKey, salt, prefix)
|
||||
|
||||
return &aeadEncrypter{
|
||||
aeadCrypter: aeadCrypter{
|
||||
aead: aead,
|
||||
chunkSize: decodeAEADChunkSize(chunkSizeByte),
|
||||
associatedData: prefix,
|
||||
chunkIndex: make([]byte, 8),
|
||||
initialNonce: nonce,
|
||||
packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected,
|
||||
},
|
||||
writer: ciphertext,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getSymmetricallyEncryptedAeadInstance(c CipherFunction, mode AEADMode, inputKey, salt, associatedData []byte) (aead cipher.AEAD, nonce []byte) {
|
||||
hkdfReader := hkdf.New(sha256.New, inputKey, salt, associatedData)
|
||||
|
||||
encryptionKey := make([]byte, c.KeySize())
|
||||
_, _ = readFull(hkdfReader, encryptionKey)
|
||||
|
||||
// Last 64 bits of nonce are the counter
|
||||
nonce = make([]byte, mode.IvLength()-8)
|
||||
|
||||
_, _ = readFull(hkdfReader, nonce)
|
||||
|
||||
blockCipher := c.new(encryptionKey)
|
||||
aead = mode.new(blockCipher)
|
||||
|
||||
return
|
||||
}
|
||||
256
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
generated
vendored
Normal file
256
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
// Copyright 2011 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 packet
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/sha1"
|
||||
"crypto/subtle"
|
||||
"hash"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// seMdcReader wraps an io.Reader with a no-op Close method.
|
||||
type seMdcReader struct {
|
||||
in io.Reader
|
||||
}
|
||||
|
||||
func (ser seMdcReader) Read(buf []byte) (int, error) {
|
||||
return ser.in.Read(buf)
|
||||
}
|
||||
|
||||
func (ser seMdcReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (se *SymmetricallyEncrypted) decryptMdc(c CipherFunction, key []byte) (io.ReadCloser, error) {
|
||||
if !c.IsSupported() {
|
||||
return nil, errors.UnsupportedError("unsupported cipher: " + strconv.Itoa(int(c)))
|
||||
}
|
||||
|
||||
if len(key) != c.KeySize() {
|
||||
return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
|
||||
}
|
||||
|
||||
if se.prefix == nil {
|
||||
se.prefix = make([]byte, c.blockSize()+2)
|
||||
_, err := readFull(se.Contents, se.prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if len(se.prefix) != c.blockSize()+2 {
|
||||
return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
|
||||
}
|
||||
|
||||
ocfbResync := OCFBResync
|
||||
if se.IntegrityProtected {
|
||||
// MDC packets use a different form of OCFB mode.
|
||||
ocfbResync = OCFBNoResync
|
||||
}
|
||||
|
||||
s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
|
||||
|
||||
plaintext := cipher.StreamReader{S: s, R: se.Contents}
|
||||
|
||||
if se.IntegrityProtected {
|
||||
// IntegrityProtected packets have an embedded hash that we need to check.
|
||||
h := sha1.New()
|
||||
h.Write(se.prefix)
|
||||
return &seMDCReader{in: plaintext, h: h}, nil
|
||||
}
|
||||
|
||||
// Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
|
||||
return seMdcReader{plaintext}, nil
|
||||
}
|
||||
|
||||
const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
|
||||
|
||||
// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
|
||||
// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
|
||||
// MDC packet containing a hash of the previous Contents which is checked
|
||||
// against the running hash. See RFC 4880, section 5.13.
|
||||
type seMDCReader struct {
|
||||
in io.Reader
|
||||
h hash.Hash
|
||||
trailer [mdcTrailerSize]byte
|
||||
scratch [mdcTrailerSize]byte
|
||||
trailerUsed int
|
||||
error bool
|
||||
eof bool
|
||||
}
|
||||
|
||||
func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
|
||||
if ser.error {
|
||||
err = io.ErrUnexpectedEOF
|
||||
return
|
||||
}
|
||||
if ser.eof {
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
|
||||
// If we haven't yet filled the trailer buffer then we must do that
|
||||
// first.
|
||||
for ser.trailerUsed < mdcTrailerSize {
|
||||
n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
|
||||
ser.trailerUsed += n
|
||||
if err == io.EOF {
|
||||
if ser.trailerUsed != mdcTrailerSize {
|
||||
n = 0
|
||||
err = io.ErrUnexpectedEOF
|
||||
ser.error = true
|
||||
return
|
||||
}
|
||||
ser.eof = true
|
||||
n = 0
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
n = 0
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a short read then we read into a temporary buffer and shift
|
||||
// the data into the caller's buffer.
|
||||
if len(buf) <= mdcTrailerSize {
|
||||
n, err = readFull(ser.in, ser.scratch[:len(buf)])
|
||||
copy(buf, ser.trailer[:n])
|
||||
ser.h.Write(buf[:n])
|
||||
copy(ser.trailer[:], ser.trailer[n:])
|
||||
copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
|
||||
if n < len(buf) {
|
||||
ser.eof = true
|
||||
err = io.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
n, err = ser.in.Read(buf[mdcTrailerSize:])
|
||||
copy(buf, ser.trailer[:])
|
||||
ser.h.Write(buf[:n])
|
||||
copy(ser.trailer[:], buf[n:])
|
||||
|
||||
if err == io.EOF {
|
||||
ser.eof = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// This is a new-format packet tag byte for a type 19 (Integrity Protected) packet.
|
||||
const mdcPacketTagByte = byte(0x80) | 0x40 | 19
|
||||
|
||||
func (ser *seMDCReader) Close() error {
|
||||
if ser.error {
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
|
||||
for !ser.eof {
|
||||
// We haven't seen EOF so we need to read to the end
|
||||
var buf [1024]byte
|
||||
_, err := ser.Read(buf[:])
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
}
|
||||
|
||||
ser.h.Write(ser.trailer[:2])
|
||||
|
||||
final := ser.h.Sum(nil)
|
||||
if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
|
||||
return errors.ErrMDCHashMismatch
|
||||
}
|
||||
// The hash already includes the MDC header, but we still check its value
|
||||
// to confirm encryption correctness
|
||||
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
|
||||
return errors.ErrMDCMissing
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// An seMDCWriter writes through to an io.WriteCloser while maintains a running
|
||||
// hash of the data written. On close, it emits an MDC packet containing the
|
||||
// running hash.
|
||||
type seMDCWriter struct {
|
||||
w io.WriteCloser
|
||||
h hash.Hash
|
||||
}
|
||||
|
||||
func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
|
||||
w.h.Write(buf)
|
||||
return w.w.Write(buf)
|
||||
}
|
||||
|
||||
func (w *seMDCWriter) Close() (err error) {
|
||||
var buf [mdcTrailerSize]byte
|
||||
|
||||
buf[0] = mdcPacketTagByte
|
||||
buf[1] = sha1.Size
|
||||
w.h.Write(buf[:2])
|
||||
digest := w.h.Sum(nil)
|
||||
copy(buf[2:], digest)
|
||||
|
||||
_, err = w.w.Write(buf[:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return w.w.Close()
|
||||
}
|
||||
|
||||
// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
|
||||
type noOpCloser struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (c noOpCloser) Write(data []byte) (n int, err error) {
|
||||
return c.w.Write(data)
|
||||
}
|
||||
|
||||
func (c noOpCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func serializeSymmetricallyEncryptedMdc(ciphertext io.WriteCloser, c CipherFunction, key []byte, config *Config) (Contents io.WriteCloser, err error) {
|
||||
// Disallow old cipher suites
|
||||
if !c.IsSupported() || c < CipherAES128 {
|
||||
return nil, errors.InvalidArgumentError("invalid mdc cipher function")
|
||||
}
|
||||
|
||||
if c.KeySize() != len(key) {
|
||||
return nil, errors.InvalidArgumentError("error in mdc serialization: bad key length")
|
||||
}
|
||||
|
||||
_, err = ciphertext.Write([]byte{symmetricallyEncryptedVersionMdc})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
block := c.new(key)
|
||||
blockSize := block.BlockSize()
|
||||
iv := make([]byte, blockSize)
|
||||
_, err = config.Random().Read(iv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
|
||||
_, err = ciphertext.Write(prefix)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
plaintext := cipher.StreamWriter{S: s, W: ciphertext}
|
||||
|
||||
h := sha1.New()
|
||||
h.Write(iv)
|
||||
h.Write(iv[blockSize-2:])
|
||||
Contents = &seMDCWriter{w: plaintext, h: h}
|
||||
return
|
||||
}
|
||||
11
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
generated
vendored
11
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
generated
vendored
@@ -42,9 +42,16 @@ func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error
|
||||
if err = jpeg.Encode(&buf, photo, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
lengthBuf := make([]byte, 5)
|
||||
n := serializeSubpacketLength(lengthBuf, len(buf.Bytes())+1)
|
||||
lengthBuf = lengthBuf[:n]
|
||||
|
||||
uat.Contents = append(uat.Contents, &OpaqueSubpacket{
|
||||
SubType: UserAttrImageSubpacket,
|
||||
Contents: buf.Bytes()})
|
||||
SubType: UserAttrImageSubpacket,
|
||||
EncodedLength: lengthBuf,
|
||||
Contents: buf.Bytes(),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
182
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
182
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
@@ -8,13 +8,16 @@ package openpgp // import "github.com/ProtonMail/go-crypto/openpgp"
|
||||
import (
|
||||
"crypto"
|
||||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"hash"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
_ "golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// SignatureType is the armor type for a PGP signature.
|
||||
@@ -119,17 +122,25 @@ ParsePackets:
|
||||
default:
|
||||
continue
|
||||
}
|
||||
var keys []Key
|
||||
if p.KeyId == 0 {
|
||||
keys = keyring.DecryptionKeys()
|
||||
} else {
|
||||
keys = keyring.KeysById(p.KeyId)
|
||||
if keyring != nil {
|
||||
var keys []Key
|
||||
if p.KeyId == 0 {
|
||||
keys = keyring.DecryptionKeys()
|
||||
} else {
|
||||
keys = keyring.KeysById(p.KeyId)
|
||||
}
|
||||
for _, k := range keys {
|
||||
pubKeys = append(pubKeys, keyEnvelopePair{k, p})
|
||||
}
|
||||
}
|
||||
for _, k := range keys {
|
||||
pubKeys = append(pubKeys, keyEnvelopePair{k, p})
|
||||
case *packet.SymmetricallyEncrypted:
|
||||
if !p.IntegrityProtected && !config.AllowUnauthenticatedMessages() {
|
||||
return nil, errors.UnsupportedError("message is not integrity protected")
|
||||
}
|
||||
case *packet.SymmetricallyEncrypted, *packet.AEADEncrypted:
|
||||
edp = p.(packet.EncryptedDataPacket)
|
||||
edp = p
|
||||
break ParsePackets
|
||||
case *packet.AEADEncrypted:
|
||||
edp = p
|
||||
break ParsePackets
|
||||
case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
|
||||
// This message isn't encrypted.
|
||||
@@ -200,13 +211,11 @@ FindKey:
|
||||
if len(symKeys) != 0 && passphrase != nil {
|
||||
for _, s := range symKeys {
|
||||
key, cipherFunc, err := s.Decrypt(passphrase)
|
||||
// On wrong passphrase, session key decryption is very likely to result in an invalid cipherFunc:
|
||||
// In v4, on wrong passphrase, session key decryption is very likely to result in an invalid cipherFunc:
|
||||
// only for < 5% of cases we will proceed to decrypt the data
|
||||
if err == nil {
|
||||
decrypted, err = edp.Decrypt(cipherFunc, key)
|
||||
// TODO: ErrKeyIncorrect is no longer thrown on SEIP decryption,
|
||||
// but it might still be relevant for when we implement AEAD decryption (otherwise, remove?)
|
||||
if err != nil && err != errors.ErrKeyIncorrect {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if decrypted != nil {
|
||||
@@ -268,9 +277,11 @@ FindLiteralData:
|
||||
|
||||
md.IsSigned = true
|
||||
md.SignedByKeyId = p.KeyId
|
||||
keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
|
||||
if len(keys) > 0 {
|
||||
md.SignedBy = &keys[0]
|
||||
if keyring != nil {
|
||||
keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
|
||||
if len(keys) > 0 {
|
||||
md.SignedBy = &keys[0]
|
||||
}
|
||||
}
|
||||
case *packet.LiteralData:
|
||||
md.LiteralData = p
|
||||
@@ -294,14 +305,14 @@ FindLiteralData:
|
||||
// should be preprocessed (i.e. to normalize line endings). Thus this function
|
||||
// returns two hashes. The second should be used to hash the message itself and
|
||||
// performs any needed preprocessing.
|
||||
func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
|
||||
if hashId == crypto.MD5 {
|
||||
return nil, nil, errors.UnsupportedError("insecure hash algorithm: MD5")
|
||||
func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
|
||||
if _, ok := algorithm.HashToHashIdWithSha1(hashFunc); !ok {
|
||||
return nil, nil, errors.UnsupportedError("unsupported hash function")
|
||||
}
|
||||
if !hashId.Available() {
|
||||
return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
|
||||
if !hashFunc.Available() {
|
||||
return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashFunc)))
|
||||
}
|
||||
h := hashId.New()
|
||||
h := hashFunc.New()
|
||||
|
||||
switch sigType {
|
||||
case packet.SigTypeBinary:
|
||||
@@ -373,19 +384,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
key := scr.md.SignedBy
|
||||
signatureError := key.PublicKey.VerifySignature(scr.h, sig)
|
||||
if signatureError == nil {
|
||||
now := scr.config.Now()
|
||||
if key.Revoked(now) ||
|
||||
key.Entity.Revoked(now) || // primary key is revoked (redundant if key is the primary key)
|
||||
key.Entity.PrimaryIdentity().Revoked(now) {
|
||||
signatureError = errors.ErrKeyRevoked
|
||||
}
|
||||
if sig.SigExpired(now) {
|
||||
signatureError = errors.ErrSignatureExpired
|
||||
}
|
||||
if key.PublicKey.KeyExpired(key.SelfSignature, now) ||
|
||||
key.SelfSignature.SigExpired(now) {
|
||||
signatureError = errors.ErrKeyExpired
|
||||
}
|
||||
signatureError = checkSignatureDetails(key, sig, scr.config)
|
||||
}
|
||||
scr.md.Signature = sig
|
||||
scr.md.SignatureError = signatureError
|
||||
@@ -424,8 +423,24 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// VerifyDetachedSignature takes a signed file and a detached signature and
|
||||
// returns the signature packet and the entity the signature was signed by,
|
||||
// if any, and a possible signature verification error.
|
||||
// If the signer isn't known, ErrUnknownIssuer is returned.
|
||||
func VerifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
var expectedHashes []crypto.Hash
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
}
|
||||
|
||||
// VerifyDetachedSignatureAndHash performs the same actions as
|
||||
// VerifyDetachedSignature and checks that the expected hash functions were used.
|
||||
func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
}
|
||||
|
||||
// CheckDetachedSignature takes a signed file and a detached signature and
|
||||
// returns the signer if the signature is valid. If the signer isn't known,
|
||||
// returns the entity the signature was signed by, if any, and a possible
|
||||
// signature verification error. If the signer isn't known,
|
||||
// ErrUnknownIssuer is returned.
|
||||
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
|
||||
var expectedHashes []crypto.Hash
|
||||
@@ -435,6 +450,11 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config
|
||||
// CheckDetachedSignatureAndHash performs the same actions as
|
||||
// CheckDetachedSignature and checks that the expected hash functions were used.
|
||||
func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) {
|
||||
_, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
return
|
||||
}
|
||||
|
||||
func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
var issuerKeyId uint64
|
||||
var hashFunc crypto.Hash
|
||||
var sigType packet.SignatureType
|
||||
@@ -443,23 +463,22 @@ func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader,
|
||||
|
||||
expectedHashesLen := len(expectedHashes)
|
||||
packets := packet.NewReader(signature)
|
||||
var sig *packet.Signature
|
||||
for {
|
||||
p, err = packets.Next()
|
||||
if err == io.EOF {
|
||||
return nil, errors.ErrUnknownIssuer
|
||||
return nil, nil, errors.ErrUnknownIssuer
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
sig, ok = p.(*packet.Signature)
|
||||
if !ok {
|
||||
return nil, errors.StructuralError("non signature packet found")
|
||||
return nil, nil, errors.StructuralError("non signature packet found")
|
||||
}
|
||||
if sig.IssuerKeyId == nil {
|
||||
return nil, errors.StructuralError("signature doesn't have an issuer")
|
||||
return nil, nil, errors.StructuralError("signature doesn't have an issuer")
|
||||
}
|
||||
issuerKeyId = *sig.IssuerKeyId
|
||||
hashFunc = sig.Hash
|
||||
@@ -470,7 +489,7 @@ func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader,
|
||||
break
|
||||
}
|
||||
if i+1 == expectedHashesLen {
|
||||
return nil, errors.StructuralError("hash algorithm mismatch with cleartext message headers")
|
||||
return nil, nil, errors.StructuralError("hash algorithm mismatch with cleartext message headers")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,34 +505,21 @@ func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader,
|
||||
|
||||
h, wrappedHash, err := hashForSignature(hashFunc, sigType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
err = key.PublicKey.VerifySignature(h, sig)
|
||||
if err == nil {
|
||||
now := config.Now()
|
||||
if key.Revoked(now) ||
|
||||
key.Entity.Revoked(now) || // primary key is revoked (redundant if key is the primary key)
|
||||
key.Entity.PrimaryIdentity().Revoked(now) {
|
||||
return key.Entity, errors.ErrKeyRevoked
|
||||
}
|
||||
if sig.SigExpired(now) {
|
||||
return key.Entity, errors.ErrSignatureExpired
|
||||
}
|
||||
if key.PublicKey.KeyExpired(key.SelfSignature, now) ||
|
||||
key.SelfSignature.SigExpired(now) {
|
||||
return key.Entity, errors.ErrKeyExpired
|
||||
}
|
||||
return key.Entity, nil
|
||||
return sig, key.Entity, checkSignatureDetails(&key, sig, config)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// CheckArmoredDetachedSignature performs the same actions as
|
||||
@@ -526,3 +532,61 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader,
|
||||
|
||||
return CheckDetachedSignature(keyring, signed, body, config)
|
||||
}
|
||||
|
||||
// checkSignatureDetails returns an error if:
|
||||
// - The signature (or one of the binding signatures mentioned below)
|
||||
// has a unknown critical notation data subpacket
|
||||
// - The primary key of the signing entity is revoked
|
||||
// - The primary identity is revoked
|
||||
// - The signature is expired
|
||||
// - The primary key of the signing entity is expired according to the
|
||||
// primary identity binding signature
|
||||
//
|
||||
// ... or, if the signature was signed by a subkey and:
|
||||
// - The signing subkey is revoked
|
||||
// - The signing subkey is expired according to the subkey binding signature
|
||||
// - The signing subkey binding signature is expired
|
||||
// - The signing subkey cross-signature is expired
|
||||
//
|
||||
// NOTE: The order of these checks is important, as the caller may choose to
|
||||
// ignore ErrSignatureExpired or ErrKeyExpired errors, but should never
|
||||
// ignore any other errors.
|
||||
//
|
||||
// TODO: Also return an error if:
|
||||
// - The primary key is expired according to a direct-key signature
|
||||
// - (For V5 keys only:) The direct-key signature (exists and) is expired
|
||||
func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
|
||||
now := config.Now()
|
||||
primaryIdentity := key.Entity.PrimaryIdentity()
|
||||
signedBySubKey := key.PublicKey != key.Entity.PrimaryKey
|
||||
sigsToCheck := []*packet.Signature{signature, primaryIdentity.SelfSignature}
|
||||
if signedBySubKey {
|
||||
sigsToCheck = append(sigsToCheck, key.SelfSignature, key.SelfSignature.EmbeddedSignature)
|
||||
}
|
||||
for _, sig := range sigsToCheck {
|
||||
for _, notation := range sig.Notations {
|
||||
if notation.IsCritical && !config.KnownNotation(notation.Name) {
|
||||
return errors.SignatureError("unknown critical notation: " + notation.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if key.Entity.Revoked(now) || // primary key is revoked
|
||||
(signedBySubKey && key.Revoked(now)) || // subkey is revoked
|
||||
primaryIdentity.Revoked(now) { // primary identity is revoked
|
||||
return errors.ErrKeyRevoked
|
||||
}
|
||||
if key.Entity.PrimaryKey.KeyExpired(primaryIdentity.SelfSignature, now) { // primary key is expired
|
||||
return errors.ErrKeyExpired
|
||||
}
|
||||
if signedBySubKey {
|
||||
if key.PublicKey.KeyExpired(key.SelfSignature, now) { // subkey is expired
|
||||
return errors.ErrKeyExpired
|
||||
}
|
||||
}
|
||||
for _, sig := range sigsToCheck {
|
||||
if sig.SigExpired(now) { // any of the relevant signatures are expired
|
||||
return errors.ErrSignatureExpired
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
111
vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
generated
vendored
111
vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
generated
vendored
@@ -1,8 +1,8 @@
|
||||
package openpgp
|
||||
|
||||
const testKey1KeyId = 0xA34D7E18C20C31BB
|
||||
const testKey3KeyId = 0x338934250CCC0360
|
||||
const testKeyP256KeyId = 0xd44a2c495918513e
|
||||
const testKey1KeyId uint64 = 0xA34D7E18C20C31BB
|
||||
const testKey3KeyId uint64 = 0x338934250CCC0360
|
||||
const testKeyP256KeyId uint64 = 0xd44a2c495918513e
|
||||
|
||||
const signedInput = "Signed message\nline 2\nline 3\n"
|
||||
const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
|
||||
@@ -102,11 +102,11 @@ ex7En5r7rHR5xwX82Msc+Rq9dSyO
|
||||
|
||||
const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
|
||||
|
||||
const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
|
||||
const rsaSignatureBadMPIlength = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
|
||||
const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
|
||||
|
||||
const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000`
|
||||
|
||||
@@ -171,3 +171,104 @@ y29VPonFXqi2zKkpZrvyvZxg+n5e8Nt9wNbuxeCd3QD/TtO2s+JvjrE4Siwv
|
||||
UQdl5MlBka1QSNbMq2Bz7XwNPg4=
|
||||
=6lbM
|
||||
-----END PGP MESSAGE-----`
|
||||
|
||||
const keyWithExpiredCrossSig = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
|
||||
/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz
|
||||
/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/
|
||||
5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3
|
||||
X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv
|
||||
9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0
|
||||
qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb
|
||||
SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb
|
||||
vLIwa3T4CyshfT0AEQEAAc0hQm9iIEJhYmJhZ2UgPGJvYkBvcGVucGdwLmV4YW1w
|
||||
bGU+wsEABBMBCgATBYJeO2eVAgsJAxUICgKbAQIeAQAhCRD7/MgqAV5zMBYhBNGm
|
||||
bhojsYLJmA94jPv8yCoBXnMwKWUMAJ3FKZfJ2mXvh+GFqgymvK4NoKkDRPB0CbUN
|
||||
aDdG7ZOizQrWXo7Da2MYIZ6eZUDqBKLdhZ5gZfVnisDfu/yeCgpENaKib1MPHpA8
|
||||
nZQjnPejbBDomNqY8HRzr5jvXNlwywBpjWGtegCKUY9xbSynjbfzIlMrWL4S+Rfl
|
||||
+bOOQKRyYJWXmECmVyqY8cz2VUYmETjNcwC8VCDUxQnhtcCJ7Aej22hfYwVEPb/J
|
||||
BsJBPq8WECCiGfJ9Y2y6TF+62KzG9Kfs5hqUeHhQy8V4TSi479ewwL7DH86XmIIK
|
||||
chSANBS+7iyMtctjNZfmF9zYdGJFvjI/mbBR/lK66E515Inuf75XnL8hqlXuwqvG
|
||||
ni+i03Aet1DzULZEIio4uIU6ioc1lGO9h7K2Xn4S7QQH1QoISNMWqXibUR0RCGjw
|
||||
FsEDTt2QwJl8XXxoJCooM7BCcCQo+rMNVUHDjIwrdoQjPld3YZsUQQRcqH6bLuln
|
||||
cfn5ufl8zTGWKydoj/iTz8KcjZ7w187AzQRdpZzyAQwA1jC/XGxjK6ddgrRfW9j+
|
||||
s/U00++EvIsgTs2kr3Rg0GP7FLWV0YNtR1mpl55/bEl7yAxCDTkOgPUMXcaKlnQh
|
||||
6zrlt6H53mF6Bvs3inOHQvOsGtU0dqvb1vkTF0juLiJgPlM7pWv+pNQ6IA39vKoQ
|
||||
sTMBv4v5vYNXP9GgKbg8inUNT17BxzZYHfw5+q63ectgDm2on1e8CIRCZ76oBVwz
|
||||
dkVxoy3gjh1eENlk2D4P0uJNZzF1Q8GV67yLANGMCDICE/OkWn6daipYDzW4iJQt
|
||||
YPUWP4hWhjdm+CK+hg6IQUEn2Vtvi16D2blRP8BpUNNa4fNuylWVuJV76rIHvsLZ
|
||||
1pbM3LHpRgE8s6jivS3Rz3WRs0TmWCNnvHPqWizQ3VTy+r3UQVJ5AmhJDrZdZq9i
|
||||
aUIuZ01PoE1+CHiJwuxPtWvVAxf2POcm1M/F1fK1J0e+lKlQuyonTXqXR22Y41wr
|
||||
fP2aPk3nPSTW2DUAf3vRMZg57ZpRxLEhEMxcM4/LMR+PABEBAAHCwrIEGAEKAAkF
|
||||
gl8sAVYCmwIB3QkQ+/zIKgFeczDA+qAEGQEKAAwFgl47Z5UFgwB4TOAAIQkQfC+q
|
||||
Tfk8N7IWIQQd3OFfCSF87i87N2B8L6pN+Tw3st58C/0exp0X2U4LqicSHEOSqHZj
|
||||
jiysdqIELHGyo5DSPv92UFPp36aqjF9OFgtNNwSa56fmAVCD4+hor/fKARRIeIjF
|
||||
qdIC5Y/9a4B10NQFJa5lsvB38x/d39LI2kEoglZnqWgdJskROo3vNQF4KlIcm6FH
|
||||
dn4WI8UkC5oUUcrpZVMSKoacIaxLwqnXT42nIVgYYuqrd/ZagZZjG5WlrTOd5+NI
|
||||
zi/l0fWProcPHGLjmAh4Thu8i7omtVw1nQaMnq9I77ffg3cPDgXknYrLL+q8xXh/
|
||||
0mEJyIhnmPwllWCSZuLv9DrD5pOexFfdlwXhf6cLzNpW6QhXD/Tf5KrqIPr9aOv8
|
||||
9xaEEXWh0vEby2kIsI2++ft+vfdIyxYw/wKqx0awTSnuBV1rG3z1dswX4BfoY66x
|
||||
Bz3KOVqlz9+mG/FTRQwrgPvR+qgLCHbuotxoGN7fzW+PI75hQG5JQAqhsC9sHjQH
|
||||
UrI21/VUNwzfw3v5pYsWuFb5bdQ3ASJetICQiMy7IW8WIQTRpm4aI7GCyZgPeIz7
|
||||
/MgqAV5zMG6/C/wLpPl/9e6Hf5wmXIUwpZNQbNZvpiCcyx9sXsHXaycOQVxn3McZ
|
||||
nYOUP9/mobl1tIeDQyTNbkxWjU0zzJl8XQsDZerb5098pg+x7oGIL7M1vn5s5JMl
|
||||
owROourqF88JEtOBxLMxlAM7X4hB48xKQ3Hu9hS1GdnqLKki4MqRGl4l5FUwyGOM
|
||||
GjyS3TzkfiDJNwQxybQiC9n57ij20ieNyLfuWCMLcNNnZUgZtnF6wCctoq/0ZIWu
|
||||
a7nvuA/XC2WW9YjEJJiWdy5109pqac+qWiY11HWy/nms4gpMdxVpT0RhrKGWq4o0
|
||||
M5q3ZElOoeN70UO3OSbU5EVrG7gB1GuwF9mTHUVlV0veSTw0axkta3FGT//XfSpD
|
||||
lRrCkyLzwq0M+UUHQAuYpAfobDlDdnxxOD2jm5GyTzak3GSVFfjW09QFVO6HlGp5
|
||||
01/jtzkUiS6nwoHHkfnyn0beZuR8X6KlcrzLB0VFgQFLmkSM9cSOgYhD0PTu9aHb
|
||||
hW1Hj9AO8lzggBQ=
|
||||
=Nt+N
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
`
|
||||
|
||||
const sigFromKeyWithExpiredCrossSig = `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
wsDzBAABCgAGBYJfLAFsACEJEHwvqk35PDeyFiEEHdzhXwkhfO4vOzdgfC+qTfk8
|
||||
N7KiqwwAts4QGB7v9bABCC2qkTxJhmStC0wQMcHRcjL/qAiVnmasQWmvE9KVsdm3
|
||||
AaXd8mIx4a37/RRvr9dYrY2eE4uw72cMqPxNja2tvVXkHQvk1oEUqfkvbXs4ypKI
|
||||
NyeTWjXNOTZEbg0hbm3nMy+Wv7zgB1CEvAsEboLDJlhGqPcD+X8a6CJGrBGUBUrv
|
||||
KVmZr3U6vEzClz3DBLpoddCQseJRhT4YM1nKmBlZ5quh2LFgTSpajv5OsZheqt9y
|
||||
EZAPbqmLhDmWRQwGzkWHKceKS7nZ/ox2WK6OS7Ob8ZGZkM64iPo6/EGj5Yc19vQN
|
||||
AGiIaPEGszBBWlOpHTPhNm0LB0nMWqqaT87oNYwP8CQuuxDb6rKJ2lffCmZH27Lb
|
||||
UbQZcH8J+0UhpeaiadPZxH5ATJAcenmVtVVMLVOFnm+eIlxzov9ntpgGYt8hLdXB
|
||||
ITEG9mMgp3TGS9ZzSifMZ8UGtHdp9QdBg8NEVPFzDOMGxpc/Bftav7RRRuPiAER+
|
||||
7A5CBid5
|
||||
=aQkm
|
||||
-----END PGP SIGNATURE-----
|
||||
`
|
||||
|
||||
const signedMessageWithCriticalNotation = `-----BEGIN PGP MESSAGE-----
|
||||
|
||||
owGbwMvMwMH4oOW7S46CznTG09xJDDE3Wl1KUotLuDousDAwcjBYiSmyXL+48d6x
|
||||
U1PSGUxcj8IUszKBVMpMaWAAAgEGZpAeh9SKxNyCnFS95PzcytRiBi5OAZjyXXzM
|
||||
f8WYLqv7TXP61Sa4rqT12CI3xaN73YS2pt089f96odCKaEPnWJ3iSGmzJaW/ug10
|
||||
2Zo8Wj2k4s7t8wt4H3HtTu+y5UZfV3VOO+l//sdE/o+Lsub8FZH7/eOq7OnbNp4n
|
||||
vwjE8mqJXetNMfj8r2SCyvkEnlVRYR+/mnge+ib56FdJ8uKtqSxyvgA=
|
||||
=fRXs
|
||||
-----END PGP MESSAGE-----`
|
||||
|
||||
const criticalNotationSigner = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+
|
||||
fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5
|
||||
GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0
|
||||
JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS
|
||||
YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6
|
||||
AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki
|
||||
Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf
|
||||
9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa
|
||||
JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag
|
||||
Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr
|
||||
woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb
|
||||
LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA
|
||||
SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP
|
||||
GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2
|
||||
bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X
|
||||
W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD
|
||||
AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY
|
||||
hz3tYjKhoFTKEIq3y3Pp
|
||||
=h/aX
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
298
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
generated
vendored
298
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
generated
vendored
@@ -3,7 +3,8 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package s2k implements the various OpenPGP string-to-key transforms as
|
||||
// specified in RFC 4800 section 3.7.1.
|
||||
// specified in RFC 4800 section 3.7.1, and Argon2 specified in
|
||||
// draft-ietf-openpgp-crypto-refresh-08 section 3.7.1.4.
|
||||
package s2k // import "github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
|
||||
import (
|
||||
@@ -14,70 +15,47 @@ import (
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"golang.org/x/crypto/argon2"
|
||||
)
|
||||
|
||||
// Config collects configuration parameters for s2k key-stretching
|
||||
// transformations. A nil *Config is valid and results in all default
|
||||
// values. Currently, Config is used only by the Serialize function in
|
||||
// this package.
|
||||
type Config struct {
|
||||
// S2KMode is the mode of s2k function.
|
||||
// It can be 0 (simple), 1(salted), 3(iterated)
|
||||
// 2(reserved) 100-110(private/experimental).
|
||||
S2KMode uint8
|
||||
// Hash is the default hash function to be used. If
|
||||
// nil, SHA256 is used.
|
||||
Hash crypto.Hash
|
||||
// S2KCount is only used for symmetric encryption. It
|
||||
// determines the strength of the passphrase stretching when
|
||||
// the said passphrase is hashed to produce a key. S2KCount
|
||||
// should be between 65536 and 65011712, inclusive. If Config
|
||||
// is nil or S2KCount is 0, the value 16777216 used. Not all
|
||||
// values in the above range can be represented. S2KCount will
|
||||
// be rounded up to the next representable value if it cannot
|
||||
// be encoded exactly. See RFC 4880 Section 3.7.1.3.
|
||||
S2KCount int
|
||||
}
|
||||
type Mode uint8
|
||||
|
||||
// Defines the default S2KMode constants
|
||||
//
|
||||
// 0 (simple), 1(salted), 3(iterated), 4(argon2)
|
||||
const (
|
||||
SimpleS2K Mode = 0
|
||||
SaltedS2K Mode = 1
|
||||
IteratedSaltedS2K Mode = 3
|
||||
Argon2S2K Mode = 4
|
||||
GnuS2K Mode = 101
|
||||
)
|
||||
|
||||
const Argon2SaltSize int = 16
|
||||
|
||||
// Params contains all the parameters of the s2k packet
|
||||
type Params struct {
|
||||
// mode is the mode of s2k function.
|
||||
// It can be 0 (simple), 1(salted), 3(iterated)
|
||||
// 2(reserved) 100-110(private/experimental).
|
||||
mode uint8
|
||||
mode Mode
|
||||
// hashId is the ID of the hash function used in any of the modes
|
||||
hashId byte
|
||||
// salt is a byte array to use as a salt in hashing process
|
||||
salt []byte
|
||||
// salt is a byte array to use as a salt in hashing process or argon2
|
||||
saltBytes [Argon2SaltSize]byte
|
||||
// countByte is used to determine how many rounds of hashing are to
|
||||
// be performed in s2k mode 3. See RFC 4880 Section 3.7.1.3.
|
||||
countByte byte
|
||||
}
|
||||
|
||||
func (c *Config) hash() crypto.Hash {
|
||||
if c == nil || uint(c.Hash) == 0 {
|
||||
return crypto.SHA256
|
||||
}
|
||||
|
||||
return c.Hash
|
||||
}
|
||||
|
||||
// EncodedCount get encoded count
|
||||
func (c *Config) EncodedCount() uint8 {
|
||||
if c == nil || c.S2KCount == 0 {
|
||||
return 224 // The common case. Corresponding to 16777216
|
||||
}
|
||||
|
||||
i := c.S2KCount
|
||||
|
||||
switch {
|
||||
case i < 65536:
|
||||
i = 65536
|
||||
case i > 65011712:
|
||||
i = 65011712
|
||||
}
|
||||
|
||||
return encodeCount(i)
|
||||
// passes is a parameter in Argon2 to determine the number of iterations
|
||||
// See RFC the crypto refresh Section 3.7.1.4.
|
||||
passes byte
|
||||
// parallelism is a parameter in Argon2 to determine the degree of paralellism
|
||||
// See RFC the crypto refresh Section 3.7.1.4.
|
||||
parallelism byte
|
||||
// memoryExp is a parameter in Argon2 to determine the memory usage
|
||||
// i.e., 2 ** memoryExp kibibytes
|
||||
// See RFC the crypto refresh Section 3.7.1.4.
|
||||
memoryExp byte
|
||||
}
|
||||
|
||||
// encodeCount converts an iterative "count" in the range 1024 to
|
||||
@@ -106,6 +84,31 @@ func decodeCount(c uint8) int {
|
||||
return (16 + int(c&15)) << (uint32(c>>4) + 6)
|
||||
}
|
||||
|
||||
// encodeMemory converts the Argon2 "memory" in the range parallelism*8 to
|
||||
// 2**31, inclusive, to an encoded memory. The return value is the
|
||||
// octet that is actually stored in the GPG file. encodeMemory panics
|
||||
// if is not in the above range
|
||||
// See OpenPGP crypto refresh Section 3.7.1.4.
|
||||
func encodeMemory(memory uint32, parallelism uint8) uint8 {
|
||||
if memory < (8 * uint32(parallelism)) || memory > uint32(2147483648) {
|
||||
panic("Memory argument memory is outside the required range")
|
||||
}
|
||||
|
||||
for exp := 3; exp < 31; exp++ {
|
||||
compare := decodeMemory(uint8(exp))
|
||||
if compare >= memory {
|
||||
return uint8(exp)
|
||||
}
|
||||
}
|
||||
|
||||
return 31
|
||||
}
|
||||
|
||||
// decodeMemory computes the decoded memory in kibibytes as 2**memoryExponent
|
||||
func decodeMemory(memoryExponent uint8) uint32 {
|
||||
return uint32(1) << memoryExponent
|
||||
}
|
||||
|
||||
// Simple writes to out the result of computing the Simple S2K function (RFC
|
||||
// 4880, section 3.7.1.1) using the given hash and input passphrase.
|
||||
func Simple(out []byte, h hash.Hash, in []byte) {
|
||||
@@ -169,25 +172,53 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
|
||||
}
|
||||
}
|
||||
|
||||
// Argon2 writes to out the key derived from the password (in) with the Argon2
|
||||
// function (the crypto refresh, section 3.7.1.4)
|
||||
func Argon2(out []byte, in []byte, salt []byte, passes uint8, paralellism uint8, memoryExp uint8) {
|
||||
key := argon2.IDKey(in, salt, uint32(passes), decodeMemory(memoryExp), paralellism, uint32(len(out)))
|
||||
copy(out[:], key)
|
||||
}
|
||||
|
||||
// Generate generates valid parameters from given configuration.
|
||||
// It will enforce salted + hashed s2k method
|
||||
// It will enforce the Iterated and Salted or Argon2 S2K method.
|
||||
func Generate(rand io.Reader, c *Config) (*Params, error) {
|
||||
hashId, ok := HashToHashId(c.Hash)
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("no such hash")
|
||||
}
|
||||
var params *Params
|
||||
if c != nil && c.Mode() == Argon2S2K {
|
||||
// handle Argon2 case
|
||||
argonConfig := c.Argon2()
|
||||
params = &Params{
|
||||
mode: Argon2S2K,
|
||||
passes: argonConfig.Passes(),
|
||||
parallelism: argonConfig.Parallelism(),
|
||||
memoryExp: argonConfig.EncodedMemory(),
|
||||
}
|
||||
} else if c != nil && c.PassphraseIsHighEntropy && c.Mode() == SaltedS2K { // Allow SaltedS2K if PassphraseIsHighEntropy
|
||||
hashId, ok := algorithm.HashToHashId(c.hash())
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("no such hash")
|
||||
}
|
||||
|
||||
params := &Params{
|
||||
mode: 3, // Enforce iterared + salted method
|
||||
hashId: hashId,
|
||||
salt: make([]byte, 8),
|
||||
countByte: c.EncodedCount(),
|
||||
params = &Params{
|
||||
mode: SaltedS2K,
|
||||
hashId: hashId,
|
||||
}
|
||||
} else { // Enforce IteratedSaltedS2K method otherwise
|
||||
hashId, ok := algorithm.HashToHashId(c.hash())
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("no such hash")
|
||||
}
|
||||
if c != nil {
|
||||
c.S2KMode = IteratedSaltedS2K
|
||||
}
|
||||
params = &Params{
|
||||
mode: IteratedSaltedS2K,
|
||||
hashId: hashId,
|
||||
countByte: c.EncodedCount(),
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(rand, params.salt); err != nil {
|
||||
if _, err := io.ReadFull(rand, params.salt()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
@@ -207,45 +238,60 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) {
|
||||
// ParseIntoParams reads a binary specification for a string-to-key
|
||||
// transformation from r and returns a struct describing the s2k parameters.
|
||||
func ParseIntoParams(r io.Reader) (params *Params, err error) {
|
||||
var buf [9]byte
|
||||
var buf [Argon2SaltSize + 3]byte
|
||||
|
||||
_, err = io.ReadFull(r, buf[:2])
|
||||
_, err = io.ReadFull(r, buf[:1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
params = &Params{
|
||||
mode: buf[0],
|
||||
hashId: buf[1],
|
||||
mode: Mode(buf[0]),
|
||||
}
|
||||
|
||||
switch params.mode {
|
||||
case 0:
|
||||
return params, nil
|
||||
case 1:
|
||||
_, err = io.ReadFull(r, buf[:8])
|
||||
case SimpleS2K:
|
||||
_, err = io.ReadFull(r, buf[:1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params.salt = buf[:8]
|
||||
params.hashId = buf[0]
|
||||
return params, nil
|
||||
case 3:
|
||||
case SaltedS2K:
|
||||
_, err = io.ReadFull(r, buf[:9])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params.salt = buf[:8]
|
||||
params.countByte = buf[8]
|
||||
params.hashId = buf[0]
|
||||
copy(params.salt(), buf[1:9])
|
||||
return params, nil
|
||||
case 101:
|
||||
// This is a GNU extension. See
|
||||
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
|
||||
if _, err = io.ReadFull(r, buf[:4]); err != nil {
|
||||
case IteratedSaltedS2K:
|
||||
_, err = io.ReadFull(r, buf[:10])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if buf[0] == 'G' && buf[1] == 'N' && buf[2] == 'U' && buf[3] == 1 {
|
||||
params.hashId = buf[0]
|
||||
copy(params.salt(), buf[1:9])
|
||||
params.countByte = buf[9]
|
||||
return params, nil
|
||||
case Argon2S2K:
|
||||
_, err = io.ReadFull(r, buf[:Argon2SaltSize+3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(params.salt(), buf[:Argon2SaltSize])
|
||||
params.passes = buf[Argon2SaltSize]
|
||||
params.parallelism = buf[Argon2SaltSize+1]
|
||||
params.memoryExp = buf[Argon2SaltSize+2]
|
||||
return params, nil
|
||||
case GnuS2K:
|
||||
// This is a GNU extension. See
|
||||
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
|
||||
if _, err = io.ReadFull(r, buf[:5]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.hashId = buf[0]
|
||||
if buf[1] == 'G' && buf[2] == 'N' && buf[3] == 'U' && buf[4] == 1 {
|
||||
return params, nil
|
||||
}
|
||||
return nil, errors.UnsupportedError("GNU S2K extension")
|
||||
@@ -255,39 +301,56 @@ func ParseIntoParams(r io.Reader) (params *Params, err error) {
|
||||
}
|
||||
|
||||
func (params *Params) Dummy() bool {
|
||||
return params != nil && params.mode == 101
|
||||
return params != nil && params.mode == GnuS2K
|
||||
}
|
||||
|
||||
func (params *Params) salt() []byte {
|
||||
switch params.mode {
|
||||
case SaltedS2K, IteratedSaltedS2K: return params.saltBytes[:8]
|
||||
case Argon2S2K: return params.saltBytes[:Argon2SaltSize]
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (params *Params) Function() (f func(out, in []byte), err error) {
|
||||
if params.Dummy() {
|
||||
return nil, errors.ErrDummyPrivateKey("dummy key found")
|
||||
}
|
||||
hashObj, ok := HashIdToHash(params.hashId)
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(params.hashId)))
|
||||
}
|
||||
if !hashObj.Available() {
|
||||
return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashObj)))
|
||||
var hashObj crypto.Hash
|
||||
if params.mode != Argon2S2K {
|
||||
var ok bool
|
||||
hashObj, ok = algorithm.HashIdToHashWithSha1(params.hashId)
|
||||
if !ok {
|
||||
return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(params.hashId)))
|
||||
}
|
||||
if !hashObj.Available() {
|
||||
return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashObj)))
|
||||
}
|
||||
}
|
||||
|
||||
switch params.mode {
|
||||
case 0:
|
||||
case SimpleS2K:
|
||||
f := func(out, in []byte) {
|
||||
Simple(out, hashObj.New(), in)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
case 1:
|
||||
case SaltedS2K:
|
||||
f := func(out, in []byte) {
|
||||
Salted(out, hashObj.New(), in, params.salt)
|
||||
Salted(out, hashObj.New(), in, params.salt())
|
||||
}
|
||||
|
||||
return f, nil
|
||||
case 3:
|
||||
case IteratedSaltedS2K:
|
||||
f := func(out, in []byte) {
|
||||
Iterated(out, hashObj.New(), in, params.salt, decodeCount(params.countByte))
|
||||
Iterated(out, hashObj.New(), in, params.salt(), decodeCount(params.countByte))
|
||||
}
|
||||
|
||||
return f, nil
|
||||
case Argon2S2K:
|
||||
f := func(out, in []byte) {
|
||||
Argon2(out, in, params.salt(), params.passes, params.parallelism, params.memoryExp)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
@@ -295,23 +358,28 @@ func (params *Params) Function() (f func(out, in []byte), err error) {
|
||||
}
|
||||
|
||||
func (params *Params) Serialize(w io.Writer) (err error) {
|
||||
if _, err = w.Write([]byte{params.mode}); err != nil {
|
||||
if _, err = w.Write([]byte{uint8(params.mode)}); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = w.Write([]byte{params.hashId}); err != nil {
|
||||
return
|
||||
if params.mode != Argon2S2K {
|
||||
if _, err = w.Write([]byte{params.hashId}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if params.Dummy() {
|
||||
_, err = w.Write(append([]byte("GNU"), 1))
|
||||
return
|
||||
}
|
||||
if params.mode > 0 {
|
||||
if _, err = w.Write(params.salt); err != nil {
|
||||
if _, err = w.Write(params.salt()); err != nil {
|
||||
return
|
||||
}
|
||||
if params.mode == 3 {
|
||||
if params.mode == IteratedSaltedS2K {
|
||||
_, err = w.Write([]byte{params.countByte})
|
||||
}
|
||||
if params.mode == Argon2S2K {
|
||||
_, err = w.Write([]byte{params.passes, params.parallelism, params.memoryExp})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -337,31 +405,3 @@ func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Co
|
||||
f(key, passphrase)
|
||||
return nil
|
||||
}
|
||||
|
||||
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
|
||||
// hash id.
|
||||
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
|
||||
if hash, ok := algorithm.HashById[id]; ok {
|
||||
return hash.HashFunc(), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// HashIdToString returns the name of the hash function corresponding to the
|
||||
// given OpenPGP hash id.
|
||||
func HashIdToString(id byte) (name string, ok bool) {
|
||||
if hash, ok := algorithm.HashById[id]; ok {
|
||||
return hash.String(), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
|
||||
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
|
||||
for id, hash := range algorithm.HashById {
|
||||
if hash.HashFunc() == h {
|
||||
return id, true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
26
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go
generated
vendored
Normal file
26
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package s2k
|
||||
|
||||
// Cache stores keys derived with s2k functions from one passphrase
|
||||
// to avoid recomputation if multiple items are encrypted with
|
||||
// the same parameters.
|
||||
type Cache map[Params][]byte
|
||||
|
||||
// GetOrComputeDerivedKey tries to retrieve the key
|
||||
// for the given s2k parameters from the cache.
|
||||
// If there is no hit, it derives the key with the s2k function from the passphrase,
|
||||
// updates the cache, and returns the key.
|
||||
func (c *Cache) GetOrComputeDerivedKey(passphrase []byte, params *Params, expectedKeySize int) ([]byte, error) {
|
||||
key, found := (*c)[*params]
|
||||
if !found || len(key) != expectedKeySize {
|
||||
var err error
|
||||
derivedKey := make([]byte, expectedKeySize)
|
||||
s2k, err := params.Function()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s2k(derivedKey, passphrase)
|
||||
(*c)[*params] = key
|
||||
return derivedKey, nil
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
129
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
generated
vendored
Normal file
129
vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
package s2k
|
||||
|
||||
import "crypto"
|
||||
|
||||
// Config collects configuration parameters for s2k key-stretching
|
||||
// transformations. A nil *Config is valid and results in all default
|
||||
// values.
|
||||
type Config struct {
|
||||
// S2K (String to Key) mode, used for key derivation in the context of secret key encryption
|
||||
// and passphrase-encrypted data. Either s2k.Argon2S2K or s2k.IteratedSaltedS2K may be used.
|
||||
// If the passphrase is a high-entropy key, indicated by setting PassphraseIsHighEntropy to true,
|
||||
// s2k.SaltedS2K can also be used.
|
||||
// Note: Argon2 is the strongest option but not all OpenPGP implementations are compatible with it
|
||||
//(pending standardisation).
|
||||
// 0 (simple), 1(salted), 3(iterated), 4(argon2)
|
||||
// 2(reserved) 100-110(private/experimental).
|
||||
S2KMode Mode
|
||||
// Only relevant if S2KMode is not set to s2k.Argon2S2K.
|
||||
// Hash is the default hash function to be used. If
|
||||
// nil, SHA256 is used.
|
||||
Hash crypto.Hash
|
||||
// Argon2 parameters for S2K (String to Key).
|
||||
// Only relevant if S2KMode is set to s2k.Argon2S2K.
|
||||
// If nil, default parameters are used.
|
||||
// For more details on the choice of parameters, see https://tools.ietf.org/html/rfc9106#section-4.
|
||||
Argon2Config *Argon2Config
|
||||
// Only relevant if S2KMode is set to s2k.IteratedSaltedS2K.
|
||||
// Iteration count for Iterated S2K (String to Key). It
|
||||
// determines the strength of the passphrase stretching when
|
||||
// the said passphrase is hashed to produce a key. S2KCount
|
||||
// should be between 65536 and 65011712, inclusive. If Config
|
||||
// is nil or S2KCount is 0, the value 16777216 used. Not all
|
||||
// values in the above range can be represented. S2KCount will
|
||||
// be rounded up to the next representable value if it cannot
|
||||
// be encoded exactly. When set, it is strongly encrouraged to
|
||||
// use a value that is at least 65536. See RFC 4880 Section
|
||||
// 3.7.1.3.
|
||||
S2KCount int
|
||||
// Indicates whether the passphrase passed by the application is a
|
||||
// high-entropy key (e.g. it's randomly generated or derived from
|
||||
// another passphrase using a strong key derivation function).
|
||||
// When true, allows the S2KMode to be s2k.SaltedS2K.
|
||||
// When the passphrase is not a high-entropy key, using SaltedS2K is
|
||||
// insecure, and not allowed by draft-ietf-openpgp-crypto-refresh-08.
|
||||
PassphraseIsHighEntropy bool
|
||||
}
|
||||
|
||||
// Argon2Config stores the Argon2 parameters
|
||||
// A nil *Argon2Config is valid and results in all default
|
||||
type Argon2Config struct {
|
||||
NumberOfPasses uint8
|
||||
DegreeOfParallelism uint8
|
||||
// The memory parameter for Argon2 specifies desired memory usage in kibibytes.
|
||||
// For example memory=64*1024 sets the memory cost to ~64 MB.
|
||||
Memory uint32
|
||||
}
|
||||
|
||||
func (c *Config) Mode() Mode {
|
||||
if c == nil {
|
||||
return IteratedSaltedS2K
|
||||
}
|
||||
return c.S2KMode
|
||||
}
|
||||
|
||||
func (c *Config) hash() crypto.Hash {
|
||||
if c == nil || uint(c.Hash) == 0 {
|
||||
return crypto.SHA256
|
||||
}
|
||||
|
||||
return c.Hash
|
||||
}
|
||||
|
||||
func (c *Config) Argon2() *Argon2Config {
|
||||
if c == nil || c.Argon2Config == nil {
|
||||
return nil
|
||||
}
|
||||
return c.Argon2Config
|
||||
}
|
||||
|
||||
// EncodedCount get encoded count
|
||||
func (c *Config) EncodedCount() uint8 {
|
||||
if c == nil || c.S2KCount == 0 {
|
||||
return 224 // The common case. Corresponding to 16777216
|
||||
}
|
||||
|
||||
i := c.S2KCount
|
||||
|
||||
switch {
|
||||
case i < 65536:
|
||||
i = 65536
|
||||
case i > 65011712:
|
||||
i = 65011712
|
||||
}
|
||||
|
||||
return encodeCount(i)
|
||||
}
|
||||
|
||||
func (c *Argon2Config) Passes() uint8 {
|
||||
if c == nil || c.NumberOfPasses == 0 {
|
||||
return 3
|
||||
}
|
||||
return c.NumberOfPasses
|
||||
}
|
||||
|
||||
func (c *Argon2Config) Parallelism() uint8 {
|
||||
if c == nil || c.DegreeOfParallelism == 0 {
|
||||
return 4
|
||||
}
|
||||
return c.DegreeOfParallelism
|
||||
}
|
||||
|
||||
func (c *Argon2Config) EncodedMemory() uint8 {
|
||||
if c == nil || c.Memory == 0 {
|
||||
return 16 // 64 MiB of RAM
|
||||
}
|
||||
|
||||
memory := c.Memory
|
||||
lowerBound := uint32(c.Parallelism())*8
|
||||
upperBound := uint32(2147483648)
|
||||
|
||||
switch {
|
||||
case memory < lowerBound:
|
||||
memory = lowerBound
|
||||
case memory > upperBound:
|
||||
memory = upperBound
|
||||
}
|
||||
|
||||
return encodeMemory(memory, c.Parallelism())
|
||||
}
|
||||
185
vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
generated
vendored
185
vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
generated
vendored
@@ -13,8 +13,8 @@ import (
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
||||
)
|
||||
|
||||
// DetachSign signs message with the private key from signer (which must
|
||||
@@ -70,15 +70,11 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
|
||||
if signingKey.PrivateKey.Encrypted {
|
||||
return errors.InvalidArgumentError("signing key is encrypted")
|
||||
}
|
||||
if _, ok := algorithm.HashToHashId(config.Hash()); !ok {
|
||||
return errors.InvalidArgumentError("invalid hash function")
|
||||
}
|
||||
|
||||
sig := new(packet.Signature)
|
||||
sig.SigType = sigType
|
||||
sig.PubKeyAlgo = signingKey.PrivateKey.PubKeyAlgo
|
||||
sig.Hash = config.Hash()
|
||||
sig.CreationTime = config.Now()
|
||||
sigLifetimeSecs := config.SigLifetime()
|
||||
sig.SigLifetimeSecs = &sigLifetimeSecs
|
||||
sig.IssuerKeyId = &signingKey.PrivateKey.KeyId
|
||||
sig := createSignaturePacket(signingKey.PublicKey, sigType, config)
|
||||
|
||||
h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
|
||||
if err != nil {
|
||||
@@ -125,16 +121,13 @@ func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHi
|
||||
}
|
||||
|
||||
var w io.WriteCloser
|
||||
if config.AEAD() != nil {
|
||||
w, err = packet.SerializeAEADEncrypted(ciphertext, key, config.Cipher(), config.AEAD().Mode(), config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
w, err = packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cipherSuite := packet.CipherSuite{
|
||||
Cipher: config.Cipher(),
|
||||
Mode: config.AEAD().Mode(),
|
||||
}
|
||||
w, err = packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), config.AEAD() != nil, cipherSuite, key, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
literalData := w
|
||||
@@ -173,8 +166,25 @@ func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
|
||||
return a[:j]
|
||||
}
|
||||
|
||||
// intersectPreferences mutates and returns a prefix of a that contains only
|
||||
// the values in the intersection of a and b. The order of a is preserved.
|
||||
func intersectCipherSuites(a [][2]uint8, b [][2]uint8) (intersection [][2]uint8) {
|
||||
var j int
|
||||
for _, v := range a {
|
||||
for _, v2 := range b {
|
||||
if v[0] == v2[0] && v[1] == v2[1] {
|
||||
a[j] = v
|
||||
j++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return a[:j]
|
||||
}
|
||||
|
||||
func hashToHashId(h crypto.Hash) uint8 {
|
||||
v, ok := s2k.HashToHashId(h)
|
||||
v, ok := algorithm.HashToHashId(h)
|
||||
if !ok {
|
||||
panic("tried to convert unknown hash")
|
||||
}
|
||||
@@ -240,7 +250,7 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
||||
|
||||
var hash crypto.Hash
|
||||
for _, hashId := range candidateHashes {
|
||||
if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
|
||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h.Available() {
|
||||
hash = h
|
||||
break
|
||||
}
|
||||
@@ -249,7 +259,7 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
||||
// If the hash specified by config is a candidate, we'll use that.
|
||||
if configuredHash := config.Hash(); configuredHash.Available() {
|
||||
for _, hashId := range candidateHashes {
|
||||
if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
|
||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h == configuredHash {
|
||||
hash = h
|
||||
break
|
||||
}
|
||||
@@ -258,7 +268,7 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
||||
|
||||
if hash == 0 {
|
||||
hashId := candidateHashes[0]
|
||||
name, ok := s2k.HashIdToString(hashId)
|
||||
name, ok := algorithm.HashIdToString(hashId)
|
||||
if !ok {
|
||||
name = "#" + strconv.Itoa(int(hashId))
|
||||
}
|
||||
@@ -329,39 +339,39 @@ func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *En
|
||||
|
||||
// These are the possible ciphers that we'll use for the message.
|
||||
candidateCiphers := []uint8{
|
||||
uint8(packet.CipherAES128),
|
||||
uint8(packet.CipherAES256),
|
||||
uint8(packet.CipherCAST5),
|
||||
uint8(packet.CipherAES128),
|
||||
}
|
||||
|
||||
// These are the possible hash functions that we'll use for the signature.
|
||||
candidateHashes := []uint8{
|
||||
hashToHashId(crypto.SHA256),
|
||||
hashToHashId(crypto.SHA384),
|
||||
hashToHashId(crypto.SHA512),
|
||||
hashToHashId(crypto.SHA1),
|
||||
hashToHashId(crypto.RIPEMD160),
|
||||
hashToHashId(crypto.SHA3_256),
|
||||
hashToHashId(crypto.SHA3_512),
|
||||
}
|
||||
candidateAeadModes := []uint8{
|
||||
uint8(packet.AEADModeEAX),
|
||||
uint8(packet.AEADModeOCB),
|
||||
uint8(packet.AEADModeExperimentalGCM),
|
||||
|
||||
// Prefer GCM if everyone supports it
|
||||
candidateCipherSuites := [][2]uint8{
|
||||
{uint8(packet.CipherAES256), uint8(packet.AEADModeGCM)},
|
||||
{uint8(packet.CipherAES256), uint8(packet.AEADModeEAX)},
|
||||
{uint8(packet.CipherAES256), uint8(packet.AEADModeOCB)},
|
||||
{uint8(packet.CipherAES128), uint8(packet.AEADModeGCM)},
|
||||
{uint8(packet.CipherAES128), uint8(packet.AEADModeEAX)},
|
||||
{uint8(packet.CipherAES128), uint8(packet.AEADModeOCB)},
|
||||
}
|
||||
|
||||
candidateCompression := []uint8{
|
||||
uint8(packet.CompressionNone),
|
||||
uint8(packet.CompressionZIP),
|
||||
uint8(packet.CompressionZLIB),
|
||||
}
|
||||
// In the event that a recipient doesn't specify any supported ciphers
|
||||
// or hash functions, these are the ones that we assume that every
|
||||
// implementation supports.
|
||||
defaultCiphers := candidateCiphers[0:1]
|
||||
defaultHashes := candidateHashes[0:1]
|
||||
defaultAeadModes := candidateAeadModes[0:1]
|
||||
defaultCompression := candidateCompression[0:1]
|
||||
|
||||
encryptKeys := make([]Key, len(to))
|
||||
// AEAD is used only if every key supports it.
|
||||
aeadSupported := true
|
||||
|
||||
// AEAD is used only if config enables it and every key supports it
|
||||
aeadSupported := config.AEAD() != nil
|
||||
|
||||
for i := range to {
|
||||
var ok bool
|
||||
@@ -371,38 +381,37 @@ func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *En
|
||||
}
|
||||
|
||||
sig := to[i].PrimaryIdentity().SelfSignature
|
||||
if sig.AEAD == false {
|
||||
if !sig.SEIPDv2 {
|
||||
aeadSupported = false
|
||||
}
|
||||
|
||||
preferredSymmetric := sig.PreferredSymmetric
|
||||
if len(preferredSymmetric) == 0 {
|
||||
preferredSymmetric = defaultCiphers
|
||||
}
|
||||
preferredHashes := sig.PreferredHash
|
||||
if len(preferredHashes) == 0 {
|
||||
preferredHashes = defaultHashes
|
||||
}
|
||||
preferredAeadModes := sig.PreferredAEAD
|
||||
if len(preferredAeadModes) == 0 {
|
||||
preferredAeadModes = defaultAeadModes
|
||||
}
|
||||
preferredCompression := sig.PreferredCompression
|
||||
if len(preferredCompression) == 0 {
|
||||
preferredCompression = defaultCompression
|
||||
}
|
||||
candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
|
||||
candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
|
||||
candidateAeadModes = intersectPreferences(candidateAeadModes, preferredAeadModes)
|
||||
candidateCompression = intersectPreferences(candidateCompression, preferredCompression)
|
||||
candidateCiphers = intersectPreferences(candidateCiphers, sig.PreferredSymmetric)
|
||||
candidateHashes = intersectPreferences(candidateHashes, sig.PreferredHash)
|
||||
candidateCipherSuites = intersectCipherSuites(candidateCipherSuites, sig.PreferredCipherSuites)
|
||||
candidateCompression = intersectPreferences(candidateCompression, sig.PreferredCompression)
|
||||
}
|
||||
|
||||
if len(candidateCiphers) == 0 || len(candidateHashes) == 0 || len(candidateAeadModes) == 0 {
|
||||
return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
|
||||
// In the event that the intersection of supported algorithms is empty we use the ones
|
||||
// labelled as MUST that every implementation supports.
|
||||
if len(candidateCiphers) == 0 {
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.3
|
||||
candidateCiphers = []uint8{uint8(packet.CipherAES128)}
|
||||
}
|
||||
if len(candidateHashes) == 0 {
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#hash-algos
|
||||
candidateHashes = []uint8{hashToHashId(crypto.SHA256)}
|
||||
}
|
||||
if len(candidateCipherSuites) == 0 {
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.6
|
||||
candidateCipherSuites = [][2]uint8{{uint8(packet.CipherAES128), uint8(packet.AEADModeOCB)}}
|
||||
}
|
||||
|
||||
cipher := packet.CipherFunction(candidateCiphers[0])
|
||||
mode := packet.AEADMode(candidateAeadModes[0])
|
||||
aeadCipherSuite := packet.CipherSuite{
|
||||
Cipher: packet.CipherFunction(candidateCipherSuites[0][0]),
|
||||
Mode: packet.AEADMode(candidateCipherSuites[0][1]),
|
||||
}
|
||||
|
||||
// If the cipher specified by config is a candidate, we'll use that.
|
||||
configuredCipher := config.Cipher()
|
||||
for _, c := range candidateCiphers {
|
||||
@@ -425,17 +434,11 @@ func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *En
|
||||
}
|
||||
|
||||
var payload io.WriteCloser
|
||||
if config.AEAD() != nil && aeadSupported {
|
||||
payload, err = packet.SerializeAEADEncrypted(dataWriter, symKey, cipher, mode, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
payload, err = packet.SerializeSymmetricallyEncrypted(dataWriter, cipher, symKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
payload, err = packet.SerializeSymmetricallyEncrypted(dataWriter, cipher, aeadSupported, aeadCipherSuite, symKey, config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
payload, err = handleCompression(payload, candidateCompression, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -458,8 +461,8 @@ func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Con
|
||||
hashToHashId(crypto.SHA256),
|
||||
hashToHashId(crypto.SHA384),
|
||||
hashToHashId(crypto.SHA512),
|
||||
hashToHashId(crypto.SHA1),
|
||||
hashToHashId(crypto.RIPEMD160),
|
||||
hashToHashId(crypto.SHA3_256),
|
||||
hashToHashId(crypto.SHA3_512),
|
||||
}
|
||||
defaultHashes := candidateHashes[0:1]
|
||||
preferredHashes := signed.PrimaryIdentity().SelfSignature.PreferredHash
|
||||
@@ -502,15 +505,9 @@ func (s signatureWriter) Write(data []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (s signatureWriter) Close() error {
|
||||
sig := &packet.Signature{
|
||||
Version: s.signer.Version,
|
||||
SigType: s.sigType,
|
||||
PubKeyAlgo: s.signer.PubKeyAlgo,
|
||||
Hash: s.hashType,
|
||||
CreationTime: s.config.Now(),
|
||||
IssuerKeyId: &s.signer.KeyId,
|
||||
Metadata: s.metadata,
|
||||
}
|
||||
sig := createSignaturePacket(&s.signer.PublicKey, s.sigType, s.config)
|
||||
sig.Hash = s.hashType
|
||||
sig.Metadata = s.metadata
|
||||
|
||||
if err := sig.Sign(s.h, s.signer, s.config); err != nil {
|
||||
return err
|
||||
@@ -524,6 +521,21 @@ func (s signatureWriter) Close() error {
|
||||
return s.encryptedData.Close()
|
||||
}
|
||||
|
||||
func createSignaturePacket(signer *packet.PublicKey, sigType packet.SignatureType, config *packet.Config) *packet.Signature {
|
||||
sigLifetimeSecs := config.SigLifetime()
|
||||
return &packet.Signature{
|
||||
Version: signer.Version,
|
||||
SigType: sigType,
|
||||
PubKeyAlgo: signer.PubKeyAlgo,
|
||||
Hash: config.Hash(),
|
||||
CreationTime: config.Now(),
|
||||
IssuerKeyId: &signer.KeyId,
|
||||
IssuerFingerprint: signer.Fingerprint,
|
||||
Notations: config.Notations(),
|
||||
SigLifetimeSecs: &sigLifetimeSecs,
|
||||
}
|
||||
}
|
||||
|
||||
// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
|
||||
// TODO: we have two of these in OpenPGP packages alone. This probably needs
|
||||
// to be promoted somewhere more common.
|
||||
@@ -545,6 +557,9 @@ func handleCompression(compressed io.WriteCloser, candidateCompression []uint8,
|
||||
if confAlgo == packet.CompressionNone {
|
||||
return
|
||||
}
|
||||
|
||||
// Set algorithm labelled as MUST as fallback
|
||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.4
|
||||
finalAlgo := packet.CompressionNone
|
||||
// if compression specified by config available we will use it
|
||||
for _, c := range candidateCompression {
|
||||
|
||||
42
vendor/github.com/acomagu/bufpipe/README.md
generated
vendored
42
vendor/github.com/acomagu/bufpipe/README.md
generated
vendored
@@ -1,42 +0,0 @@
|
||||
# bufpipe: Buffered Pipe
|
||||
|
||||
[](https://circleci.com/gh/acomagu/bufpipe) [](https://godoc.org/github.com/acomagu/bufpipe)
|
||||
|
||||
The buffered version of io.Pipe. It's safe for concurrent use.
|
||||
|
||||
## How does it differ from io.Pipe?
|
||||
|
||||
Writes never block because the pipe has variable-sized buffer.
|
||||
|
||||
```Go
|
||||
r, w := bufpipe.New(nil)
|
||||
io.WriteString(w, "abc") // No blocking.
|
||||
io.WriteString(w, "def") // No blocking, too.
|
||||
w.Close()
|
||||
io.Copy(os.Stdout, r)
|
||||
// Output: abcdef
|
||||
```
|
||||
|
||||
[Playground](https://play.golang.org/p/PdyBAS3pVob)
|
||||
|
||||
## How does it differ from bytes.Buffer?
|
||||
|
||||
Reads block if the internal buffer is empty until the writer is closed.
|
||||
|
||||
```Go
|
||||
r, w := bufpipe.New(nil)
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
io.Copy(os.Stdout, r) // The reads block until the writer is closed.
|
||||
done <- struct{}{}
|
||||
}()
|
||||
|
||||
io.WriteString(w, "abc")
|
||||
io.WriteString(w, "def")
|
||||
w.Close()
|
||||
<-done
|
||||
// Output: abcdef
|
||||
```
|
||||
|
||||
[Playground](https://play.golang.org/p/UppmyLeRgX6)
|
||||
128
vendor/github.com/acomagu/bufpipe/bufpipe.go
generated
vendored
128
vendor/github.com/acomagu/bufpipe/bufpipe.go
generated
vendored
@@ -1,128 +0,0 @@
|
||||
package bufpipe
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ErrClosedPipe is the error used for read or write operations on a closed pipe.
|
||||
var ErrClosedPipe = errors.New("bufpipe: read/write on closed pipe")
|
||||
|
||||
type pipe struct {
|
||||
cond *sync.Cond
|
||||
buf *bytes.Buffer
|
||||
rerr, werr error
|
||||
}
|
||||
|
||||
// A PipeReader is the read half of a pipe.
|
||||
type PipeReader struct {
|
||||
*pipe
|
||||
}
|
||||
|
||||
// A PipeWriter is the write half of a pipe.
|
||||
type PipeWriter struct {
|
||||
*pipe
|
||||
}
|
||||
|
||||
// New creates a synchronous pipe using buf as its initial contents. It can be
|
||||
// used to connect code expecting an io.Reader with code expecting an io.Writer.
|
||||
//
|
||||
// Unlike io.Pipe, writes never block because the internal buffer has variable
|
||||
// size. Reads block only when the buffer is empty.
|
||||
//
|
||||
// It is safe to call Read and Write in parallel with each other or with Close.
|
||||
// Parallel calls to Read and parallel calls to Write are also safe: the
|
||||
// individual calls will be gated sequentially.
|
||||
//
|
||||
// The new pipe takes ownership of buf, and the caller should not use buf after
|
||||
// this call. New is intended to prepare a PipeReader to read existing data. It
|
||||
// can also be used to set the initial size of the internal buffer for writing.
|
||||
// To do that, buf should have the desired capacity but a length of zero.
|
||||
func New(buf []byte) (*PipeReader, *PipeWriter) {
|
||||
p := &pipe{
|
||||
buf: bytes.NewBuffer(buf),
|
||||
cond: sync.NewCond(new(sync.Mutex)),
|
||||
}
|
||||
return &PipeReader{
|
||||
pipe: p,
|
||||
}, &PipeWriter{
|
||||
pipe: p,
|
||||
}
|
||||
}
|
||||
|
||||
// Read implements the standard Read interface: it reads data from the pipe,
|
||||
// reading from the internal buffer, otherwise blocking until a writer arrives
|
||||
// or the write end is closed. If the write end is closed with an error, that
|
||||
// error is returned as err; otherwise err is io.EOF.
|
||||
func (r *PipeReader) Read(data []byte) (int, error) {
|
||||
r.cond.L.Lock()
|
||||
defer r.cond.L.Unlock()
|
||||
|
||||
RETRY:
|
||||
n, err := r.buf.Read(data)
|
||||
// If not closed and no read, wait for writing.
|
||||
if err == io.EOF && r.rerr == nil && n == 0 {
|
||||
r.cond.Wait()
|
||||
goto RETRY
|
||||
}
|
||||
if err == io.EOF {
|
||||
return n, r.rerr
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the reader; subsequent writes from the write half of the pipe
|
||||
// will return error ErrClosedPipe.
|
||||
func (r *PipeReader) Close() error {
|
||||
return r.CloseWithError(nil)
|
||||
}
|
||||
|
||||
// CloseWithError closes the reader; subsequent writes to the write half of the
|
||||
// pipe will return the error err.
|
||||
func (r *PipeReader) CloseWithError(err error) error {
|
||||
r.cond.L.Lock()
|
||||
defer r.cond.L.Unlock()
|
||||
|
||||
if err == nil {
|
||||
err = ErrClosedPipe
|
||||
}
|
||||
r.werr = err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements the standard Write interface: it writes data to the internal
|
||||
// buffer. If the read end is closed with an error, that err is returned as err;
|
||||
// otherwise err is ErrClosedPipe.
|
||||
func (w *PipeWriter) Write(data []byte) (int, error) {
|
||||
w.cond.L.Lock()
|
||||
defer w.cond.L.Unlock()
|
||||
|
||||
if w.werr != nil {
|
||||
return 0, w.werr
|
||||
}
|
||||
|
||||
n, err := w.buf.Write(data)
|
||||
w.cond.Signal()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the writer; subsequent reads from the read half of the pipe will
|
||||
// return io.EOF once the internal buffer get empty.
|
||||
func (w *PipeWriter) Close() error {
|
||||
return w.CloseWithError(nil)
|
||||
}
|
||||
|
||||
// Close closes the writer; subsequent reads from the read half of the pipe will
|
||||
// return err once the internal buffer get empty.
|
||||
func (w *PipeWriter) CloseWithError(err error) error {
|
||||
w.cond.L.Lock()
|
||||
defer w.cond.L.Unlock()
|
||||
|
||||
if err == nil {
|
||||
err = io.EOF
|
||||
}
|
||||
w.rerr = err
|
||||
return nil
|
||||
}
|
||||
2
vendor/github.com/acomagu/bufpipe/doc.go
generated
vendored
2
vendor/github.com/acomagu/bufpipe/doc.go
generated
vendored
@@ -1,2 +0,0 @@
|
||||
// Package bufpipe provides a IO pipe, has variable-sized buffer.
|
||||
package bufpipe
|
||||
57
vendor/github.com/cloudflare/circl/LICENSE
generated
vendored
Normal file
57
vendor/github.com/cloudflare/circl/LICENSE
generated
vendored
Normal file
@@ -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.
|
||||
96
vendor/github.com/cloudflare/circl/dh/x25519/curve.go
generated
vendored
Normal file
96
vendor/github.com/cloudflare/circl/dh/x25519/curve.go
generated
vendored
Normal file
@@ -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,
|
||||
},
|
||||
}
|
||||
30
vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go
generated
vendored
Normal file
30
vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go
generated
vendored
Normal file
@@ -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)
|
||||
111
vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h
generated
vendored
Normal file
111
vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h
generated
vendored
Normal file
@@ -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)
|
||||
156
vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s
generated
vendored
Normal file
156
vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s
generated
vendored
Normal file
@@ -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
|
||||
85
vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go
generated
vendored
Normal file
85
vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go
generated
vendored
Normal file
@@ -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])
|
||||
}
|
||||
}
|
||||
11
vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go
generated
vendored
Normal file
11
vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go
generated
vendored
Normal file
@@ -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) }
|
||||
19
vendor/github.com/cloudflare/circl/dh/x25519/doc.go
generated
vendored
Normal file
19
vendor/github.com/cloudflare/circl/dh/x25519/doc.go
generated
vendored
Normal file
@@ -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
|
||||
47
vendor/github.com/cloudflare/circl/dh/x25519/key.go
generated
vendored
Normal file
47
vendor/github.com/cloudflare/circl/dh/x25519/key.go
generated
vendored
Normal file
@@ -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
|
||||
}
|
||||
268
vendor/github.com/cloudflare/circl/dh/x25519/table.go
generated
vendored
Normal file
268
vendor/github.com/cloudflare/circl/dh/x25519/table.go
generated
vendored
Normal file
@@ -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,
|
||||
}
|
||||
104
vendor/github.com/cloudflare/circl/dh/x448/curve.go
generated
vendored
Normal file
104
vendor/github.com/cloudflare/circl/dh/x448/curve.go
generated
vendored
Normal file
@@ -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,
|
||||
},
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user