diff --git a/0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch b/0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch index 28f2252..4497c4a 100644 --- a/0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch +++ b/0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch @@ -1,7 +1,7 @@ -From 823bedd07fac6778a3d94b6f949ac16e6bd12638 Mon Sep 17 00:00:00 2001 +From 5c6812a104e161599fc8569d0b4af04224ef3b5a Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Wed, 8 Mar 2017 12:41:54 +1100 -Subject: [PATCH 1/7] SECRETS: daemon: allow directory creation in /run/secrets +Subject: [PATCH 1/3] SECRETS: daemon: allow directory creation in /run/secrets Since FileMode can have the directory bit set, allow a SecretStore implementation to return secrets that are actually directories. This is @@ -10,11 +10,11 @@ useful for creating directories and subdirectories of secrets. Signed-off-by: Antonio Murdaca Signed-off-by: Aleksa Sarai --- - daemon/container_operations_unix.go | 24 +++++++++++++++++++++--- - 1 file changed, 21 insertions(+), 3 deletions(-) + daemon/container_operations_unix.go | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go -index 75b4b09b8dc4..583db20aa459 100644 +index 561077b66b60..0b70825dd2ff 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -4,6 +4,7 @@ @@ -23,12 +23,12 @@ index 75b4b09b8dc4..583db20aa459 100644 import ( + "bytes" "fmt" - "io/ioutil" "os" -@@ -13,6 +14,7 @@ import ( - "github.com/docker/docker/container" + "path/filepath" +@@ -14,6 +15,7 @@ import ( "github.com/docker/docker/daemon/links" "github.com/docker/docker/errdefs" + "github.com/docker/docker/libnetwork" + "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/stringid" @@ -37,13 +37,13 @@ index 75b4b09b8dc4..583db20aa459 100644 if err != nil { return errors.Wrap(err, "unable to get secret from secret store") } -- if err := ioutil.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil { +- if err := os.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil { - return errors.Wrap(err, "error injecting secret") - } uid, err := strconv.Atoi(s.File.UID) if err != nil { -@@ -219,6 +218,25 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { +@@ -219,6 +218,24 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { return err } @@ -55,14 +55,13 @@ index 75b4b09b8dc4..583db20aa459 100644 + // If the "file" is a directory, then s.File.Data is actually a tar + // archive of the directory. So we just do a tar extraction here. + if err := archive.UntarUncompressed(bytes.NewBuffer(secret.Spec.Data), fPath, &archive.TarOptions{ -+ UIDMaps: daemon.idMapping.UIDs(), -+ GIDMaps: daemon.idMapping.GIDs(), ++ IDMap: daemon.idMapping, + }); err != nil { + return errors.Wrap(err, "error injecting secretdir") + } + } + } else { -+ if err := ioutil.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil { ++ if err := os.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil { + return errors.Wrap(err, "error injecting secret") + } + } @@ -70,5 +69,5 @@ index 75b4b09b8dc4..583db20aa459 100644 return errors.Wrap(err, "error setting ownership for secret") } -- -2.38.1 +2.40.0 diff --git a/0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch b/0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch index a5680ba..4d4f280 100644 --- a/0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch +++ b/0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch @@ -1,7 +1,7 @@ -From fa24396cbecbb6cdc7c734559389486849c2268c Mon Sep 17 00:00:00 2001 +From 4138c02a19fbd3d3ff50f0b364bf4b99adc47298 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Wed, 8 Mar 2017 11:43:29 +1100 -Subject: [PATCH 2/7] SECRETS: SUSE: implement SUSE container secrets +Subject: [PATCH 2/3] SECRETS: SUSE: implement SUSE container secrets This allows for us to pass in host credentials to a container, allowing for SUSEConnect to work with containers. @@ -14,12 +14,12 @@ SUSE-Bugs: bsc#1065609 bsc#1057743 bsc#1055676 bsc#1030702 Signed-off-by: Aleksa Sarai --- daemon/start.go | 5 + - daemon/suse_secrets.go | 410 +++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 415 insertions(+) + daemon/suse_secrets.go | 415 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 420 insertions(+) create mode 100644 daemon/suse_secrets.go diff --git a/daemon/start.go b/daemon/start.go -index d9bc082b1078..091dae2ae65e 100644 +index 9d6f7812b67c..53c42082c5bf 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -150,6 +150,11 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint @@ -36,10 +36,10 @@ index d9bc082b1078..091dae2ae65e 100644 return errdefs.System(err) diff --git a/daemon/suse_secrets.go b/daemon/suse_secrets.go new file mode 100644 -index 000000000000..9ee33adf7497 +index 000000000000..32b0ece91b59 --- /dev/null +++ b/daemon/suse_secrets.go -@@ -0,0 +1,410 @@ +@@ -0,0 +1,415 @@ +/* + * suse-secrets: patch for Docker to implement SUSE secrets + * Copyright (C) 2017-2021 SUSE LLC. @@ -75,8 +75,8 @@ index 000000000000..9ee33adf7497 + "github.com/docker/docker/pkg/idtools" + + swarmtypes "github.com/docker/docker/api/types/swarm" -+ swarmexec "github.com/docker/swarmkit/agent/exec" -+ swarmapi "github.com/docker/swarmkit/api" ++ swarmexec "github.com/moby/swarmkit/v2/agent/exec" ++ swarmapi "github.com/moby/swarmkit/v2/api" + + "github.com/opencontainers/go-digest" + "github.com/sirupsen/logrus" @@ -113,7 +113,7 @@ index 000000000000..9ee33adf7497 + } +} + -+func (s SuseFakeFile) toSecretReference(idMaps *idtools.IdentityMapping) *swarmtypes.SecretReference { ++func (s SuseFakeFile) toSecretReference(idMaps idtools.IdentityMapping) *swarmtypes.SecretReference { + // Figure out the host-facing {uid,gid} based on the provided maps. Fall + // back to root if the UID/GID don't match (we are guaranteed that root is + // mapped). @@ -345,6 +345,7 @@ index 000000000000..9ee33adf7497 + suseEmptyStore struct{} + suseEmptySecret struct{} + suseEmptyConfig struct{} ++ suseEmptyVolume struct{} +) + +// In order to reduce the amount of code touched outside of this file, we @@ -356,14 +357,17 @@ index 000000000000..9ee33adf7497 + emptyStore swarmexec.DependencyGetter = suseEmptyStore{} + emptySecret swarmexec.SecretGetter = suseEmptySecret{} + emptyConfig swarmexec.ConfigGetter = suseEmptyConfig{} ++ emptyVolume swarmexec.VolumeGetter = suseEmptyVolume{} +) + +var errSuseEmptyStore = fmt.Errorf("SUSE:secrets :: tried to get a resource from empty store [this is a bug]") + +func (_ suseEmptyConfig) Get(_ string) (*swarmapi.Config, error) { return nil, errSuseEmptyStore } +func (_ suseEmptySecret) Get(_ string) (*swarmapi.Secret, error) { return nil, errSuseEmptyStore } ++func (_ suseEmptyVolume) Get(_ string) (string, error) { return "", errSuseEmptyStore } +func (_ suseEmptyStore) Secrets() swarmexec.SecretGetter { return emptySecret } +func (_ suseEmptyStore) Configs() swarmexec.ConfigGetter { return emptyConfig } ++func (_ suseEmptyStore) Volumes() swarmexec.VolumeGetter { return emptyVolume } + +type suseDependencyStore struct { + dfl swarmexec.DependencyGetter @@ -373,6 +377,7 @@ index 000000000000..9ee33adf7497 +// The following are effectively dumb wrappers that return ourselves, or the +// default. +func (s *suseDependencyStore) Secrets() swarmexec.SecretGetter { return s } ++func (s *suseDependencyStore) Volumes() swarmexec.VolumeGetter { return emptyVolume } +func (s *suseDependencyStore) Configs() swarmexec.ConfigGetter { return s.dfl.Configs() } + +// Get overrides the underlying DependencyGetter with our own secrets (falling @@ -451,5 +456,5 @@ index 000000000000..9ee33adf7497 + return nil +} -- -2.38.1 +2.40.0 diff --git a/0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch b/0003-bsc1073877-apparmor-clobber-docker-default-profile-o.patch similarity index 89% rename from 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch rename to 0003-bsc1073877-apparmor-clobber-docker-default-profile-o.patch index ceef77c..6f2d6ca 100644 --- a/0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch +++ b/0003-bsc1073877-apparmor-clobber-docker-default-profile-o.patch @@ -1,7 +1,7 @@ -From bc52d15141402d94eeaee618f1df0b540f527b98 Mon Sep 17 00:00:00 2001 +From 3e37bbad6f0a0c2576ad0b9dfe7a4a9290aa2aa0 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Fri, 29 Jun 2018 17:59:30 +1000 -Subject: [PATCH 4/7] bsc1073877: apparmor: clobber docker-default profile on +Subject: [PATCH 3/3] bsc1073877: apparmor: clobber docker-default profile on start In the process of making docker-default reloading far less expensive, @@ -22,7 +22,7 @@ Signed-off-by: Aleksa Sarai 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/daemon/apparmor_default.go b/daemon/apparmor_default.go -index 21813ec14f8f..0de75b32b7fa 100644 +index 6376001613f7..5fde21a4af8a 100644 --- a/daemon/apparmor_default.go +++ b/daemon/apparmor_default.go @@ -24,6 +24,15 @@ func DefaultApparmorProfile() string { @@ -30,7 +30,7 @@ index 21813ec14f8f..0de75b32b7fa 100644 } +func clobberDefaultAppArmorProfile() error { -+ if apparmor.IsEnabled() { ++ if apparmor.HostSupports() { + if err := aaprofile.InstallDefault(defaultAppArmorProfile); err != nil { + return fmt.Errorf("AppArmor enabled on system but the %s profile could not be loaded: %s", defaultAppArmorProfile, err) + } @@ -39,7 +39,7 @@ index 21813ec14f8f..0de75b32b7fa 100644 +} + func ensureDefaultAppArmorProfile() error { - if apparmor.IsEnabled() { + if apparmor.HostSupports() { loaded, err := aaprofile.IsLoaded(defaultAppArmorProfile) @@ -37,10 +46,7 @@ func ensureDefaultAppArmorProfile() error { } @@ -69,10 +69,10 @@ index e3dc18b32b5e..9c7723056268 100644 return nil } diff --git a/daemon/daemon.go b/daemon/daemon.go -index f15a4b038498..2f0c23bc62c9 100644 +index 40abbe8cc19c..05c6db818c30 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go -@@ -857,8 +857,9 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S +@@ -807,8 +807,9 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S logrus.Warnf("Failed to configure golang's threads limit: %v", err) } @@ -85,5 +85,5 @@ index f15a4b038498..2f0c23bc62c9 100644 } -- -2.38.1 +2.40.0 diff --git a/0005-bsc1183855-btrfs-Do-not-disable-quota-on-cleanup.patch b/0005-bsc1183855-btrfs-Do-not-disable-quota-on-cleanup.patch deleted file mode 100644 index f76db42..0000000 --- a/0005-bsc1183855-btrfs-Do-not-disable-quota-on-cleanup.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 57673ad5455b1b27e41716e33b67c9cd8099b580 Mon Sep 17 00:00:00 2001 -From: Michal Rostecki -Date: Thu, 8 Apr 2021 14:42:02 +0100 -Subject: [PATCH 5/7] bsc1183855: btrfs: Do not disable quota on cleanup - -Before this change, cleanup of the btrfs driver (occuring on each daemon -shutdown) resulted in disabling quotas. It was done with an assumption -that quotas can be enabled or disabled on a subvolume level, which is -not true - enabling or disabling quota is always done on a filesystem -level. - -That was leading to disabling quota on btrfs filesystems on each daemon -shutdown. - -This change fixes that behavior and removes misleading `subvol` prefix -from functions and methods which set up quota (on a filesystem level). - -SUSE-Bugs: bsc#1175081 bsc#1183855 -SUSE-Upstream-Commit: 1ec689c4c2ecda24ed8495451c53072bb0497871 -Fixes: 401c8d176743 ("Add disk quota support for btrfs") -Signed-off-by: Michal Rostecki ---- - daemon/graphdriver/btrfs/btrfs.go | 50 +++++-------------------------- - 1 file changed, 8 insertions(+), 42 deletions(-) - -diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go -index fa0cdf8666b1..02bbb5da1088 100644 ---- a/daemon/graphdriver/btrfs/btrfs.go -+++ b/daemon/graphdriver/btrfs/btrfs.go -@@ -104,7 +104,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap - } - - if userDiskQuota { -- if err := driver.subvolEnableQuota(); err != nil { -+ if err := driver.enableQuota(); err != nil { - return nil, err - } - } -@@ -173,18 +173,10 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) { - - // Cleanup unmounts the home directory. - func (d *Driver) Cleanup() error { -- err := d.subvolDisableQuota() -- umountErr := mount.Unmount(d.home) -- -- // in case we have two errors, prefer the one from disableQuota() -- if err != nil { -+ if err := mount.Unmount(d.home); err != nil { - return err - } - -- if umountErr != nil { -- return umountErr -- } -- - return nil - } - -@@ -342,7 +334,7 @@ func (d *Driver) updateQuotaStatus() { - d.once.Do(func() { - if !d.quotaEnabled { - // In case quotaEnabled is not set, check qgroup and update quotaEnabled as needed -- if err := subvolQgroupStatus(d.home); err != nil { -+ if err := qgroupStatus(d.home); err != nil { - // quota is still not enabled - return - } -@@ -351,7 +343,7 @@ func (d *Driver) updateQuotaStatus() { - }) - } - --func (d *Driver) subvolEnableQuota() error { -+func (d *Driver) enableQuota() error { - d.updateQuotaStatus() - - if d.quotaEnabled { -@@ -377,32 +369,6 @@ func (d *Driver) subvolEnableQuota() error { - return nil - } - --func (d *Driver) subvolDisableQuota() error { -- d.updateQuotaStatus() -- -- if !d.quotaEnabled { -- return nil -- } -- -- dir, err := openDir(d.home) -- if err != nil { -- return err -- } -- defer closeDir(dir) -- -- var args C.struct_btrfs_ioctl_quota_ctl_args -- args.cmd = C.BTRFS_QUOTA_CTL_DISABLE -- _, _, errno := unix.Syscall(unix.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_QUOTA_CTL, -- uintptr(unsafe.Pointer(&args))) -- if errno != 0 { -- return fmt.Errorf("Failed to disable btrfs quota for %s: %v", dir, errno.Error()) -- } -- -- d.quotaEnabled = false -- -- return nil --} -- - func (d *Driver) subvolRescanQuota() error { - d.updateQuotaStatus() - -@@ -445,11 +411,11 @@ func subvolLimitQgroup(path string, size uint64) error { - return nil - } - --// subvolQgroupStatus performs a BTRFS_IOC_TREE_SEARCH on the root path -+// qgroupStatus performs a BTRFS_IOC_TREE_SEARCH on the root path - // with search key of BTRFS_QGROUP_STATUS_KEY. - // In case qgroup is enabled, the retuned key type will match BTRFS_QGROUP_STATUS_KEY. - // For more details please see https://github.com/kdave/btrfs-progs/blob/v4.9/qgroup.c#L1035 --func subvolQgroupStatus(path string) error { -+func qgroupStatus(path string) error { - dir, err := openDir(path) - if err != nil { - return err -@@ -623,7 +589,7 @@ func (d *Driver) setStorageSize(dir string, driver *Driver) error { - if d.options.minSpace > 0 && driver.options.size < d.options.minSpace { - return fmt.Errorf("btrfs: storage size cannot be less than %s", units.HumanSize(float64(d.options.minSpace))) - } -- if err := d.subvolEnableQuota(); err != nil { -+ if err := d.enableQuota(); err != nil { - return err - } - return subvolLimitQgroup(dir, driver.options.size) -@@ -677,7 +643,7 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { - - if quota, err := ioutil.ReadFile(d.quotasDirID(id)); err == nil { - if size, err := strconv.ParseUint(string(quota), 10, 64); err == nil && size >= d.options.minSpace { -- if err := d.subvolEnableQuota(); err != nil { -+ if err := d.enableQuota(); err != nil { - return nil, err - } - if err := subvolLimitQgroup(dir, size); err != nil { --- -2.38.1 - diff --git a/0006-bsc1193930-vendor-update-golang.org-x-crypto.patch b/0006-bsc1193930-vendor-update-golang.org-x-crypto.patch deleted file mode 100644 index 5248319..0000000 --- a/0006-bsc1193930-vendor-update-golang.org-x-crypto.patch +++ /dev/null @@ -1,41072 +0,0 @@ -From dd265ac6cbe070f80a0c607ba147af35858ae5e9 Mon Sep 17 00:00:00 2001 -From: Aleksa Sarai -Date: Fri, 29 Apr 2022 12:44:21 +1000 -Subject: [PATCH 6/7] bsc1193930: vendor: update golang.org/x/crypto - -This is necessary to fix several security issues that Docker hasn't -backported to their CE branch: - - * CVE-2022-27191 - * CVE-2021-43565 - -SUSE-Bugs: bsc#1193930 bsc#1197284 -Signed-off-by: Aleksa Sarai ---- - vendor.conf | 2 +- - vendor/golang.org/x/crypto/README.md | 2 + - vendor/golang.org/x/crypto/acme/acme.go | 805 +++++ - .../x/crypto/acme/autocert/autocert.go | 1193 ++++++++ - .../x/crypto/acme/autocert/cache.go | 136 + - .../acme/autocert/internal/acmetest/ca.go | 762 +++++ - .../x/crypto/acme/autocert/listener.go | 155 + - .../x/crypto/acme/autocert/renewal.go | 156 + - vendor/golang.org/x/crypto/acme/http.go | 325 ++ - .../crypto/acme/internal/acmeprobe/prober.go | 433 +++ - vendor/golang.org/x/crypto/acme/jws.go | 232 ++ - vendor/golang.org/x/crypto/acme/rfc8555.go | 438 +++ - vendor/golang.org/x/crypto/acme/types.go | 614 ++++ - .../golang.org/x/crypto/acme/version_go112.go | 28 + - vendor/golang.org/x/crypto/argon2/argon2.go | 285 ++ - vendor/golang.org/x/crypto/argon2/blake2b.go | 53 + - .../x/crypto/argon2/blamka_amd64.go | 61 + - .../golang.org/x/crypto/argon2/blamka_amd64.s | 244 ++ - .../x/crypto/argon2/blamka_generic.go | 163 + - .../golang.org/x/crypto/argon2/blamka_ref.go | 16 + - vendor/golang.org/x/crypto/bcrypt/base64.go | 35 + - vendor/golang.org/x/crypto/bcrypt/bcrypt.go | 295 ++ - vendor/golang.org/x/crypto/blake2b/blake2b.go | 291 ++ - .../x/crypto/blake2b/blake2bAVX2_amd64.go | 38 + - .../x/crypto/blake2b/blake2bAVX2_amd64.s | 745 +++++ - .../x/crypto/blake2b/blake2b_amd64.go | 25 + - .../x/crypto/blake2b/blake2b_amd64.s | 279 ++ - .../x/crypto/blake2b/blake2b_generic.go | 182 ++ - .../x/crypto/blake2b/blake2b_ref.go | 12 + - vendor/golang.org/x/crypto/blake2b/blake2x.go | 177 ++ - .../golang.org/x/crypto/blake2b/register.go | 33 + - vendor/golang.org/x/crypto/blake2s/blake2s.go | 246 ++ - .../x/crypto/blake2s/blake2s_386.go | 33 + - .../golang.org/x/crypto/blake2s/blake2s_386.s | 430 +++ - .../x/crypto/blake2s/blake2s_amd64.go | 38 + - .../x/crypto/blake2s/blake2s_amd64.s | 433 +++ - .../x/crypto/blake2s/blake2s_generic.go | 178 ++ - .../x/crypto/blake2s/blake2s_ref.go | 18 + - vendor/golang.org/x/crypto/blake2s/blake2x.go | 178 ++ - .../golang.org/x/crypto/blake2s/register.go | 22 + - vendor/golang.org/x/crypto/bn256/bn256.go | 429 +++ - vendor/golang.org/x/crypto/bn256/constants.go | 44 + - vendor/golang.org/x/crypto/bn256/curve.go | 287 ++ - vendor/golang.org/x/crypto/bn256/gfp12.go | 200 ++ - vendor/golang.org/x/crypto/bn256/gfp2.go | 219 ++ - vendor/golang.org/x/crypto/bn256/gfp6.go | 296 ++ - vendor/golang.org/x/crypto/bn256/optate.go | 395 +++ - vendor/golang.org/x/crypto/bn256/twist.go | 258 ++ - vendor/golang.org/x/crypto/cast5/cast5.go | 533 ++++ - .../x/crypto/chacha20/chacha_arm64.go | 3 +- - .../x/crypto/chacha20/chacha_arm64.s | 3 +- - .../x/crypto/chacha20/chacha_noasm.go | 3 +- - .../x/crypto/chacha20/chacha_ppc64le.go | 3 +- - .../x/crypto/chacha20/chacha_ppc64le.s | 3 +- - .../x/crypto/chacha20/chacha_s390x.go | 3 +- - .../x/crypto/chacha20/chacha_s390x.s | 3 +- - .../chacha20poly1305/chacha20poly1305.go | 98 + - .../chacha20poly1305_amd64.go | 87 + - .../chacha20poly1305/chacha20poly1305_amd64.s | 2696 +++++++++++++++++ - .../chacha20poly1305_generic.go | 81 + - .../chacha20poly1305_noasm.go | 16 + - .../chacha20poly1305/xchacha20poly1305.go | 86 + - vendor/golang.org/x/crypto/codereview.cfg | 1 + - vendor/golang.org/x/crypto/cryptobyte/asn1.go | 59 +- - .../x/crypto/curve25519/curve25519.go | 52 +- - .../x/crypto/curve25519/curve25519_amd64.go | 240 -- - .../x/crypto/curve25519/curve25519_amd64.s | 1793 ----------- - .../x/crypto/curve25519/curve25519_generic.go | 828 ----- - .../x/crypto/curve25519/curve25519_noasm.go | 11 - - .../x/crypto/curve25519/internal/field/README | 7 + - .../internal/field/_asm/fe_amd64_asm.go | 298 ++ - .../curve25519/internal/field/_asm/go.mod | 10 + - .../curve25519/internal/field/_asm/go.sum | 34 + - .../x/crypto/curve25519/internal/field/fe.go | 416 +++ - .../curve25519/internal/field/fe_amd64.go | 13 + - .../curve25519/internal/field/fe_amd64.s | 379 +++ - .../internal/field/fe_amd64_noasm.go | 12 + - .../curve25519/internal/field/fe_arm64.go | 16 + - .../curve25519/internal/field/fe_arm64.s | 43 + - .../internal/field/fe_arm64_noasm.go | 12 + - .../curve25519/internal/field/fe_generic.go | 264 ++ - .../curve25519/internal/field/sync.checkpoint | 1 + - .../crypto/curve25519/internal/field/sync.sh | 19 + - vendor/golang.org/x/crypto/ed25519/ed25519.go | 187 +- - .../x/crypto/ed25519/ed25519_go113.go | 73 - - .../ed25519/internal/edwards25519/const.go | 1422 --------- - .../internal/edwards25519/edwards25519.go | 1793 ----------- - vendor/golang.org/x/crypto/go.mod | 10 +- - vendor/golang.org/x/crypto/go.sum | 11 + - vendor/golang.org/x/crypto/hkdf/hkdf.go | 93 + - .../{ => internal}/poly1305/bits_compat.go | 1 + - .../{ => internal}/poly1305/bits_go1.13.go | 1 + - .../{ => internal}/poly1305/mac_noasm.go | 3 +- - .../{ => internal}/poly1305/poly1305.go | 2 +- - .../{ => internal}/poly1305/sum_amd64.go | 3 +- - .../{ => internal}/poly1305/sum_amd64.s | 3 +- - .../{ => internal}/poly1305/sum_generic.go | 0 - .../{ => internal}/poly1305/sum_ppc64le.go | 3 +- - .../{ => internal}/poly1305/sum_ppc64le.s | 21 +- - .../{ => internal}/poly1305/sum_s390x.go | 3 +- - .../{ => internal}/poly1305/sum_s390x.s | 5 +- - .../x/crypto/internal/subtle/aliasing.go | 3 +- - ...iasing_appengine.go => aliasing_purego.go} | 3 +- - .../x/crypto/internal/wycheproof/README.md | 12 + - .../internal/wycheproof/internal/dsa/dsa.go | 33 + - vendor/golang.org/x/crypto/md4/md4.go | 122 + - vendor/golang.org/x/crypto/md4/md4block.go | 89 + - vendor/golang.org/x/crypto/nacl/auth/auth.go | 58 + - vendor/golang.org/x/crypto/nacl/box/box.go | 182 ++ - .../x/crypto/nacl/secretbox/secretbox.go | 2 +- - vendor/golang.org/x/crypto/ocsp/ocsp.go | 2 +- - .../x/crypto/openpgp/armor/armor.go | 230 ++ - .../x/crypto/openpgp/armor/encode.go | 160 + - .../x/crypto/openpgp/canonical_text.go | 59 + - .../x/crypto/openpgp/clearsign/clearsign.go | 424 +++ - .../x/crypto/openpgp/elgamal/elgamal.go | 130 + - .../x/crypto/openpgp/errors/errors.go | 78 + - vendor/golang.org/x/crypto/openpgp/keys.go | 693 +++++ - .../x/crypto/openpgp/packet/compressed.go | 123 + - .../x/crypto/openpgp/packet/config.go | 91 + - .../x/crypto/openpgp/packet/encrypted_key.go | 208 ++ - .../x/crypto/openpgp/packet/literal.go | 89 + - .../x/crypto/openpgp/packet/ocfb.go | 143 + - .../openpgp/packet/one_pass_signature.go | 73 + - .../x/crypto/openpgp/packet/opaque.go | 162 + - .../x/crypto/openpgp/packet/packet.go | 590 ++++ - .../x/crypto/openpgp/packet/private_key.go | 385 +++ - .../x/crypto/openpgp/packet/public_key.go | 753 +++++ - .../x/crypto/openpgp/packet/public_key_v3.go | 279 ++ - .../x/crypto/openpgp/packet/reader.go | 76 + - .../x/crypto/openpgp/packet/signature.go | 731 +++++ - .../x/crypto/openpgp/packet/signature_v3.go | 146 + - .../openpgp/packet/symmetric_key_encrypted.go | 155 + - .../openpgp/packet/symmetrically_encrypted.go | 290 ++ - .../x/crypto/openpgp/packet/userattribute.go | 91 + - .../x/crypto/openpgp/packet/userid.go | 160 + - vendor/golang.org/x/crypto/openpgp/read.go | 448 +++ - vendor/golang.org/x/crypto/openpgp/s2k/s2k.go | 279 ++ - vendor/golang.org/x/crypto/openpgp/write.go | 418 +++ - .../x/crypto/poly1305/poly1305_compat.go | 91 + - .../x/crypto/ripemd160/ripemd160.go | 124 + - .../x/crypto/ripemd160/ripemd160block.go | 165 + - .../x/crypto/salsa20/salsa/salsa20_amd64.go | 3 +- - .../x/crypto/salsa20/salsa/salsa20_amd64.s | 238 +- - .../x/crypto/salsa20/salsa/salsa20_noasm.go | 3 +- - vendor/golang.org/x/crypto/salsa20/salsa20.go | 58 + - vendor/golang.org/x/crypto/scrypt/scrypt.go | 212 ++ - vendor/golang.org/x/crypto/sha3/doc.go | 66 + - vendor/golang.org/x/crypto/sha3/hashes.go | 97 + - .../x/crypto/sha3/hashes_generic.go | 28 + - vendor/golang.org/x/crypto/sha3/keccakf.go | 413 +++ - .../golang.org/x/crypto/sha3/keccakf_amd64.go | 14 + - .../golang.org/x/crypto/sha3/keccakf_amd64.s | 391 +++ - vendor/golang.org/x/crypto/sha3/register.go | 19 + - vendor/golang.org/x/crypto/sha3/sha3.go | 193 ++ - vendor/golang.org/x/crypto/sha3/sha3_s390x.go | 285 ++ - vendor/golang.org/x/crypto/sha3/sha3_s390x.s | 34 + - vendor/golang.org/x/crypto/sha3/shake.go | 173 ++ - .../golang.org/x/crypto/sha3/shake_generic.go | 20 + - vendor/golang.org/x/crypto/sha3/xor.go | 24 + - .../golang.org/x/crypto/sha3/xor_generic.go | 28 + - .../golang.org/x/crypto/sha3/xor_unaligned.go | 68 + - .../golang.org/x/crypto/ssh/agent/client.go | 819 +++++ - .../golang.org/x/crypto/ssh/agent/forward.go | 103 + - .../golang.org/x/crypto/ssh/agent/keyring.go | 241 ++ - .../golang.org/x/crypto/ssh/agent/server.go | 570 ++++ - vendor/golang.org/x/crypto/ssh/certs.go | 85 +- - vendor/golang.org/x/crypto/ssh/cipher.go | 10 +- - vendor/golang.org/x/crypto/ssh/client.go | 20 +- - vendor/golang.org/x/crypto/ssh/client_auth.go | 132 +- - vendor/golang.org/x/crypto/ssh/common.go | 76 +- - vendor/golang.org/x/crypto/ssh/handshake.go | 81 +- - vendor/golang.org/x/crypto/ssh/kex.go | 186 +- - vendor/golang.org/x/crypto/ssh/keys.go | 147 +- - .../x/crypto/ssh/knownhosts/knownhosts.go | 540 ++++ - vendor/golang.org/x/crypto/ssh/messages.go | 21 +- - vendor/golang.org/x/crypto/ssh/server.go | 50 +- - vendor/golang.org/x/crypto/ssh/session.go | 1 + - .../x/crypto/ssh/terminal/terminal.go | 76 + - vendor/golang.org/x/crypto/ssh/transport.go | 10 +- - vendor/golang.org/x/crypto/tea/cipher.go | 116 + - vendor/golang.org/x/crypto/twofish/twofish.go | 348 +++ - vendor/golang.org/x/crypto/xtea/block.go | 66 + - vendor/golang.org/x/crypto/xtea/cipher.go | 90 + - vendor/golang.org/x/crypto/xts/xts.go | 164 + - 185 files changed, 31569 insertions(+), 6779 deletions(-) - create mode 100644 vendor/golang.org/x/crypto/acme/acme.go - create mode 100644 vendor/golang.org/x/crypto/acme/autocert/autocert.go - create mode 100644 vendor/golang.org/x/crypto/acme/autocert/cache.go - create mode 100644 vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go - create mode 100644 vendor/golang.org/x/crypto/acme/autocert/listener.go - create mode 100644 vendor/golang.org/x/crypto/acme/autocert/renewal.go - create mode 100644 vendor/golang.org/x/crypto/acme/http.go - create mode 100644 vendor/golang.org/x/crypto/acme/internal/acmeprobe/prober.go - create mode 100644 vendor/golang.org/x/crypto/acme/jws.go - create mode 100644 vendor/golang.org/x/crypto/acme/rfc8555.go - create mode 100644 vendor/golang.org/x/crypto/acme/types.go - create mode 100644 vendor/golang.org/x/crypto/acme/version_go112.go - create mode 100644 vendor/golang.org/x/crypto/argon2/argon2.go - create mode 100644 vendor/golang.org/x/crypto/argon2/blake2b.go - create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_amd64.go - create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_amd64.s - create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_generic.go - create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_ref.go - create mode 100644 vendor/golang.org/x/crypto/bcrypt/base64.go - create mode 100644 vendor/golang.org/x/crypto/bcrypt/bcrypt.go - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b.go - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_generic.go - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_ref.go - create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2x.go - create mode 100644 vendor/golang.org/x/crypto/blake2b/register.go - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2s.go - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2s_386.go - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2s_386.s - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2s_generic.go - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2s_ref.go - create mode 100644 vendor/golang.org/x/crypto/blake2s/blake2x.go - create mode 100644 vendor/golang.org/x/crypto/blake2s/register.go - create mode 100644 vendor/golang.org/x/crypto/bn256/bn256.go - create mode 100644 vendor/golang.org/x/crypto/bn256/constants.go - create mode 100644 vendor/golang.org/x/crypto/bn256/curve.go - create mode 100644 vendor/golang.org/x/crypto/bn256/gfp12.go - create mode 100644 vendor/golang.org/x/crypto/bn256/gfp2.go - create mode 100644 vendor/golang.org/x/crypto/bn256/gfp6.go - create mode 100644 vendor/golang.org/x/crypto/bn256/optate.go - create mode 100644 vendor/golang.org/x/crypto/bn256/twist.go - create mode 100644 vendor/golang.org/x/crypto/cast5/cast5.go - create mode 100644 vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go - create mode 100644 vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go - create mode 100644 vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s - create mode 100644 vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go - create mode 100644 vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go - create mode 100644 vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go - create mode 100644 vendor/golang.org/x/crypto/codereview.cfg - delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go - delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s - delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_generic.go - delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/README - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go - create mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint - create mode 100755 vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh - delete mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519_go113.go - delete mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go - delete mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go - create mode 100644 vendor/golang.org/x/crypto/go.sum - create mode 100644 vendor/golang.org/x/crypto/hkdf/hkdf.go - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/bits_compat.go (98%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/bits_go1.13.go (96%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/mac_noasm.go (66%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/poly1305.go (98%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_amd64.go (95%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_amd64.s (98%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_generic.go (100%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_ppc64le.go (95%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_ppc64le.s (94%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_s390x.go (97%) - rename vendor/golang.org/x/crypto/{ => internal}/poly1305/sum_s390x.s (99%) - rename vendor/golang.org/x/crypto/internal/subtle/{aliasing_appengine.go => aliasing_purego.go} (97%) - create mode 100644 vendor/golang.org/x/crypto/internal/wycheproof/README.md - create mode 100644 vendor/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go - create mode 100644 vendor/golang.org/x/crypto/md4/md4.go - create mode 100644 vendor/golang.org/x/crypto/md4/md4block.go - create mode 100644 vendor/golang.org/x/crypto/nacl/auth/auth.go - create mode 100644 vendor/golang.org/x/crypto/nacl/box/box.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/armor/armor.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/armor/encode.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/canonical_text.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/errors/errors.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/keys.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/compressed.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/config.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/literal.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/ocfb.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/opaque.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/packet.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/private_key.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/reader.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userattribute.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/packet/userid.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/read.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/s2k/s2k.go - create mode 100644 vendor/golang.org/x/crypto/openpgp/write.go - create mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305_compat.go - create mode 100644 vendor/golang.org/x/crypto/ripemd160/ripemd160.go - create mode 100644 vendor/golang.org/x/crypto/ripemd160/ripemd160block.go - create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa20.go - create mode 100644 vendor/golang.org/x/crypto/scrypt/scrypt.go - create mode 100644 vendor/golang.org/x/crypto/sha3/doc.go - create mode 100644 vendor/golang.org/x/crypto/sha3/hashes.go - create mode 100644 vendor/golang.org/x/crypto/sha3/hashes_generic.go - create mode 100644 vendor/golang.org/x/crypto/sha3/keccakf.go - create mode 100644 vendor/golang.org/x/crypto/sha3/keccakf_amd64.go - create mode 100644 vendor/golang.org/x/crypto/sha3/keccakf_amd64.s - create mode 100644 vendor/golang.org/x/crypto/sha3/register.go - create mode 100644 vendor/golang.org/x/crypto/sha3/sha3.go - create mode 100644 vendor/golang.org/x/crypto/sha3/sha3_s390x.go - create mode 100644 vendor/golang.org/x/crypto/sha3/sha3_s390x.s - create mode 100644 vendor/golang.org/x/crypto/sha3/shake.go - create mode 100644 vendor/golang.org/x/crypto/sha3/shake_generic.go - create mode 100644 vendor/golang.org/x/crypto/sha3/xor.go - create mode 100644 vendor/golang.org/x/crypto/sha3/xor_generic.go - create mode 100644 vendor/golang.org/x/crypto/sha3/xor_unaligned.go - create mode 100644 vendor/golang.org/x/crypto/ssh/agent/client.go - create mode 100644 vendor/golang.org/x/crypto/ssh/agent/forward.go - create mode 100644 vendor/golang.org/x/crypto/ssh/agent/keyring.go - create mode 100644 vendor/golang.org/x/crypto/ssh/agent/server.go - create mode 100644 vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go - create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/terminal.go - create mode 100644 vendor/golang.org/x/crypto/tea/cipher.go - create mode 100644 vendor/golang.org/x/crypto/twofish/twofish.go - create mode 100644 vendor/golang.org/x/crypto/xtea/block.go - create mode 100644 vendor/golang.org/x/crypto/xtea/cipher.go - create mode 100644 vendor/golang.org/x/crypto/xts/xts.go - -diff --git a/vendor.conf b/vendor.conf -index a41471b57b71..2965c71c3709 100644 ---- a/vendor.conf -+++ b/vendor.conf -@@ -152,7 +152,7 @@ github.com/golang/protobuf 84668698ea25b64748563aa20726 - github.com/cloudflare/cfssl 5d63dbd981b5c408effbb58c442d54761ff94fbd # 1.3.2 - github.com/fernet/fernet-go 9eac43b88a5efb8651d24de9b68e87567e029736 - github.com/google/certificate-transparency-go 37a384cd035e722ea46e55029093e26687138edf # v1.0.20 --golang.org/x/crypto c1f2f97bffc9c53fc40a1a28a5b460094c0050d9 -+golang.org/x/crypto 3147a52a75dda54ac3a611ef8978640d85188a2a - golang.org/x/time 555d28b269f0569763d25dbe1a237ae74c6bcc82 - github.com/hashicorp/go-memdb cb9a474f84cc5e41b273b20c6927680b2a8776ad - github.com/hashicorp/go-immutable-radix 826af9ccf0feeee615d546d69b11f8e98da8c8f1 https://github.com/tonistiigi/go-immutable-radix.git -diff --git a/vendor/golang.org/x/crypto/README.md b/vendor/golang.org/x/crypto/README.md -index c9d6fecd1e5f..92f73cdfbfee 100644 ---- a/vendor/golang.org/x/crypto/README.md -+++ b/vendor/golang.org/x/crypto/README.md -@@ -1,5 +1,7 @@ - # Go Cryptography - -+[![Go Reference](https://pkg.go.dev/badge/golang.org/x/crypto.svg)](https://pkg.go.dev/golang.org/x/crypto) -+ - This repository holds supplementary Go cryptography libraries. - - ## Download/Install -diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go -new file mode 100644 -index 000000000000..f2d23f697687 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/acme.go -@@ -0,0 +1,805 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package acme provides an implementation of the -+// Automatic Certificate Management Environment (ACME) spec, -+// most famously used by Let's Encrypt. -+// -+// The initial implementation of this package was based on an early version -+// of the spec. The current implementation supports only the modern -+// RFC 8555 but some of the old API surface remains for compatibility. -+// While code using the old API will still compile, it will return an error. -+// Note the deprecation comments to update your code. -+// -+// See https://tools.ietf.org/html/rfc8555 for the spec. -+// -+// Most common scenarios will want to use autocert subdirectory instead, -+// which provides automatic access to certificates from Let's Encrypt -+// and any other ACME-based CA. -+package acme -+ -+import ( -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/sha256" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/base64" -+ "encoding/hex" -+ "encoding/json" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "math/big" -+ "net/http" -+ "strings" -+ "sync" -+ "time" -+) -+ -+const ( -+ // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. -+ LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory" -+ -+ // ALPNProto is the ALPN protocol name used by a CA server when validating -+ // tls-alpn-01 challenges. -+ // -+ // Package users must ensure their servers can negotiate the ACME ALPN in -+ // order for tls-alpn-01 challenge verifications to succeed. -+ // See the crypto/tls package's Config.NextProtos field. -+ ALPNProto = "acme-tls/1" -+) -+ -+// idPeACMEIdentifier is the OID for the ACME extension for the TLS-ALPN challenge. -+// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-5.1 -+var idPeACMEIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} -+ -+const ( -+ maxChainLen = 5 // max depth and breadth of a certificate chain -+ maxCertSize = 1 << 20 // max size of a certificate, in DER bytes -+ // Used for decoding certs from application/pem-certificate-chain response, -+ // the default when in RFC mode. -+ maxCertChainSize = maxCertSize * maxChainLen -+ -+ // Max number of collected nonces kept in memory. -+ // Expect usual peak of 1 or 2. -+ maxNonces = 100 -+) -+ -+// Client is an ACME client. -+// -+// The only required field is Key. An example of creating a client with a new key -+// is as follows: -+// -+// key, err := rsa.GenerateKey(rand.Reader, 2048) -+// if err != nil { -+// log.Fatal(err) -+// } -+// client := &Client{Key: key} -+// -+type Client struct { -+ // Key is the account key used to register with a CA and sign requests. -+ // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey. -+ // -+ // The following algorithms are supported: -+ // RS256, ES256, ES384 and ES512. -+ // See RFC7518 for more details about the algorithms. -+ Key crypto.Signer -+ -+ // HTTPClient optionally specifies an HTTP client to use -+ // instead of http.DefaultClient. -+ HTTPClient *http.Client -+ -+ // DirectoryURL points to the CA directory endpoint. -+ // If empty, LetsEncryptURL is used. -+ // Mutating this value after a successful call of Client's Discover method -+ // will have no effect. -+ DirectoryURL string -+ -+ // RetryBackoff computes the duration after which the nth retry of a failed request -+ // should occur. The value of n for the first call on failure is 1. -+ // The values of r and resp are the request and response of the last failed attempt. -+ // If the returned value is negative or zero, no more retries are done and an error -+ // is returned to the caller of the original method. -+ // -+ // Requests which result in a 4xx client error are not retried, -+ // except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests. -+ // -+ // If RetryBackoff is nil, a truncated exponential backoff algorithm -+ // with the ceiling of 10 seconds is used, where each subsequent retry n -+ // is done after either ("Retry-After" + jitter) or (2^n seconds + jitter), -+ // preferring the former if "Retry-After" header is found in the resp. -+ // The jitter is a random value up to 1 second. -+ RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration -+ -+ // UserAgent is prepended to the User-Agent header sent to the ACME server, -+ // which by default is this package's name and version. -+ // -+ // Reusable libraries and tools in particular should set this value to be -+ // identifiable by the server, in case they are causing issues. -+ UserAgent string -+ -+ cacheMu sync.Mutex -+ dir *Directory // cached result of Client's Discover method -+ // KID is the key identifier provided by the CA. If not provided it will be -+ // retrieved from the CA by making a call to the registration endpoint. -+ KID KeyID -+ -+ noncesMu sync.Mutex -+ nonces map[string]struct{} // nonces collected from previous responses -+} -+ -+// accountKID returns a key ID associated with c.Key, the account identity -+// provided by the CA during RFC based registration. -+// It assumes c.Discover has already been called. -+// -+// accountKID requires at most one network roundtrip. -+// It caches only successful result. -+// -+// When in pre-RFC mode or when c.getRegRFC responds with an error, accountKID -+// returns noKeyID. -+func (c *Client) accountKID(ctx context.Context) KeyID { -+ c.cacheMu.Lock() -+ defer c.cacheMu.Unlock() -+ if c.KID != noKeyID { -+ return c.KID -+ } -+ a, err := c.getRegRFC(ctx) -+ if err != nil { -+ return noKeyID -+ } -+ c.KID = KeyID(a.URI) -+ return c.KID -+} -+ -+var errPreRFC = errors.New("acme: server does not support the RFC 8555 version of ACME") -+ -+// Discover performs ACME server discovery using c.DirectoryURL. -+// -+// It caches successful result. So, subsequent calls will not result in -+// a network round-trip. This also means mutating c.DirectoryURL after successful call -+// of this method will have no effect. -+func (c *Client) Discover(ctx context.Context) (Directory, error) { -+ c.cacheMu.Lock() -+ defer c.cacheMu.Unlock() -+ if c.dir != nil { -+ return *c.dir, nil -+ } -+ -+ res, err := c.get(ctx, c.directoryURL(), wantStatus(http.StatusOK)) -+ if err != nil { -+ return Directory{}, err -+ } -+ defer res.Body.Close() -+ c.addNonce(res.Header) -+ -+ var v struct { -+ Reg string `json:"newAccount"` -+ Authz string `json:"newAuthz"` -+ Order string `json:"newOrder"` -+ Revoke string `json:"revokeCert"` -+ Nonce string `json:"newNonce"` -+ KeyChange string `json:"keyChange"` -+ Meta struct { -+ Terms string `json:"termsOfService"` -+ Website string `json:"website"` -+ CAA []string `json:"caaIdentities"` -+ ExternalAcct bool `json:"externalAccountRequired"` -+ } -+ } -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return Directory{}, err -+ } -+ if v.Order == "" { -+ return Directory{}, errPreRFC -+ } -+ c.dir = &Directory{ -+ RegURL: v.Reg, -+ AuthzURL: v.Authz, -+ OrderURL: v.Order, -+ RevokeURL: v.Revoke, -+ NonceURL: v.Nonce, -+ KeyChangeURL: v.KeyChange, -+ Terms: v.Meta.Terms, -+ Website: v.Meta.Website, -+ CAA: v.Meta.CAA, -+ ExternalAccountRequired: v.Meta.ExternalAcct, -+ } -+ return *c.dir, nil -+} -+ -+func (c *Client) directoryURL() string { -+ if c.DirectoryURL != "" { -+ return c.DirectoryURL -+ } -+ return LetsEncryptURL -+} -+ -+// CreateCert was part of the old version of ACME. It is incompatible with RFC 8555. -+// -+// Deprecated: this was for the pre-RFC 8555 version of ACME. Callers should use CreateOrderCert. -+func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) { -+ return nil, "", errPreRFC -+} -+ -+// FetchCert retrieves already issued certificate from the given url, in DER format. -+// It retries the request until the certificate is successfully retrieved, -+// context is cancelled by the caller or an error response is received. -+// -+// If the bundle argument is true, the returned value also contains the CA (issuer) -+// certificate chain. -+// -+// FetchCert returns an error if the CA's response or chain was unreasonably large. -+// Callers are encouraged to parse the returned value to ensure the certificate is valid -+// and has expected features. -+func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.fetchCertRFC(ctx, url, bundle) -+} -+ -+// RevokeCert revokes a previously issued certificate cert, provided in DER format. -+// -+// The key argument, used to sign the request, must be authorized -+// to revoke the certificate. It's up to the CA to decide which keys are authorized. -+// For instance, the key pair of the certificate may be authorized. -+// If the key is nil, c.Key is used instead. -+func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { -+ if _, err := c.Discover(ctx); err != nil { -+ return err -+ } -+ return c.revokeCertRFC(ctx, key, cert, reason) -+} -+ -+// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service -+// during account registration. See Register method of Client for more details. -+func AcceptTOS(tosURL string) bool { return true } -+ -+// Register creates a new account with the CA using c.Key. -+// It returns the registered account. The account acct is not modified. -+// -+// The registration may require the caller to agree to the CA's Terms of Service (TOS). -+// If so, and the account has not indicated the acceptance of the terms (see Account for details), -+// Register calls prompt with a TOS URL provided by the CA. Prompt should report -+// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS. -+// -+// When interfacing with an RFC-compliant CA, non-RFC 8555 fields of acct are ignored -+// and prompt is called if Directory's Terms field is non-zero. -+// Also see Error's Instance field for when a CA requires already registered accounts to agree -+// to an updated Terms of Service. -+func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { -+ if c.Key == nil { -+ return nil, errors.New("acme: client.Key must be set to Register") -+ } -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.registerRFC(ctx, acct, prompt) -+} -+ -+// GetReg retrieves an existing account associated with c.Key. -+// -+// The url argument is a legacy artifact of the pre-RFC 8555 API -+// and is ignored. -+func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.getRegRFC(ctx) -+} -+ -+// UpdateReg updates an existing registration. -+// It returns an updated account copy. The provided account is not modified. -+// -+// The account's URI is ignored and the account URL associated with -+// c.Key is used instead. -+func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.updateRegRFC(ctx, acct) -+} -+ -+// Authorize performs the initial step in the pre-authorization flow, -+// as opposed to order-based flow. -+// The caller will then need to choose from and perform a set of returned -+// challenges using c.Accept in order to successfully complete authorization. -+// -+// Once complete, the caller can use AuthorizeOrder which the CA -+// should provision with the already satisfied authorization. -+// For pre-RFC CAs, the caller can proceed directly to requesting a certificate -+// using CreateCert method. -+// -+// If an authorization has been previously granted, the CA may return -+// a valid authorization which has its Status field set to StatusValid. -+// -+// More about pre-authorization can be found at -+// https://tools.ietf.org/html/rfc8555#section-7.4.1. -+func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) { -+ return c.authorize(ctx, "dns", domain) -+} -+ -+// AuthorizeIP is the same as Authorize but requests IP address authorization. -+// Clients which successfully obtain such authorization may request to issue -+// a certificate for IP addresses. -+// -+// See the ACME spec extension for more details about IP address identifiers: -+// https://tools.ietf.org/html/draft-ietf-acme-ip. -+func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error) { -+ return c.authorize(ctx, "ip", ipaddr) -+} -+ -+func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ type authzID struct { -+ Type string `json:"type"` -+ Value string `json:"value"` -+ } -+ req := struct { -+ Resource string `json:"resource"` -+ Identifier authzID `json:"identifier"` -+ }{ -+ Resource: "new-authz", -+ Identifier: authzID{Type: typ, Value: val}, -+ } -+ res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ var v wireAuthz -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ if v.Status != StatusPending && v.Status != StatusValid { -+ return nil, fmt.Errorf("acme: unexpected status: %s", v.Status) -+ } -+ return v.authorization(res.Header.Get("Location")), nil -+} -+ -+// GetAuthorization retrieves an authorization identified by the given URL. -+// -+// If a caller needs to poll an authorization until its status is final, -+// see the WaitAuthorization method. -+func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ var v wireAuthz -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ return v.authorization(url), nil -+} -+ -+// RevokeAuthorization relinquishes an existing authorization identified -+// by the given URL. -+// The url argument is an Authorization.URI value. -+// -+// If successful, the caller will be required to obtain a new authorization -+// using the Authorize or AuthorizeOrder methods before being able to request -+// a new certificate for the domain associated with the authorization. -+// -+// It does not revoke existing certificates. -+func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { -+ if _, err := c.Discover(ctx); err != nil { -+ return err -+ } -+ -+ req := struct { -+ Resource string `json:"resource"` -+ Status string `json:"status"` -+ Delete bool `json:"delete"` -+ }{ -+ Resource: "authz", -+ Status: "deactivated", -+ Delete: true, -+ } -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return err -+ } -+ defer res.Body.Close() -+ return nil -+} -+ -+// WaitAuthorization polls an authorization at the given URL -+// until it is in one of the final states, StatusValid or StatusInvalid, -+// the ACME CA responded with a 4xx error code, or the context is done. -+// -+// It returns a non-nil Authorization only if its Status is StatusValid. -+// In all other cases WaitAuthorization returns an error. -+// If the Status is StatusInvalid, the returned error is of type *AuthorizationError. -+func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ for { -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) -+ if err != nil { -+ return nil, err -+ } -+ -+ var raw wireAuthz -+ err = json.NewDecoder(res.Body).Decode(&raw) -+ res.Body.Close() -+ switch { -+ case err != nil: -+ // Skip and retry. -+ case raw.Status == StatusValid: -+ return raw.authorization(url), nil -+ case raw.Status == StatusInvalid: -+ return nil, raw.error(url) -+ } -+ -+ // Exponential backoff is implemented in c.get above. -+ // This is just to prevent continuously hitting the CA -+ // while waiting for a final authorization status. -+ d := retryAfter(res.Header.Get("Retry-After")) -+ if d == 0 { -+ // Given that the fastest challenges TLS-SNI and HTTP-01 -+ // require a CA to make at least 1 network round trip -+ // and most likely persist a challenge state, -+ // this default delay seems reasonable. -+ d = time.Second -+ } -+ t := time.NewTimer(d) -+ select { -+ case <-ctx.Done(): -+ t.Stop() -+ return nil, ctx.Err() -+ case <-t.C: -+ // Retry. -+ } -+ } -+} -+ -+// GetChallenge retrieves the current status of an challenge. -+// -+// A client typically polls a challenge status using this method. -+func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) -+ if err != nil { -+ return nil, err -+ } -+ -+ defer res.Body.Close() -+ v := wireChallenge{URI: url} -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ return v.challenge(), nil -+} -+ -+// Accept informs the server that the client accepts one of its challenges -+// previously obtained with c.Authorize. -+// -+// The server will then perform the validation asynchronously. -+func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.post(ctx, nil, chal.URI, json.RawMessage("{}"), wantStatus( -+ http.StatusOK, // according to the spec -+ http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md) -+ )) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ var v wireChallenge -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ return v.challenge(), nil -+} -+ -+// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response. -+// A TXT record containing the returned value must be provisioned under -+// "_acme-challenge" name of the domain being validated. -+// -+// The token argument is a Challenge.Token value. -+func (c *Client) DNS01ChallengeRecord(token string) (string, error) { -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return "", err -+ } -+ b := sha256.Sum256([]byte(ka)) -+ return base64.RawURLEncoding.EncodeToString(b[:]), nil -+} -+ -+// HTTP01ChallengeResponse returns the response for an http-01 challenge. -+// Servers should respond with the value to HTTP requests at the URL path -+// provided by HTTP01ChallengePath to validate the challenge and prove control -+// over a domain name. -+// -+// The token argument is a Challenge.Token value. -+func (c *Client) HTTP01ChallengeResponse(token string) (string, error) { -+ return keyAuth(c.Key.Public(), token) -+} -+ -+// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge -+// should be provided by the servers. -+// The response value can be obtained with HTTP01ChallengeResponse. -+// -+// The token argument is a Challenge.Token value. -+func (c *Client) HTTP01ChallengePath(token string) string { -+ return "/.well-known/acme-challenge/" + token -+} -+ -+// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response. -+// -+// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec. -+func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ b := sha256.Sum256([]byte(ka)) -+ h := hex.EncodeToString(b[:]) -+ name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:]) -+ cert, err = tlsChallengeCert([]string{name}, opt) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ return cert, name, nil -+} -+ -+// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response. -+// -+// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec. -+func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { -+ b := sha256.Sum256([]byte(token)) -+ h := hex.EncodeToString(b[:]) -+ sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:]) -+ -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ b = sha256.Sum256([]byte(ka)) -+ h = hex.EncodeToString(b[:]) -+ sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:]) -+ -+ cert, err = tlsChallengeCert([]string{sanA, sanB}, opt) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ return cert, sanA, nil -+} -+ -+// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response. -+// Servers can present the certificate to validate the challenge and prove control -+// over a domain name. For more details on TLS-ALPN-01 see -+// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3 -+// -+// The token argument is a Challenge.Token value. -+// If a WithKey option is provided, its private part signs the returned cert, -+// and the public part is used to specify the signee. -+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. -+// -+// The returned certificate is valid for the next 24 hours and must be presented only when -+// the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol -+// has been specified. -+func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) { -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return tls.Certificate{}, err -+ } -+ shasum := sha256.Sum256([]byte(ka)) -+ extValue, err := asn1.Marshal(shasum[:]) -+ if err != nil { -+ return tls.Certificate{}, err -+ } -+ acmeExtension := pkix.Extension{ -+ Id: idPeACMEIdentifier, -+ Critical: true, -+ Value: extValue, -+ } -+ -+ tmpl := defaultTLSChallengeCertTemplate() -+ -+ var newOpt []CertOption -+ for _, o := range opt { -+ switch o := o.(type) { -+ case *certOptTemplate: -+ t := *(*x509.Certificate)(o) // shallow copy is ok -+ tmpl = &t -+ default: -+ newOpt = append(newOpt, o) -+ } -+ } -+ tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension) -+ newOpt = append(newOpt, WithTemplate(tmpl)) -+ return tlsChallengeCert([]string{domain}, newOpt) -+} -+ -+// popNonce returns a nonce value previously stored with c.addNonce -+// or fetches a fresh one from c.dir.NonceURL. -+// If NonceURL is empty, it first tries c.directoryURL() and, failing that, -+// the provided url. -+func (c *Client) popNonce(ctx context.Context, url string) (string, error) { -+ c.noncesMu.Lock() -+ defer c.noncesMu.Unlock() -+ if len(c.nonces) == 0 { -+ if c.dir != nil && c.dir.NonceURL != "" { -+ return c.fetchNonce(ctx, c.dir.NonceURL) -+ } -+ dirURL := c.directoryURL() -+ v, err := c.fetchNonce(ctx, dirURL) -+ if err != nil && url != dirURL { -+ v, err = c.fetchNonce(ctx, url) -+ } -+ return v, err -+ } -+ var nonce string -+ for nonce = range c.nonces { -+ delete(c.nonces, nonce) -+ break -+ } -+ return nonce, nil -+} -+ -+// clearNonces clears any stored nonces -+func (c *Client) clearNonces() { -+ c.noncesMu.Lock() -+ defer c.noncesMu.Unlock() -+ c.nonces = make(map[string]struct{}) -+} -+ -+// addNonce stores a nonce value found in h (if any) for future use. -+func (c *Client) addNonce(h http.Header) { -+ v := nonceFromHeader(h) -+ if v == "" { -+ return -+ } -+ c.noncesMu.Lock() -+ defer c.noncesMu.Unlock() -+ if len(c.nonces) >= maxNonces { -+ return -+ } -+ if c.nonces == nil { -+ c.nonces = make(map[string]struct{}) -+ } -+ c.nonces[v] = struct{}{} -+} -+ -+func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) { -+ r, err := http.NewRequest("HEAD", url, nil) -+ if err != nil { -+ return "", err -+ } -+ resp, err := c.doNoRetry(ctx, r) -+ if err != nil { -+ return "", err -+ } -+ defer resp.Body.Close() -+ nonce := nonceFromHeader(resp.Header) -+ if nonce == "" { -+ if resp.StatusCode > 299 { -+ return "", responseError(resp) -+ } -+ return "", errors.New("acme: nonce not found") -+ } -+ return nonce, nil -+} -+ -+func nonceFromHeader(h http.Header) string { -+ return h.Get("Replay-Nonce") -+} -+ -+// linkHeader returns URI-Reference values of all Link headers -+// with relation-type rel. -+// See https://tools.ietf.org/html/rfc5988#section-5 for details. -+func linkHeader(h http.Header, rel string) []string { -+ var links []string -+ for _, v := range h["Link"] { -+ parts := strings.Split(v, ";") -+ for _, p := range parts { -+ p = strings.TrimSpace(p) -+ if !strings.HasPrefix(p, "rel=") { -+ continue -+ } -+ if v := strings.Trim(p[4:], `"`); v == rel { -+ links = append(links, strings.Trim(parts[0], "<>")) -+ } -+ } -+ } -+ return links -+} -+ -+// keyAuth generates a key authorization string for a given token. -+func keyAuth(pub crypto.PublicKey, token string) (string, error) { -+ th, err := JWKThumbprint(pub) -+ if err != nil { -+ return "", err -+ } -+ return fmt.Sprintf("%s.%s", token, th), nil -+} -+ -+// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges. -+func defaultTLSChallengeCertTemplate() *x509.Certificate { -+ return &x509.Certificate{ -+ SerialNumber: big.NewInt(1), -+ NotBefore: time.Now(), -+ NotAfter: time.Now().Add(24 * time.Hour), -+ BasicConstraintsValid: true, -+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, -+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, -+ } -+} -+ -+// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges -+// with the given SANs and auto-generated public/private key pair. -+// The Subject Common Name is set to the first SAN to aid debugging. -+// To create a cert with a custom key pair, specify WithKey option. -+func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { -+ var key crypto.Signer -+ tmpl := defaultTLSChallengeCertTemplate() -+ for _, o := range opt { -+ switch o := o.(type) { -+ case *certOptKey: -+ if key != nil { -+ return tls.Certificate{}, errors.New("acme: duplicate key option") -+ } -+ key = o.key -+ case *certOptTemplate: -+ t := *(*x509.Certificate)(o) // shallow copy is ok -+ tmpl = &t -+ default: -+ // package's fault, if we let this happen: -+ panic(fmt.Sprintf("unsupported option type %T", o)) -+ } -+ } -+ if key == nil { -+ var err error -+ if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil { -+ return tls.Certificate{}, err -+ } -+ } -+ tmpl.DNSNames = san -+ if len(san) > 0 { -+ tmpl.Subject.CommonName = san[0] -+ } -+ -+ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key) -+ if err != nil { -+ return tls.Certificate{}, err -+ } -+ return tls.Certificate{ -+ Certificate: [][]byte{der}, -+ PrivateKey: key, -+ }, nil -+} -+ -+// encodePEM returns b encoded as PEM with block of type typ. -+func encodePEM(typ string, b []byte) []byte { -+ pb := &pem.Block{Type: typ, Bytes: b} -+ return pem.EncodeToMemory(pb) -+} -+ -+// timeNow is time.Now, except in tests which can mess with it. -+var timeNow = time.Now -diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/golang.org/x/crypto/acme/autocert/autocert.go -new file mode 100644 -index 000000000000..1858184e8167 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/autocert/autocert.go -@@ -0,0 +1,1193 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package autocert provides automatic access to certificates from Let's Encrypt -+// and any other ACME-based CA. -+// -+// This package is a work in progress and makes no API stability promises. -+package autocert -+ -+import ( -+ "bytes" -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "io" -+ mathrand "math/rand" -+ "net" -+ "net/http" -+ "path" -+ "strings" -+ "sync" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+ "golang.org/x/net/idna" -+) -+ -+// DefaultACMEDirectory is the default ACME Directory URL used when the Manager's Client is nil. -+const DefaultACMEDirectory = "https://acme-v02.api.letsencrypt.org/directory" -+ -+// createCertRetryAfter is how much time to wait before removing a failed state -+// entry due to an unsuccessful createCert call. -+// This is a variable instead of a const for testing. -+// TODO: Consider making it configurable or an exp backoff? -+var createCertRetryAfter = time.Minute -+ -+// pseudoRand is safe for concurrent use. -+var pseudoRand *lockedMathRand -+ -+var errPreRFC = errors.New("autocert: ACME server doesn't support RFC 8555") -+ -+func init() { -+ src := mathrand.NewSource(time.Now().UnixNano()) -+ pseudoRand = &lockedMathRand{rnd: mathrand.New(src)} -+} -+ -+// AcceptTOS is a Manager.Prompt function that always returns true to -+// indicate acceptance of the CA's Terms of Service during account -+// registration. -+func AcceptTOS(tosURL string) bool { return true } -+ -+// HostPolicy specifies which host names the Manager is allowed to respond to. -+// It returns a non-nil error if the host should be rejected. -+// The returned error is accessible via tls.Conn.Handshake and its callers. -+// See Manager's HostPolicy field and GetCertificate method docs for more details. -+type HostPolicy func(ctx context.Context, host string) error -+ -+// HostWhitelist returns a policy where only the specified host names are allowed. -+// Only exact matches are currently supported. Subdomains, regexp or wildcard -+// will not match. -+// -+// Note that all hosts will be converted to Punycode via idna.Lookup.ToASCII so that -+// Manager.GetCertificate can handle the Unicode IDN and mixedcase hosts correctly. -+// Invalid hosts will be silently ignored. -+func HostWhitelist(hosts ...string) HostPolicy { -+ whitelist := make(map[string]bool, len(hosts)) -+ for _, h := range hosts { -+ if h, err := idna.Lookup.ToASCII(h); err == nil { -+ whitelist[h] = true -+ } -+ } -+ return func(_ context.Context, host string) error { -+ if !whitelist[host] { -+ return fmt.Errorf("acme/autocert: host %q not configured in HostWhitelist", host) -+ } -+ return nil -+ } -+} -+ -+// defaultHostPolicy is used when Manager.HostPolicy is not set. -+func defaultHostPolicy(context.Context, string) error { -+ return nil -+} -+ -+// Manager is a stateful certificate manager built on top of acme.Client. -+// It obtains and refreshes certificates automatically using "tls-alpn-01" -+// or "http-01" challenge types, as well as providing them to a TLS server -+// via tls.Config. -+// -+// You must specify a cache implementation, such as DirCache, -+// to reuse obtained certificates across program restarts. -+// Otherwise your server is very likely to exceed the certificate -+// issuer's request rate limits. -+type Manager struct { -+ // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS). -+ // The registration may require the caller to agree to the CA's TOS. -+ // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report -+ // whether the caller agrees to the terms. -+ // -+ // To always accept the terms, the callers can use AcceptTOS. -+ Prompt func(tosURL string) bool -+ -+ // Cache optionally stores and retrieves previously-obtained certificates -+ // and other state. If nil, certs will only be cached for the lifetime of -+ // the Manager. Multiple Managers can share the same Cache. -+ // -+ // Using a persistent Cache, such as DirCache, is strongly recommended. -+ Cache Cache -+ -+ // HostPolicy controls which domains the Manager will attempt -+ // to retrieve new certificates for. It does not affect cached certs. -+ // -+ // If non-nil, HostPolicy is called before requesting a new cert. -+ // If nil, all hosts are currently allowed. This is not recommended, -+ // as it opens a potential attack where clients connect to a server -+ // by IP address and pretend to be asking for an incorrect host name. -+ // Manager will attempt to obtain a certificate for that host, incorrectly, -+ // eventually reaching the CA's rate limit for certificate requests -+ // and making it impossible to obtain actual certificates. -+ // -+ // See GetCertificate for more details. -+ HostPolicy HostPolicy -+ -+ // RenewBefore optionally specifies how early certificates should -+ // be renewed before they expire. -+ // -+ // If zero, they're renewed 30 days before expiration. -+ RenewBefore time.Duration -+ -+ // Client is used to perform low-level operations, such as account registration -+ // and requesting new certificates. -+ // -+ // If Client is nil, a zero-value acme.Client is used with DefaultACMEDirectory -+ // as the directory endpoint. -+ // If the Client.Key is nil, a new ECDSA P-256 key is generated and, -+ // if Cache is not nil, stored in cache. -+ // -+ // Mutating the field after the first call of GetCertificate method will have no effect. -+ Client *acme.Client -+ -+ // Email optionally specifies a contact email address. -+ // This is used by CAs, such as Let's Encrypt, to notify about problems -+ // with issued certificates. -+ // -+ // If the Client's account key is already registered, Email is not used. -+ Email string -+ -+ // ForceRSA used to make the Manager generate RSA certificates. It is now ignored. -+ // -+ // Deprecated: the Manager will request the correct type of certificate based -+ // on what each client supports. -+ ForceRSA bool -+ -+ // ExtraExtensions are used when generating a new CSR (Certificate Request), -+ // thus allowing customization of the resulting certificate. -+ // For instance, TLS Feature Extension (RFC 7633) can be used -+ // to prevent an OCSP downgrade attack. -+ // -+ // The field value is passed to crypto/x509.CreateCertificateRequest -+ // in the template's ExtraExtensions field as is. -+ ExtraExtensions []pkix.Extension -+ -+ clientMu sync.Mutex -+ client *acme.Client // initialized by acmeClient method -+ -+ stateMu sync.Mutex -+ state map[certKey]*certState -+ -+ // renewal tracks the set of domains currently running renewal timers. -+ renewalMu sync.Mutex -+ renewal map[certKey]*domainRenewal -+ -+ // challengeMu guards tryHTTP01, certTokens and httpTokens. -+ challengeMu sync.RWMutex -+ // tryHTTP01 indicates whether the Manager should try "http-01" challenge type -+ // during the authorization flow. -+ tryHTTP01 bool -+ // httpTokens contains response body values for http-01 challenges -+ // and is keyed by the URL path at which a challenge response is expected -+ // to be provisioned. -+ // The entries are stored for the duration of the authorization flow. -+ httpTokens map[string][]byte -+ // certTokens contains temporary certificates for tls-alpn-01 challenges -+ // and is keyed by the domain name which matches the ClientHello server name. -+ // The entries are stored for the duration of the authorization flow. -+ certTokens map[string]*tls.Certificate -+ -+ // nowFunc, if not nil, returns the current time. This may be set for -+ // testing purposes. -+ nowFunc func() time.Time -+} -+ -+// certKey is the key by which certificates are tracked in state, renewal and cache. -+type certKey struct { -+ domain string // without trailing dot -+ isRSA bool // RSA cert for legacy clients (as opposed to default ECDSA) -+ isToken bool // tls-based challenge token cert; key type is undefined regardless of isRSA -+} -+ -+func (c certKey) String() string { -+ if c.isToken { -+ return c.domain + "+token" -+ } -+ if c.isRSA { -+ return c.domain + "+rsa" -+ } -+ return c.domain -+} -+ -+// TLSConfig creates a new TLS config suitable for net/http.Server servers, -+// supporting HTTP/2 and the tls-alpn-01 ACME challenge type. -+func (m *Manager) TLSConfig() *tls.Config { -+ return &tls.Config{ -+ GetCertificate: m.GetCertificate, -+ NextProtos: []string{ -+ "h2", "http/1.1", // enable HTTP/2 -+ acme.ALPNProto, // enable tls-alpn ACME challenges -+ }, -+ } -+} -+ -+// GetCertificate implements the tls.Config.GetCertificate hook. -+// It provides a TLS certificate for hello.ServerName host, including answering -+// tls-alpn-01 challenges. -+// All other fields of hello are ignored. -+// -+// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting -+// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation. -+// The error is propagated back to the caller of GetCertificate and is user-visible. -+// This does not affect cached certs. See HostPolicy field description for more details. -+// -+// If GetCertificate is used directly, instead of via Manager.TLSConfig, package users will -+// also have to add acme.ALPNProto to NextProtos for tls-alpn-01, or use HTTPHandler for http-01. -+func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { -+ if m.Prompt == nil { -+ return nil, errors.New("acme/autocert: Manager.Prompt not set") -+ } -+ -+ name := hello.ServerName -+ if name == "" { -+ return nil, errors.New("acme/autocert: missing server name") -+ } -+ if !strings.Contains(strings.Trim(name, "."), ".") { -+ return nil, errors.New("acme/autocert: server name component count invalid") -+ } -+ -+ // Note that this conversion is necessary because some server names in the handshakes -+ // started by some clients (such as cURL) are not converted to Punycode, which will -+ // prevent us from obtaining certificates for them. In addition, we should also treat -+ // example.com and EXAMPLE.COM as equivalent and return the same certificate for them. -+ // Fortunately, this conversion also helped us deal with this kind of mixedcase problems. -+ // -+ // Due to the "σςΣ" problem (see https://unicode.org/faq/idn.html#22), we can't use -+ // idna.Punycode.ToASCII (or just idna.ToASCII) here. -+ name, err := idna.Lookup.ToASCII(name) -+ if err != nil { -+ return nil, errors.New("acme/autocert: server name contains invalid character") -+ } -+ -+ // In the worst-case scenario, the timeout needs to account for caching, host policy, -+ // domain ownership verification and certificate issuance. -+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) -+ defer cancel() -+ -+ // Check whether this is a token cert requested for TLS-ALPN challenge. -+ if wantsTokenCert(hello) { -+ m.challengeMu.RLock() -+ defer m.challengeMu.RUnlock() -+ if cert := m.certTokens[name]; cert != nil { -+ return cert, nil -+ } -+ if cert, err := m.cacheGet(ctx, certKey{domain: name, isToken: true}); err == nil { -+ return cert, nil -+ } -+ // TODO: cache error results? -+ return nil, fmt.Errorf("acme/autocert: no token cert for %q", name) -+ } -+ -+ // regular domain -+ ck := certKey{ -+ domain: strings.TrimSuffix(name, "."), // golang.org/issue/18114 -+ isRSA: !supportsECDSA(hello), -+ } -+ cert, err := m.cert(ctx, ck) -+ if err == nil { -+ return cert, nil -+ } -+ if err != ErrCacheMiss { -+ return nil, err -+ } -+ -+ // first-time -+ if err := m.hostPolicy()(ctx, name); err != nil { -+ return nil, err -+ } -+ cert, err = m.createCert(ctx, ck) -+ if err != nil { -+ return nil, err -+ } -+ m.cachePut(ctx, ck, cert) -+ return cert, nil -+} -+ -+// wantsTokenCert reports whether a TLS request with SNI is made by a CA server -+// for a challenge verification. -+func wantsTokenCert(hello *tls.ClientHelloInfo) bool { -+ // tls-alpn-01 -+ if len(hello.SupportedProtos) == 1 && hello.SupportedProtos[0] == acme.ALPNProto { -+ return true -+ } -+ return false -+} -+ -+func supportsECDSA(hello *tls.ClientHelloInfo) bool { -+ // The "signature_algorithms" extension, if present, limits the key exchange -+ // algorithms allowed by the cipher suites. See RFC 5246, section 7.4.1.4.1. -+ if hello.SignatureSchemes != nil { -+ ecdsaOK := false -+ schemeLoop: -+ for _, scheme := range hello.SignatureSchemes { -+ const tlsECDSAWithSHA1 tls.SignatureScheme = 0x0203 // constant added in Go 1.10 -+ switch scheme { -+ case tlsECDSAWithSHA1, tls.ECDSAWithP256AndSHA256, -+ tls.ECDSAWithP384AndSHA384, tls.ECDSAWithP521AndSHA512: -+ ecdsaOK = true -+ break schemeLoop -+ } -+ } -+ if !ecdsaOK { -+ return false -+ } -+ } -+ if hello.SupportedCurves != nil { -+ ecdsaOK := false -+ for _, curve := range hello.SupportedCurves { -+ if curve == tls.CurveP256 { -+ ecdsaOK = true -+ break -+ } -+ } -+ if !ecdsaOK { -+ return false -+ } -+ } -+ for _, suite := range hello.CipherSuites { -+ switch suite { -+ case tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, -+ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: -+ return true -+ } -+ } -+ return false -+} -+ -+// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses. -+// It returns an http.Handler that responds to the challenges and must be -+// running on port 80. If it receives a request that is not an ACME challenge, -+// it delegates the request to the optional fallback handler. -+// -+// If fallback is nil, the returned handler redirects all GET and HEAD requests -+// to the default TLS port 443 with 302 Found status code, preserving the original -+// request path and query. It responds with 400 Bad Request to all other HTTP methods. -+// The fallback is not protected by the optional HostPolicy. -+// -+// Because the fallback handler is run with unencrypted port 80 requests, -+// the fallback should not serve TLS-only requests. -+// -+// If HTTPHandler is never called, the Manager will only use the "tls-alpn-01" -+// challenge for domain verification. -+func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ m.tryHTTP01 = true -+ -+ if fallback == nil { -+ fallback = http.HandlerFunc(handleHTTPRedirect) -+ } -+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if !strings.HasPrefix(r.URL.Path, "/.well-known/acme-challenge/") { -+ fallback.ServeHTTP(w, r) -+ return -+ } -+ // A reasonable context timeout for cache and host policy only, -+ // because we don't wait for a new certificate issuance here. -+ ctx, cancel := context.WithTimeout(r.Context(), time.Minute) -+ defer cancel() -+ if err := m.hostPolicy()(ctx, r.Host); err != nil { -+ http.Error(w, err.Error(), http.StatusForbidden) -+ return -+ } -+ data, err := m.httpToken(ctx, r.URL.Path) -+ if err != nil { -+ http.Error(w, err.Error(), http.StatusNotFound) -+ return -+ } -+ w.Write(data) -+ }) -+} -+ -+func handleHTTPRedirect(w http.ResponseWriter, r *http.Request) { -+ if r.Method != "GET" && r.Method != "HEAD" { -+ http.Error(w, "Use HTTPS", http.StatusBadRequest) -+ return -+ } -+ target := "https://" + stripPort(r.Host) + r.URL.RequestURI() -+ http.Redirect(w, r, target, http.StatusFound) -+} -+ -+func stripPort(hostport string) string { -+ host, _, err := net.SplitHostPort(hostport) -+ if err != nil { -+ return hostport -+ } -+ return net.JoinHostPort(host, "443") -+} -+ -+// cert returns an existing certificate either from m.state or cache. -+// If a certificate is found in cache but not in m.state, the latter will be filled -+// with the cached value. -+func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error) { -+ m.stateMu.Lock() -+ if s, ok := m.state[ck]; ok { -+ m.stateMu.Unlock() -+ s.RLock() -+ defer s.RUnlock() -+ return s.tlscert() -+ } -+ defer m.stateMu.Unlock() -+ cert, err := m.cacheGet(ctx, ck) -+ if err != nil { -+ return nil, err -+ } -+ signer, ok := cert.PrivateKey.(crypto.Signer) -+ if !ok { -+ return nil, errors.New("acme/autocert: private key cannot sign") -+ } -+ if m.state == nil { -+ m.state = make(map[certKey]*certState) -+ } -+ s := &certState{ -+ key: signer, -+ cert: cert.Certificate, -+ leaf: cert.Leaf, -+ } -+ m.state[ck] = s -+ go m.startRenew(ck, s.key, s.leaf.NotAfter) -+ return cert, nil -+} -+ -+// cacheGet always returns a valid certificate, or an error otherwise. -+// If a cached certificate exists but is not valid, ErrCacheMiss is returned. -+func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, error) { -+ if m.Cache == nil { -+ return nil, ErrCacheMiss -+ } -+ data, err := m.Cache.Get(ctx, ck.String()) -+ if err != nil { -+ return nil, err -+ } -+ -+ // private -+ priv, pub := pem.Decode(data) -+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { -+ return nil, ErrCacheMiss -+ } -+ privKey, err := parsePrivateKey(priv.Bytes) -+ if err != nil { -+ return nil, err -+ } -+ -+ // public -+ var pubDER [][]byte -+ for len(pub) > 0 { -+ var b *pem.Block -+ b, pub = pem.Decode(pub) -+ if b == nil { -+ break -+ } -+ pubDER = append(pubDER, b.Bytes) -+ } -+ if len(pub) > 0 { -+ // Leftover content not consumed by pem.Decode. Corrupt. Ignore. -+ return nil, ErrCacheMiss -+ } -+ -+ // verify and create TLS cert -+ leaf, err := validCert(ck, pubDER, privKey, m.now()) -+ if err != nil { -+ return nil, ErrCacheMiss -+ } -+ tlscert := &tls.Certificate{ -+ Certificate: pubDER, -+ PrivateKey: privKey, -+ Leaf: leaf, -+ } -+ return tlscert, nil -+} -+ -+func (m *Manager) cachePut(ctx context.Context, ck certKey, tlscert *tls.Certificate) error { -+ if m.Cache == nil { -+ return nil -+ } -+ -+ // contains PEM-encoded data -+ var buf bytes.Buffer -+ -+ // private -+ switch key := tlscert.PrivateKey.(type) { -+ case *ecdsa.PrivateKey: -+ if err := encodeECDSAKey(&buf, key); err != nil { -+ return err -+ } -+ case *rsa.PrivateKey: -+ b := x509.MarshalPKCS1PrivateKey(key) -+ pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b} -+ if err := pem.Encode(&buf, pb); err != nil { -+ return err -+ } -+ default: -+ return errors.New("acme/autocert: unknown private key type") -+ } -+ -+ // public -+ for _, b := range tlscert.Certificate { -+ pb := &pem.Block{Type: "CERTIFICATE", Bytes: b} -+ if err := pem.Encode(&buf, pb); err != nil { -+ return err -+ } -+ } -+ -+ return m.Cache.Put(ctx, ck.String(), buf.Bytes()) -+} -+ -+func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { -+ b, err := x509.MarshalECPrivateKey(key) -+ if err != nil { -+ return err -+ } -+ pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} -+ return pem.Encode(w, pb) -+} -+ -+// createCert starts the domain ownership verification and returns a certificate -+// for that domain upon success. -+// -+// If the domain is already being verified, it waits for the existing verification to complete. -+// Either way, createCert blocks for the duration of the whole process. -+func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, error) { -+ // TODO: maybe rewrite this whole piece using sync.Once -+ state, err := m.certState(ck) -+ if err != nil { -+ return nil, err -+ } -+ // state may exist if another goroutine is already working on it -+ // in which case just wait for it to finish -+ if !state.locked { -+ state.RLock() -+ defer state.RUnlock() -+ return state.tlscert() -+ } -+ -+ // We are the first; state is locked. -+ // Unblock the readers when domain ownership is verified -+ // and we got the cert or the process failed. -+ defer state.Unlock() -+ state.locked = false -+ -+ der, leaf, err := m.authorizedCert(ctx, state.key, ck) -+ if err != nil { -+ // Remove the failed state after some time, -+ // making the manager call createCert again on the following TLS hello. -+ didRemove := testDidRemoveState // The lifetime of this timer is untracked, so copy mutable local state to avoid races. -+ time.AfterFunc(createCertRetryAfter, func() { -+ defer didRemove(ck) -+ m.stateMu.Lock() -+ defer m.stateMu.Unlock() -+ // Verify the state hasn't changed and it's still invalid -+ // before deleting. -+ s, ok := m.state[ck] -+ if !ok { -+ return -+ } -+ if _, err := validCert(ck, s.cert, s.key, m.now()); err == nil { -+ return -+ } -+ delete(m.state, ck) -+ }) -+ return nil, err -+ } -+ state.cert = der -+ state.leaf = leaf -+ go m.startRenew(ck, state.key, state.leaf.NotAfter) -+ return state.tlscert() -+} -+ -+// certState returns a new or existing certState. -+// If a new certState is returned, state.exist is false and the state is locked. -+// The returned error is non-nil only in the case where a new state could not be created. -+func (m *Manager) certState(ck certKey) (*certState, error) { -+ m.stateMu.Lock() -+ defer m.stateMu.Unlock() -+ if m.state == nil { -+ m.state = make(map[certKey]*certState) -+ } -+ // existing state -+ if state, ok := m.state[ck]; ok { -+ return state, nil -+ } -+ -+ // new locked state -+ var ( -+ err error -+ key crypto.Signer -+ ) -+ if ck.isRSA { -+ key, err = rsa.GenerateKey(rand.Reader, 2048) -+ } else { -+ key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ state := &certState{ -+ key: key, -+ locked: true, -+ } -+ state.Lock() // will be unlocked by m.certState caller -+ m.state[ck] = state -+ return state, nil -+} -+ -+// authorizedCert starts the domain ownership verification process and requests a new cert upon success. -+// The key argument is the certificate private key. -+func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) { -+ csr, err := certRequest(key, ck.domain, m.ExtraExtensions) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ client, err := m.acmeClient(ctx) -+ if err != nil { -+ return nil, nil, err -+ } -+ dir, err := client.Discover(ctx) -+ if err != nil { -+ return nil, nil, err -+ } -+ if dir.OrderURL == "" { -+ return nil, nil, errPreRFC -+ } -+ -+ o, err := m.verifyRFC(ctx, client, ck.domain) -+ if err != nil { -+ return nil, nil, err -+ } -+ chain, _, err := client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ leaf, err = validCert(ck, chain, key, m.now()) -+ if err != nil { -+ return nil, nil, err -+ } -+ return chain, leaf, nil -+} -+ -+// verifyRFC runs the identifier (domain) order-based authorization flow for RFC compliant CAs -+// using each applicable ACME challenge type. -+func (m *Manager) verifyRFC(ctx context.Context, client *acme.Client, domain string) (*acme.Order, error) { -+ // Try each supported challenge type starting with a new order each time. -+ // The nextTyp index of the next challenge type to try is shared across -+ // all order authorizations: if we've tried a challenge type once and it didn't work, -+ // it will most likely not work on another order's authorization either. -+ challengeTypes := m.supportedChallengeTypes() -+ nextTyp := 0 // challengeTypes index -+AuthorizeOrderLoop: -+ for { -+ o, err := client.AuthorizeOrder(ctx, acme.DomainIDs(domain)) -+ if err != nil { -+ return nil, err -+ } -+ // Remove all hanging authorizations to reduce rate limit quotas -+ // after we're done. -+ defer func(urls []string) { -+ go m.deactivatePendingAuthz(urls) -+ }(o.AuthzURLs) -+ -+ // Check if there's actually anything we need to do. -+ switch o.Status { -+ case acme.StatusReady: -+ // Already authorized. -+ return o, nil -+ case acme.StatusPending: -+ // Continue normal Order-based flow. -+ default: -+ return nil, fmt.Errorf("acme/autocert: invalid new order status %q; order URL: %q", o.Status, o.URI) -+ } -+ -+ // Satisfy all pending authorizations. -+ for _, zurl := range o.AuthzURLs { -+ z, err := client.GetAuthorization(ctx, zurl) -+ if err != nil { -+ return nil, err -+ } -+ if z.Status != acme.StatusPending { -+ // We are interested only in pending authorizations. -+ continue -+ } -+ // Pick the next preferred challenge. -+ var chal *acme.Challenge -+ for chal == nil && nextTyp < len(challengeTypes) { -+ chal = pickChallenge(challengeTypes[nextTyp], z.Challenges) -+ nextTyp++ -+ } -+ if chal == nil { -+ return nil, fmt.Errorf("acme/autocert: unable to satisfy %q for domain %q: no viable challenge type found", z.URI, domain) -+ } -+ // Respond to the challenge and wait for validation result. -+ cleanup, err := m.fulfill(ctx, client, chal, domain) -+ if err != nil { -+ continue AuthorizeOrderLoop -+ } -+ defer cleanup() -+ if _, err := client.Accept(ctx, chal); err != nil { -+ continue AuthorizeOrderLoop -+ } -+ if _, err := client.WaitAuthorization(ctx, z.URI); err != nil { -+ continue AuthorizeOrderLoop -+ } -+ } -+ -+ // All authorizations are satisfied. -+ // Wait for the CA to update the order status. -+ o, err = client.WaitOrder(ctx, o.URI) -+ if err != nil { -+ continue AuthorizeOrderLoop -+ } -+ return o, nil -+ } -+} -+ -+func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { -+ for _, c := range chal { -+ if c.Type == typ { -+ return c -+ } -+ } -+ return nil -+} -+ -+func (m *Manager) supportedChallengeTypes() []string { -+ m.challengeMu.RLock() -+ defer m.challengeMu.RUnlock() -+ typ := []string{"tls-alpn-01"} -+ if m.tryHTTP01 { -+ typ = append(typ, "http-01") -+ } -+ return typ -+} -+ -+// deactivatePendingAuthz relinquishes all authorizations identified by the elements -+// of the provided uri slice which are in "pending" state. -+// It ignores revocation errors. -+// -+// deactivatePendingAuthz takes no context argument and instead runs with its own -+// "detached" context because deactivations are done in a goroutine separate from -+// that of the main issuance or renewal flow. -+func (m *Manager) deactivatePendingAuthz(uri []string) { -+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) -+ defer cancel() -+ client, err := m.acmeClient(ctx) -+ if err != nil { -+ return -+ } -+ for _, u := range uri { -+ z, err := client.GetAuthorization(ctx, u) -+ if err == nil && z.Status == acme.StatusPending { -+ client.RevokeAuthorization(ctx, u) -+ } -+ } -+} -+ -+// fulfill provisions a response to the challenge chal. -+// The cleanup is non-nil only if provisioning succeeded. -+func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge, domain string) (cleanup func(), err error) { -+ switch chal.Type { -+ case "tls-alpn-01": -+ cert, err := client.TLSALPN01ChallengeCert(chal.Token, domain) -+ if err != nil { -+ return nil, err -+ } -+ m.putCertToken(ctx, domain, &cert) -+ return func() { go m.deleteCertToken(domain) }, nil -+ case "http-01": -+ resp, err := client.HTTP01ChallengeResponse(chal.Token) -+ if err != nil { -+ return nil, err -+ } -+ p := client.HTTP01ChallengePath(chal.Token) -+ m.putHTTPToken(ctx, p, resp) -+ return func() { go m.deleteHTTPToken(p) }, nil -+ } -+ return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type) -+} -+ -+// putCertToken stores the token certificate with the specified name -+// in both m.certTokens map and m.Cache. -+func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ if m.certTokens == nil { -+ m.certTokens = make(map[string]*tls.Certificate) -+ } -+ m.certTokens[name] = cert -+ m.cachePut(ctx, certKey{domain: name, isToken: true}, cert) -+} -+ -+// deleteCertToken removes the token certificate with the specified name -+// from both m.certTokens map and m.Cache. -+func (m *Manager) deleteCertToken(name string) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ delete(m.certTokens, name) -+ if m.Cache != nil { -+ ck := certKey{domain: name, isToken: true} -+ m.Cache.Delete(context.Background(), ck.String()) -+ } -+} -+ -+// httpToken retrieves an existing http-01 token value from an in-memory map -+// or the optional cache. -+func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) { -+ m.challengeMu.RLock() -+ defer m.challengeMu.RUnlock() -+ if v, ok := m.httpTokens[tokenPath]; ok { -+ return v, nil -+ } -+ if m.Cache == nil { -+ return nil, fmt.Errorf("acme/autocert: no token at %q", tokenPath) -+ } -+ return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath)) -+} -+ -+// putHTTPToken stores an http-01 token value using tokenPath as key -+// in both in-memory map and the optional Cache. -+// -+// It ignores any error returned from Cache.Put. -+func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ if m.httpTokens == nil { -+ m.httpTokens = make(map[string][]byte) -+ } -+ b := []byte(val) -+ m.httpTokens[tokenPath] = b -+ if m.Cache != nil { -+ m.Cache.Put(ctx, httpTokenCacheKey(tokenPath), b) -+ } -+} -+ -+// deleteHTTPToken removes an http-01 token value from both in-memory map -+// and the optional Cache, ignoring any error returned from the latter. -+// -+// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout. -+func (m *Manager) deleteHTTPToken(tokenPath string) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ delete(m.httpTokens, tokenPath) -+ if m.Cache != nil { -+ m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath)) -+ } -+} -+ -+// httpTokenCacheKey returns a key at which an http-01 token value may be stored -+// in the Manager's optional Cache. -+func httpTokenCacheKey(tokenPath string) string { -+ return path.Base(tokenPath) + "+http-01" -+} -+ -+// startRenew starts a cert renewal timer loop, one per domain. -+// -+// The loop is scheduled in two cases: -+// - a cert was fetched from cache for the first time (wasn't in m.state) -+// - a new cert was created by m.createCert -+// -+// The key argument is a certificate private key. -+// The exp argument is the cert expiration time (NotAfter). -+func (m *Manager) startRenew(ck certKey, key crypto.Signer, exp time.Time) { -+ m.renewalMu.Lock() -+ defer m.renewalMu.Unlock() -+ if m.renewal[ck] != nil { -+ // another goroutine is already on it -+ return -+ } -+ if m.renewal == nil { -+ m.renewal = make(map[certKey]*domainRenewal) -+ } -+ dr := &domainRenewal{m: m, ck: ck, key: key} -+ m.renewal[ck] = dr -+ dr.start(exp) -+} -+ -+// stopRenew stops all currently running cert renewal timers. -+// The timers are not restarted during the lifetime of the Manager. -+func (m *Manager) stopRenew() { -+ m.renewalMu.Lock() -+ defer m.renewalMu.Unlock() -+ for name, dr := range m.renewal { -+ delete(m.renewal, name) -+ dr.stop() -+ } -+} -+ -+func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { -+ const keyName = "acme_account+key" -+ -+ // Previous versions of autocert stored the value under a different key. -+ const legacyKeyName = "acme_account.key" -+ -+ genKey := func() (*ecdsa.PrivateKey, error) { -+ return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ } -+ -+ if m.Cache == nil { -+ return genKey() -+ } -+ -+ data, err := m.Cache.Get(ctx, keyName) -+ if err == ErrCacheMiss { -+ data, err = m.Cache.Get(ctx, legacyKeyName) -+ } -+ if err == ErrCacheMiss { -+ key, err := genKey() -+ if err != nil { -+ return nil, err -+ } -+ var buf bytes.Buffer -+ if err := encodeECDSAKey(&buf, key); err != nil { -+ return nil, err -+ } -+ if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil { -+ return nil, err -+ } -+ return key, nil -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ priv, _ := pem.Decode(data) -+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { -+ return nil, errors.New("acme/autocert: invalid account key found in cache") -+ } -+ return parsePrivateKey(priv.Bytes) -+} -+ -+func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) { -+ m.clientMu.Lock() -+ defer m.clientMu.Unlock() -+ if m.client != nil { -+ return m.client, nil -+ } -+ -+ client := m.Client -+ if client == nil { -+ client = &acme.Client{DirectoryURL: DefaultACMEDirectory} -+ } -+ if client.Key == nil { -+ var err error -+ client.Key, err = m.accountKey(ctx) -+ if err != nil { -+ return nil, err -+ } -+ } -+ if client.UserAgent == "" { -+ client.UserAgent = "autocert" -+ } -+ var contact []string -+ if m.Email != "" { -+ contact = []string{"mailto:" + m.Email} -+ } -+ a := &acme.Account{Contact: contact} -+ _, err := client.Register(ctx, a, m.Prompt) -+ if err == nil || isAccountAlreadyExist(err) { -+ m.client = client -+ err = nil -+ } -+ return m.client, err -+} -+ -+// isAccountAlreadyExist reports whether the err, as returned from acme.Client.Register, -+// indicates the account has already been registered. -+func isAccountAlreadyExist(err error) bool { -+ if err == acme.ErrAccountAlreadyExists { -+ return true -+ } -+ ae, ok := err.(*acme.Error) -+ return ok && ae.StatusCode == http.StatusConflict -+} -+ -+func (m *Manager) hostPolicy() HostPolicy { -+ if m.HostPolicy != nil { -+ return m.HostPolicy -+ } -+ return defaultHostPolicy -+} -+ -+func (m *Manager) renewBefore() time.Duration { -+ if m.RenewBefore > renewJitter { -+ return m.RenewBefore -+ } -+ return 720 * time.Hour // 30 days -+} -+ -+func (m *Manager) now() time.Time { -+ if m.nowFunc != nil { -+ return m.nowFunc() -+ } -+ return time.Now() -+} -+ -+// certState is ready when its mutex is unlocked for reading. -+type certState struct { -+ sync.RWMutex -+ locked bool // locked for read/write -+ key crypto.Signer // private key for cert -+ cert [][]byte // DER encoding -+ leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil -+} -+ -+// tlscert creates a tls.Certificate from s.key and s.cert. -+// Callers should wrap it in s.RLock() and s.RUnlock(). -+func (s *certState) tlscert() (*tls.Certificate, error) { -+ if s.key == nil { -+ return nil, errors.New("acme/autocert: missing signer") -+ } -+ if len(s.cert) == 0 { -+ return nil, errors.New("acme/autocert: missing certificate") -+ } -+ return &tls.Certificate{ -+ PrivateKey: s.key, -+ Certificate: s.cert, -+ Leaf: s.leaf, -+ }, nil -+} -+ -+// certRequest generates a CSR for the given common name. -+func certRequest(key crypto.Signer, name string, ext []pkix.Extension) ([]byte, error) { -+ req := &x509.CertificateRequest{ -+ Subject: pkix.Name{CommonName: name}, -+ DNSNames: []string{name}, -+ ExtraExtensions: ext, -+ } -+ return x509.CreateCertificateRequest(rand.Reader, req, key) -+} -+ -+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates -+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys. -+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. -+// -+// Inspired by parsePrivateKey in crypto/tls/tls.go. -+func parsePrivateKey(der []byte) (crypto.Signer, error) { -+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { -+ return key, nil -+ } -+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { -+ switch key := key.(type) { -+ case *rsa.PrivateKey: -+ return key, nil -+ case *ecdsa.PrivateKey: -+ return key, nil -+ default: -+ return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping") -+ } -+ } -+ if key, err := x509.ParseECPrivateKey(der); err == nil { -+ return key, nil -+ } -+ -+ return nil, errors.New("acme/autocert: failed to parse private key") -+} -+ -+// validCert parses a cert chain provided as der argument and verifies the leaf and der[0] -+// correspond to the private key, the domain and key type match, and expiration dates -+// are valid. It doesn't do any revocation checking. -+// -+// The returned value is the verified leaf cert. -+func validCert(ck certKey, der [][]byte, key crypto.Signer, now time.Time) (leaf *x509.Certificate, err error) { -+ // parse public part(s) -+ var n int -+ for _, b := range der { -+ n += len(b) -+ } -+ pub := make([]byte, n) -+ n = 0 -+ for _, b := range der { -+ n += copy(pub[n:], b) -+ } -+ x509Cert, err := x509.ParseCertificates(pub) -+ if err != nil || len(x509Cert) == 0 { -+ return nil, errors.New("acme/autocert: no public key found") -+ } -+ // verify the leaf is not expired and matches the domain name -+ leaf = x509Cert[0] -+ if now.Before(leaf.NotBefore) { -+ return nil, errors.New("acme/autocert: certificate is not valid yet") -+ } -+ if now.After(leaf.NotAfter) { -+ return nil, errors.New("acme/autocert: expired certificate") -+ } -+ if err := leaf.VerifyHostname(ck.domain); err != nil { -+ return nil, err -+ } -+ // renew certificates revoked by Let's Encrypt in January 2022 -+ if isRevokedLetsEncrypt(leaf) { -+ return nil, errors.New("acme/autocert: certificate was probably revoked by Let's Encrypt") -+ } -+ // ensure the leaf corresponds to the private key and matches the certKey type -+ switch pub := leaf.PublicKey.(type) { -+ case *rsa.PublicKey: -+ prv, ok := key.(*rsa.PrivateKey) -+ if !ok { -+ return nil, errors.New("acme/autocert: private key type does not match public key type") -+ } -+ if pub.N.Cmp(prv.N) != 0 { -+ return nil, errors.New("acme/autocert: private key does not match public key") -+ } -+ if !ck.isRSA && !ck.isToken { -+ return nil, errors.New("acme/autocert: key type does not match expected value") -+ } -+ case *ecdsa.PublicKey: -+ prv, ok := key.(*ecdsa.PrivateKey) -+ if !ok { -+ return nil, errors.New("acme/autocert: private key type does not match public key type") -+ } -+ if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 { -+ return nil, errors.New("acme/autocert: private key does not match public key") -+ } -+ if ck.isRSA && !ck.isToken { -+ return nil, errors.New("acme/autocert: key type does not match expected value") -+ } -+ default: -+ return nil, errors.New("acme/autocert: unknown public key algorithm") -+ } -+ return leaf, nil -+} -+ -+// https://community.letsencrypt.org/t/2022-01-25-issue-with-tls-alpn-01-validation-method/170450 -+var letsEncryptFixDeployTime = time.Date(2022, time.January, 26, 00, 48, 0, 0, time.UTC) -+ -+// isRevokedLetsEncrypt returns whether the certificate is likely to be part of -+// a batch of certificates revoked by Let's Encrypt in January 2022. This check -+// can be safely removed from May 2022. -+func isRevokedLetsEncrypt(cert *x509.Certificate) bool { -+ O := cert.Issuer.Organization -+ return len(O) == 1 && O[0] == "Let's Encrypt" && -+ cert.NotBefore.Before(letsEncryptFixDeployTime) -+} -+ -+type lockedMathRand struct { -+ sync.Mutex -+ rnd *mathrand.Rand -+} -+ -+func (r *lockedMathRand) int63n(max int64) int64 { -+ r.Lock() -+ n := r.rnd.Int63n(max) -+ r.Unlock() -+ return n -+} -+ -+// For easier testing. -+var ( -+ // Called when a state is removed. -+ testDidRemoveState = func(certKey) {} -+) -diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go -new file mode 100644 -index 000000000000..03f63022fa42 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/autocert/cache.go -@@ -0,0 +1,136 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "context" -+ "errors" -+ "io/ioutil" -+ "os" -+ "path/filepath" -+) -+ -+// ErrCacheMiss is returned when a certificate is not found in cache. -+var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") -+ -+// Cache is used by Manager to store and retrieve previously obtained certificates -+// and other account data as opaque blobs. -+// -+// Cache implementations should not rely on the key naming pattern. Keys can -+// include any printable ASCII characters, except the following: \/:*?"<>| -+type Cache interface { -+ // Get returns a certificate data for the specified key. -+ // If there's no such key, Get returns ErrCacheMiss. -+ Get(ctx context.Context, key string) ([]byte, error) -+ -+ // Put stores the data in the cache under the specified key. -+ // Underlying implementations may use any data storage format, -+ // as long as the reverse operation, Get, results in the original data. -+ Put(ctx context.Context, key string, data []byte) error -+ -+ // Delete removes a certificate data from the cache under the specified key. -+ // If there's no such key in the cache, Delete returns nil. -+ Delete(ctx context.Context, key string) error -+} -+ -+// DirCache implements Cache using a directory on the local filesystem. -+// If the directory does not exist, it will be created with 0700 permissions. -+type DirCache string -+ -+// Get reads a certificate data from the specified file name. -+func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) { -+ name = filepath.Join(string(d), name) -+ var ( -+ data []byte -+ err error -+ done = make(chan struct{}) -+ ) -+ go func() { -+ data, err = ioutil.ReadFile(name) -+ close(done) -+ }() -+ select { -+ case <-ctx.Done(): -+ return nil, ctx.Err() -+ case <-done: -+ } -+ if os.IsNotExist(err) { -+ return nil, ErrCacheMiss -+ } -+ return data, err -+} -+ -+// Put writes the certificate data to the specified file name. -+// The file will be created with 0600 permissions. -+func (d DirCache) Put(ctx context.Context, name string, data []byte) error { -+ if err := os.MkdirAll(string(d), 0700); err != nil { -+ return err -+ } -+ -+ done := make(chan struct{}) -+ var err error -+ go func() { -+ defer close(done) -+ var tmp string -+ if tmp, err = d.writeTempFile(name, data); err != nil { -+ return -+ } -+ defer os.Remove(tmp) -+ select { -+ case <-ctx.Done(): -+ // Don't overwrite the file if the context was canceled. -+ default: -+ newName := filepath.Join(string(d), name) -+ err = os.Rename(tmp, newName) -+ } -+ }() -+ select { -+ case <-ctx.Done(): -+ return ctx.Err() -+ case <-done: -+ } -+ return err -+} -+ -+// Delete removes the specified file name. -+func (d DirCache) Delete(ctx context.Context, name string) error { -+ name = filepath.Join(string(d), name) -+ var ( -+ err error -+ done = make(chan struct{}) -+ ) -+ go func() { -+ err = os.Remove(name) -+ close(done) -+ }() -+ select { -+ case <-ctx.Done(): -+ return ctx.Err() -+ case <-done: -+ } -+ if err != nil && !os.IsNotExist(err) { -+ return err -+ } -+ return nil -+} -+ -+// writeTempFile writes b to a temporary file, closes the file and returns its path. -+func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) { -+ // TempFile uses 0600 permissions -+ f, err := ioutil.TempFile(string(d), prefix) -+ if err != nil { -+ return "", err -+ } -+ defer func() { -+ if reterr != nil { -+ os.Remove(f.Name()) -+ } -+ }() -+ if _, err := f.Write(b); err != nil { -+ f.Close() -+ return "", err -+ } -+ return f.Name(), f.Close() -+} -diff --git a/vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go b/vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go -new file mode 100644 -index 000000000000..8c4c6426a1f9 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go -@@ -0,0 +1,762 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package acmetest provides types for testing acme and autocert packages. -+// -+// TODO: Consider moving this to x/crypto/acme/internal/acmetest for acme tests as well. -+package acmetest -+ -+import ( -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/base64" -+ "encoding/json" -+ "encoding/pem" -+ "fmt" -+ "io" -+ "math/big" -+ "net" -+ "net/http" -+ "net/http/httptest" -+ "path" -+ "strconv" -+ "strings" -+ "sync" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+) -+ -+// CAServer is a simple test server which implements ACME spec bits needed for testing. -+type CAServer struct { -+ rootKey crypto.Signer -+ rootCert []byte // DER encoding -+ rootTemplate *x509.Certificate -+ -+ t *testing.T -+ server *httptest.Server -+ issuer pkix.Name -+ challengeTypes []string -+ url string -+ roots *x509.CertPool -+ -+ mu sync.Mutex -+ certCount int // number of issued certs -+ acctRegistered bool // set once an account has been registered -+ domainAddr map[string]string // domain name to addr:port resolution -+ domainGetCert map[string]getCertificateFunc // domain name to GetCertificate function -+ domainHandler map[string]http.Handler // domain name to Handle function -+ validAuthz map[string]*authorization // valid authz, keyed by domain name -+ authorizations []*authorization // all authz, index is used as ID -+ orders []*order // index is used as order ID -+ errors []error // encountered client errors -+} -+ -+type getCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) -+ -+// NewCAServer creates a new ACME test server. The returned CAServer issues -+// certs signed with the CA roots available in the Roots field. -+func NewCAServer(t *testing.T) *CAServer { -+ ca := &CAServer{t: t, -+ challengeTypes: []string{"fake-01", "tls-alpn-01", "http-01"}, -+ domainAddr: make(map[string]string), -+ domainGetCert: make(map[string]getCertificateFunc), -+ domainHandler: make(map[string]http.Handler), -+ validAuthz: make(map[string]*authorization), -+ } -+ -+ ca.server = httptest.NewUnstartedServer(http.HandlerFunc(ca.handle)) -+ -+ r, err := rand.Int(rand.Reader, big.NewInt(1000000)) -+ if err != nil { -+ panic(fmt.Sprintf("rand.Int: %v", err)) -+ } -+ ca.issuer = pkix.Name{ -+ Organization: []string{"Test Acme Co"}, -+ CommonName: "Root CA " + r.String(), -+ } -+ -+ return ca -+} -+ -+func (ca *CAServer) generateRoot() { -+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err)) -+ } -+ tmpl := &x509.Certificate{ -+ SerialNumber: big.NewInt(1), -+ Subject: ca.issuer, -+ NotBefore: time.Now(), -+ NotAfter: time.Now().Add(365 * 24 * time.Hour), -+ KeyUsage: x509.KeyUsageCertSign, -+ BasicConstraintsValid: true, -+ IsCA: true, -+ } -+ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) -+ if err != nil { -+ panic(fmt.Sprintf("x509.CreateCertificate: %v", err)) -+ } -+ cert, err := x509.ParseCertificate(der) -+ if err != nil { -+ panic(fmt.Sprintf("x509.ParseCertificate: %v", err)) -+ } -+ ca.roots = x509.NewCertPool() -+ ca.roots.AddCert(cert) -+ ca.rootKey = key -+ ca.rootCert = der -+ ca.rootTemplate = tmpl -+} -+ -+// IssuerName sets the name of the issuing CA. -+func (ca *CAServer) IssuerName(name pkix.Name) *CAServer { -+ if ca.url != "" { -+ panic("IssuerName must be called before Start") -+ } -+ ca.issuer = name -+ return ca -+} -+ -+// ChallengeTypes sets the supported challenge types. -+func (ca *CAServer) ChallengeTypes(types ...string) *CAServer { -+ if ca.url != "" { -+ panic("ChallengeTypes must be called before Start") -+ } -+ ca.challengeTypes = types -+ return ca -+} -+ -+// URL returns the server address, after Start has been called. -+func (ca *CAServer) URL() string { -+ if ca.url == "" { -+ panic("URL called before Start") -+ } -+ return ca.url -+} -+ -+// Roots returns a pool cointaining the CA root. -+func (ca *CAServer) Roots() *x509.CertPool { -+ if ca.url == "" { -+ panic("Roots called before Start") -+ } -+ return ca.roots -+} -+ -+// Start starts serving requests. The server address becomes available in the -+// URL field. -+func (ca *CAServer) Start() *CAServer { -+ if ca.url == "" { -+ ca.generateRoot() -+ ca.server.Start() -+ ca.t.Cleanup(ca.server.Close) -+ ca.url = ca.server.URL -+ } -+ return ca -+} -+ -+func (ca *CAServer) serverURL(format string, arg ...interface{}) string { -+ return ca.server.URL + fmt.Sprintf(format, arg...) -+} -+ -+func (ca *CAServer) addr(domain string) (string, bool) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ addr, ok := ca.domainAddr[domain] -+ return addr, ok -+} -+ -+func (ca *CAServer) getCert(domain string) (getCertificateFunc, bool) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ f, ok := ca.domainGetCert[domain] -+ return f, ok -+} -+ -+func (ca *CAServer) getHandler(domain string) (http.Handler, bool) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ h, ok := ca.domainHandler[domain] -+ return h, ok -+} -+ -+func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...interface{}) { -+ s := fmt.Sprintf(format, a...) -+ ca.t.Errorf(format, a...) -+ http.Error(w, s, code) -+} -+ -+// Resolve adds a domain to address resolution for the ca to dial to -+// when validating challenges for the domain authorization. -+func (ca *CAServer) Resolve(domain, addr string) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ ca.domainAddr[domain] = addr -+} -+ -+// ResolveGetCertificate redirects TLS connections for domain to f when -+// validating challenges for the domain authorization. -+func (ca *CAServer) ResolveGetCertificate(domain string, f getCertificateFunc) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ ca.domainGetCert[domain] = f -+} -+ -+// ResolveHandler redirects HTTP requests for domain to f when -+// validating challenges for the domain authorization. -+func (ca *CAServer) ResolveHandler(domain string, h http.Handler) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ ca.domainHandler[domain] = h -+} -+ -+type discovery struct { -+ NewNonce string `json:"newNonce"` -+ NewAccount string `json:"newAccount"` -+ NewOrder string `json:"newOrder"` -+ NewAuthz string `json:"newAuthz"` -+} -+ -+type challenge struct { -+ URI string `json:"uri"` -+ Type string `json:"type"` -+ Token string `json:"token"` -+} -+ -+type authorization struct { -+ Status string `json:"status"` -+ Challenges []challenge `json:"challenges"` -+ -+ domain string -+ id int -+} -+ -+type order struct { -+ Status string `json:"status"` -+ AuthzURLs []string `json:"authorizations"` -+ FinalizeURL string `json:"finalize"` // CSR submit URL -+ CertURL string `json:"certificate"` // already issued cert -+ -+ leaf []byte // issued cert in DER format -+} -+ -+func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { -+ ca.t.Logf("%s %s", r.Method, r.URL) -+ w.Header().Set("Replay-Nonce", "nonce") -+ // TODO: Verify nonce header for all POST requests. -+ -+ switch { -+ default: -+ ca.httpErrorf(w, http.StatusBadRequest, "unrecognized r.URL.Path: %s", r.URL.Path) -+ -+ // Discovery request. -+ case r.URL.Path == "/": -+ resp := &discovery{ -+ NewNonce: ca.serverURL("/new-nonce"), -+ NewAccount: ca.serverURL("/new-account"), -+ NewOrder: ca.serverURL("/new-order"), -+ } -+ if err := json.NewEncoder(w).Encode(resp); err != nil { -+ panic(fmt.Sprintf("discovery response: %v", err)) -+ } -+ -+ // Nonce requests. -+ case r.URL.Path == "/new-nonce": -+ // Nonce values are always set. Nothing else to do. -+ return -+ -+ // Client key registration request. -+ case r.URL.Path == "/new-account": -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ if ca.acctRegistered { -+ ca.httpErrorf(w, http.StatusServiceUnavailable, "multiple accounts are not implemented") -+ return -+ } -+ ca.acctRegistered = true -+ // TODO: Check the user account key against a ca.accountKeys? -+ w.Header().Set("Location", ca.serverURL("/accounts/1")) -+ w.WriteHeader(http.StatusCreated) -+ w.Write([]byte("{}")) -+ -+ // New order request. -+ case r.URL.Path == "/new-order": -+ var req struct { -+ Identifiers []struct{ Value string } -+ } -+ if err := decodePayload(&req, r.Body); err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ o := &order{Status: acme.StatusPending} -+ for _, id := range req.Identifiers { -+ z := ca.authz(id.Value) -+ o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%d", z.id)) -+ } -+ orderID := len(ca.orders) -+ ca.orders = append(ca.orders, o) -+ w.Header().Set("Location", ca.serverURL("/orders/%d", orderID)) -+ w.WriteHeader(http.StatusCreated) -+ if err := json.NewEncoder(w).Encode(o); err != nil { -+ panic(err) -+ } -+ -+ // Existing order status requests. -+ case strings.HasPrefix(r.URL.Path, "/orders/"): -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/orders/")) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ if err := json.NewEncoder(w).Encode(o); err != nil { -+ panic(err) -+ } -+ -+ // Accept challenge requests. -+ case strings.HasPrefix(r.URL.Path, "/challenge/"): -+ parts := strings.Split(r.URL.Path, "/") -+ typ, id := parts[len(parts)-2], parts[len(parts)-1] -+ ca.mu.Lock() -+ supported := false -+ for _, suppTyp := range ca.challengeTypes { -+ if suppTyp == typ { -+ supported = true -+ } -+ } -+ a, err := ca.storedAuthz(id) -+ ca.mu.Unlock() -+ if !supported { -+ ca.httpErrorf(w, http.StatusBadRequest, "unsupported challenge: %v", typ) -+ return -+ } -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: %v", err) -+ return -+ } -+ go ca.validateChallenge(a, typ) -+ w.Write([]byte("{}")) -+ -+ // Get authorization status requests. -+ case strings.HasPrefix(r.URL.Path, "/authz/"): -+ var req struct{ Status string } -+ decodePayload(&req, r.Body) -+ deactivate := req.Status == "deactivated" -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ authz, err := ca.storedAuthz(strings.TrimPrefix(r.URL.Path, "/authz/")) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusNotFound, "%v", err) -+ return -+ } -+ if deactivate { -+ // Note we don't invalidate authorized orders as we should. -+ authz.Status = "deactivated" -+ ca.t.Logf("authz %d is now %s", authz.id, authz.Status) -+ ca.updatePendingOrders() -+ } -+ if err := json.NewEncoder(w).Encode(authz); err != nil { -+ panic(fmt.Sprintf("encoding authz %d: %v", authz.id, err)) -+ } -+ -+ // Certificate issuance request. -+ case strings.HasPrefix(r.URL.Path, "/new-cert/"): -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ orderID := strings.TrimPrefix(r.URL.Path, "/new-cert/") -+ o, err := ca.storedOrder(orderID) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ if o.Status != acme.StatusReady { -+ ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) -+ return -+ } -+ // Validate CSR request. -+ var req struct { -+ CSR string `json:"csr"` -+ } -+ decodePayload(&req, r.Body) -+ b, _ := base64.RawURLEncoding.DecodeString(req.CSR) -+ csr, err := x509.ParseCertificateRequest(b) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ // Issue the certificate. -+ der, err := ca.leafCert(csr) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, "new-cert response: ca.leafCert: %v", err) -+ return -+ } -+ o.leaf = der -+ o.CertURL = ca.serverURL("/issued-cert/%s", orderID) -+ o.Status = acme.StatusValid -+ if err := json.NewEncoder(w).Encode(o); err != nil { -+ panic(err) -+ } -+ -+ // Already issued cert download requests. -+ case strings.HasPrefix(r.URL.Path, "/issued-cert/"): -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/issued-cert/")) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ if o.Status != acme.StatusValid { -+ ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) -+ return -+ } -+ w.Header().Set("Content-Type", "application/pem-certificate-chain") -+ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: o.leaf}) -+ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: ca.rootCert}) -+ } -+} -+ -+// storedOrder retrieves a previously created order at index i. -+// It requires ca.mu to be locked. -+func (ca *CAServer) storedOrder(i string) (*order, error) { -+ idx, err := strconv.Atoi(i) -+ if err != nil { -+ return nil, fmt.Errorf("storedOrder: %v", err) -+ } -+ if idx < 0 { -+ return nil, fmt.Errorf("storedOrder: invalid order index %d", idx) -+ } -+ if idx > len(ca.orders)-1 { -+ return nil, fmt.Errorf("storedOrder: no such order %d", idx) -+ } -+ -+ ca.updatePendingOrders() -+ return ca.orders[idx], nil -+} -+ -+// storedAuthz retrieves a previously created authz at index i. -+// It requires ca.mu to be locked. -+func (ca *CAServer) storedAuthz(i string) (*authorization, error) { -+ idx, err := strconv.Atoi(i) -+ if err != nil { -+ return nil, fmt.Errorf("storedAuthz: %v", err) -+ } -+ if idx < 0 { -+ return nil, fmt.Errorf("storedAuthz: invalid authz index %d", idx) -+ } -+ if idx > len(ca.authorizations)-1 { -+ return nil, fmt.Errorf("storedAuthz: no such authz %d", idx) -+ } -+ return ca.authorizations[idx], nil -+} -+ -+// authz returns an existing valid authorization for the identifier or creates a -+// new one. It requires ca.mu to be locked. -+func (ca *CAServer) authz(identifier string) *authorization { -+ authz, ok := ca.validAuthz[identifier] -+ if !ok { -+ authzId := len(ca.authorizations) -+ authz = &authorization{ -+ id: authzId, -+ domain: identifier, -+ Status: acme.StatusPending, -+ } -+ for _, typ := range ca.challengeTypes { -+ authz.Challenges = append(authz.Challenges, challenge{ -+ Type: typ, -+ URI: ca.serverURL("/challenge/%s/%d", typ, authzId), -+ Token: challengeToken(authz.domain, typ, authzId), -+ }) -+ } -+ ca.authorizations = append(ca.authorizations, authz) -+ } -+ return authz -+} -+ -+// leafCert issues a new certificate. -+// It requires ca.mu to be locked. -+func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) { -+ ca.certCount++ // next leaf cert serial number -+ leaf := &x509.Certificate{ -+ SerialNumber: big.NewInt(int64(ca.certCount)), -+ Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, -+ NotBefore: time.Now(), -+ NotAfter: time.Now().Add(90 * 24 * time.Hour), -+ KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, -+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, -+ DNSNames: csr.DNSNames, -+ BasicConstraintsValid: true, -+ } -+ if len(csr.DNSNames) == 0 { -+ leaf.DNSNames = []string{csr.Subject.CommonName} -+ } -+ return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey) -+} -+ -+// LeafCert issues a leaf certificate. -+func (ca *CAServer) LeafCert(name, keyType string, notBefore, notAfter time.Time) *tls.Certificate { -+ if ca.url == "" { -+ panic("LeafCert called before Start") -+ } -+ -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ var pk crypto.Signer -+ switch keyType { -+ case "RSA": -+ var err error -+ pk, err = rsa.GenerateKey(rand.Reader, 1024) -+ if err != nil { -+ ca.t.Fatal(err) -+ } -+ case "ECDSA": -+ var err error -+ pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ ca.t.Fatal(err) -+ } -+ default: -+ panic("LeafCert: unknown key type") -+ } -+ ca.certCount++ // next leaf cert serial number -+ leaf := &x509.Certificate{ -+ SerialNumber: big.NewInt(int64(ca.certCount)), -+ Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, -+ NotBefore: notBefore, -+ NotAfter: notAfter, -+ KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, -+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, -+ DNSNames: []string{name}, -+ BasicConstraintsValid: true, -+ } -+ der, err := x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, pk.Public(), ca.rootKey) -+ if err != nil { -+ ca.t.Fatal(err) -+ } -+ return &tls.Certificate{ -+ Certificate: [][]byte{der}, -+ PrivateKey: pk, -+ } -+} -+ -+func (ca *CAServer) validateChallenge(authz *authorization, typ string) { -+ var err error -+ switch typ { -+ case "tls-alpn-01": -+ err = ca.verifyALPNChallenge(authz) -+ case "http-01": -+ err = ca.verifyHTTPChallenge(authz) -+ default: -+ panic(fmt.Sprintf("validation of %q is not implemented", typ)) -+ } -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ if err != nil { -+ authz.Status = "invalid" -+ } else { -+ authz.Status = "valid" -+ ca.validAuthz[authz.domain] = authz -+ } -+ ca.t.Logf("validated %q for %q, err: %v", typ, authz.domain, err) -+ ca.t.Logf("authz %d is now %s", authz.id, authz.Status) -+ -+ ca.updatePendingOrders() -+} -+ -+func (ca *CAServer) updatePendingOrders() { -+ // Update all pending orders. -+ // An order becomes "ready" if all authorizations are "valid". -+ // An order becomes "invalid" if any authorization is "invalid". -+ // Status changes: https://tools.ietf.org/html/rfc8555#section-7.1.6 -+ for i, o := range ca.orders { -+ if o.Status != acme.StatusPending { -+ continue -+ } -+ -+ countValid, countInvalid := ca.validateAuthzURLs(o.AuthzURLs, i) -+ if countInvalid > 0 { -+ o.Status = acme.StatusInvalid -+ ca.t.Logf("order %d is now invalid", i) -+ continue -+ } -+ if countValid == len(o.AuthzURLs) { -+ o.Status = acme.StatusReady -+ o.FinalizeURL = ca.serverURL("/new-cert/%d", i) -+ ca.t.Logf("order %d is now ready", i) -+ } -+ } -+} -+ -+func (ca *CAServer) validateAuthzURLs(urls []string, orderNum int) (countValid, countInvalid int) { -+ for _, zurl := range urls { -+ z, err := ca.storedAuthz(path.Base(zurl)) -+ if err != nil { -+ ca.t.Logf("no authz %q for order %d", zurl, orderNum) -+ continue -+ } -+ if z.Status == acme.StatusInvalid { -+ countInvalid++ -+ } -+ if z.Status == acme.StatusValid { -+ countValid++ -+ } -+ } -+ return countValid, countInvalid -+} -+ -+func (ca *CAServer) verifyALPNChallenge(a *authorization) error { -+ const acmeALPNProto = "acme-tls/1" -+ -+ addr, haveAddr := ca.addr(a.domain) -+ getCert, haveGetCert := ca.getCert(a.domain) -+ if !haveAddr && !haveGetCert { -+ return fmt.Errorf("no resolution information for %q", a.domain) -+ } -+ if haveAddr && haveGetCert { -+ return fmt.Errorf("overlapping resolution information for %q", a.domain) -+ } -+ -+ var crt *x509.Certificate -+ switch { -+ case haveAddr: -+ conn, err := tls.Dial("tcp", addr, &tls.Config{ -+ ServerName: a.domain, -+ InsecureSkipVerify: true, -+ NextProtos: []string{acmeALPNProto}, -+ MinVersion: tls.VersionTLS12, -+ }) -+ if err != nil { -+ return err -+ } -+ if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { -+ return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) -+ } -+ if n := len(conn.ConnectionState().PeerCertificates); n != 1 { -+ return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) -+ } -+ crt = conn.ConnectionState().PeerCertificates[0] -+ case haveGetCert: -+ hello := &tls.ClientHelloInfo{ -+ ServerName: a.domain, -+ // TODO: support selecting ECDSA. -+ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, -+ SupportedProtos: []string{acme.ALPNProto}, -+ SupportedVersions: []uint16{tls.VersionTLS12}, -+ } -+ c, err := getCert(hello) -+ if err != nil { -+ return err -+ } -+ crt, err = x509.ParseCertificate(c.Certificate[0]) -+ if err != nil { -+ return err -+ } -+ } -+ -+ if err := crt.VerifyHostname(a.domain); err != nil { -+ return fmt.Errorf("verifyALPNChallenge: VerifyHostname: %v", err) -+ } -+ // See RFC 8737, Section 6.1. -+ oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} -+ for _, x := range crt.Extensions { -+ if x.Id.Equal(oid) { -+ // TODO: check the token. -+ return nil -+ } -+ } -+ return fmt.Errorf("verifyTokenCert: no id-pe-acmeIdentifier extension found") -+} -+ -+func (ca *CAServer) verifyHTTPChallenge(a *authorization) error { -+ addr, haveAddr := ca.addr(a.domain) -+ handler, haveHandler := ca.getHandler(a.domain) -+ if !haveAddr && !haveHandler { -+ return fmt.Errorf("no resolution information for %q", a.domain) -+ } -+ if haveAddr && haveHandler { -+ return fmt.Errorf("overlapping resolution information for %q", a.domain) -+ } -+ -+ token := challengeToken(a.domain, "http-01", a.id) -+ path := "/.well-known/acme-challenge/" + token -+ -+ var body string -+ switch { -+ case haveAddr: -+ t := &http.Transport{ -+ DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) { -+ return (&net.Dialer{}).DialContext(ctx, network, addr) -+ }, -+ } -+ req, err := http.NewRequest("GET", "http://"+a.domain+path, nil) -+ if err != nil { -+ return err -+ } -+ res, err := t.RoundTrip(req) -+ if err != nil { -+ return err -+ } -+ if res.StatusCode != http.StatusOK { -+ return fmt.Errorf("http token: w.Code = %d; want %d", res.StatusCode, http.StatusOK) -+ } -+ b, err := io.ReadAll(res.Body) -+ if err != nil { -+ return err -+ } -+ body = string(b) -+ case haveHandler: -+ r := httptest.NewRequest("GET", path, nil) -+ r.Host = a.domain -+ w := httptest.NewRecorder() -+ handler.ServeHTTP(w, r) -+ if w.Code != http.StatusOK { -+ return fmt.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) -+ } -+ body = w.Body.String() -+ } -+ -+ if !strings.HasPrefix(body, token) { -+ return fmt.Errorf("http token value = %q; want 'token-http-01.' prefix", body) -+ } -+ return nil -+} -+ -+func decodePayload(v interface{}, r io.Reader) error { -+ var req struct{ Payload string } -+ if err := json.NewDecoder(r).Decode(&req); err != nil { -+ return err -+ } -+ payload, err := base64.RawURLEncoding.DecodeString(req.Payload) -+ if err != nil { -+ return err -+ } -+ return json.Unmarshal(payload, v) -+} -+ -+func challengeToken(domain, challType string, authzID int) string { -+ return fmt.Sprintf("token-%s-%s-%d", domain, challType, authzID) -+} -+ -+func unique(a []string) []string { -+ seen := make(map[string]bool) -+ var res []string -+ for _, s := range a { -+ if s != "" && !seen[s] { -+ seen[s] = true -+ res = append(res, s) -+ } -+ } -+ return res -+} -diff --git a/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/golang.org/x/crypto/acme/autocert/listener.go -new file mode 100644 -index 000000000000..cb486097370f ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/autocert/listener.go -@@ -0,0 +1,155 @@ -+// 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 autocert -+ -+import ( -+ "crypto/tls" -+ "log" -+ "net" -+ "os" -+ "path/filepath" -+ "runtime" -+ "time" -+) -+ -+// NewListener returns a net.Listener that listens on the standard TLS -+// port (443) on all interfaces and returns *tls.Conn connections with -+// LetsEncrypt certificates for the provided domain or domains. -+// -+// It enables one-line HTTPS servers: -+// -+// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) -+// -+// NewListener is a convenience function for a common configuration. -+// More complex or custom configurations can use the autocert.Manager -+// type instead. -+// -+// Use of this function implies acceptance of the LetsEncrypt Terms of -+// Service. If domains is not empty, the provided domains are passed -+// to HostWhitelist. If domains is empty, the listener will do -+// LetsEncrypt challenges for any requested domain, which is not -+// recommended. -+// -+// Certificates are cached in a "golang-autocert" directory under an -+// operating system-specific cache or temp directory. This may not -+// be suitable for servers spanning multiple machines. -+// -+// The returned listener uses a *tls.Config that enables HTTP/2, and -+// should only be used with servers that support HTTP/2. -+// -+// The returned Listener also enables TCP keep-alives on the accepted -+// connections. The returned *tls.Conn are returned before their TLS -+// handshake has completed. -+func NewListener(domains ...string) net.Listener { -+ m := &Manager{ -+ Prompt: AcceptTOS, -+ } -+ if len(domains) > 0 { -+ m.HostPolicy = HostWhitelist(domains...) -+ } -+ dir := cacheDir() -+ if err := os.MkdirAll(dir, 0700); err != nil { -+ log.Printf("warning: autocert.NewListener not using a cache: %v", err) -+ } else { -+ m.Cache = DirCache(dir) -+ } -+ return m.Listener() -+} -+ -+// Listener listens on the standard TLS port (443) on all interfaces -+// and returns a net.Listener returning *tls.Conn connections. -+// -+// The returned listener uses a *tls.Config that enables HTTP/2, and -+// should only be used with servers that support HTTP/2. -+// -+// The returned Listener also enables TCP keep-alives on the accepted -+// connections. The returned *tls.Conn are returned before their TLS -+// handshake has completed. -+// -+// Unlike NewListener, it is the caller's responsibility to initialize -+// the Manager m's Prompt, Cache, HostPolicy, and other desired options. -+func (m *Manager) Listener() net.Listener { -+ ln := &listener{ -+ conf: m.TLSConfig(), -+ } -+ ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") -+ return ln -+} -+ -+type listener struct { -+ conf *tls.Config -+ -+ tcpListener net.Listener -+ tcpListenErr error -+} -+ -+func (ln *listener) Accept() (net.Conn, error) { -+ if ln.tcpListenErr != nil { -+ return nil, ln.tcpListenErr -+ } -+ conn, err := ln.tcpListener.Accept() -+ if err != nil { -+ return nil, err -+ } -+ tcpConn := conn.(*net.TCPConn) -+ -+ // Because Listener is a convenience function, help out with -+ // this too. This is not possible for the caller to set once -+ // we return a *tcp.Conn wrapping an inaccessible net.Conn. -+ // If callers don't want this, they can do things the manual -+ // way and tweak as needed. But this is what net/http does -+ // itself, so copy that. If net/http changes, we can change -+ // here too. -+ tcpConn.SetKeepAlive(true) -+ tcpConn.SetKeepAlivePeriod(3 * time.Minute) -+ -+ return tls.Server(tcpConn, ln.conf), nil -+} -+ -+func (ln *listener) Addr() net.Addr { -+ if ln.tcpListener != nil { -+ return ln.tcpListener.Addr() -+ } -+ // net.Listen failed. Return something non-nil in case callers -+ // call Addr before Accept: -+ return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443} -+} -+ -+func (ln *listener) Close() error { -+ if ln.tcpListenErr != nil { -+ return ln.tcpListenErr -+ } -+ return ln.tcpListener.Close() -+} -+ -+func homeDir() string { -+ if runtime.GOOS == "windows" { -+ return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") -+ } -+ if h := os.Getenv("HOME"); h != "" { -+ return h -+ } -+ return "/" -+} -+ -+func cacheDir() string { -+ const base = "golang-autocert" -+ switch runtime.GOOS { -+ case "darwin": -+ return filepath.Join(homeDir(), "Library", "Caches", base) -+ case "windows": -+ for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} { -+ if v := os.Getenv(ev); v != "" { -+ return filepath.Join(v, base) -+ } -+ } -+ // Worst case: -+ return filepath.Join(homeDir(), base) -+ } -+ if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" { -+ return filepath.Join(xdg, base) -+ } -+ return filepath.Join(homeDir(), ".cache", base) -+} -diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/golang.org/x/crypto/acme/autocert/renewal.go -new file mode 100644 -index 000000000000..0df7da78a6f6 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/autocert/renewal.go -@@ -0,0 +1,156 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "context" -+ "crypto" -+ "sync" -+ "time" -+) -+ -+// renewJitter is the maximum deviation from Manager.RenewBefore. -+const renewJitter = time.Hour -+ -+// domainRenewal tracks the state used by the periodic timers -+// renewing a single domain's cert. -+type domainRenewal struct { -+ m *Manager -+ ck certKey -+ key crypto.Signer -+ -+ timerMu sync.Mutex -+ timer *time.Timer -+ timerClose chan struct{} // if non-nil, renew closes this channel (and nils out the timer fields) instead of running -+} -+ -+// start starts a cert renewal timer at the time -+// defined by the certificate expiration time exp. -+// -+// If the timer is already started, calling start is a noop. -+func (dr *domainRenewal) start(exp time.Time) { -+ dr.timerMu.Lock() -+ defer dr.timerMu.Unlock() -+ if dr.timer != nil { -+ return -+ } -+ dr.timer = time.AfterFunc(dr.next(exp), dr.renew) -+} -+ -+// stop stops the cert renewal timer and waits for any in-flight calls to renew -+// to complete. If the timer is already stopped, calling stop is a noop. -+func (dr *domainRenewal) stop() { -+ dr.timerMu.Lock() -+ defer dr.timerMu.Unlock() -+ for { -+ if dr.timer == nil { -+ return -+ } -+ if dr.timer.Stop() { -+ dr.timer = nil -+ return -+ } else { -+ // dr.timer fired, and we acquired dr.timerMu before the renew callback did. -+ // (We know this because otherwise the renew callback would have reset dr.timer!) -+ timerClose := make(chan struct{}) -+ dr.timerClose = timerClose -+ dr.timerMu.Unlock() -+ <-timerClose -+ dr.timerMu.Lock() -+ } -+ } -+} -+ -+// renew is called periodically by a timer. -+// The first renew call is kicked off by dr.start. -+func (dr *domainRenewal) renew() { -+ dr.timerMu.Lock() -+ defer dr.timerMu.Unlock() -+ if dr.timerClose != nil { -+ close(dr.timerClose) -+ dr.timer, dr.timerClose = nil, nil -+ return -+ } -+ -+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) -+ defer cancel() -+ // TODO: rotate dr.key at some point? -+ next, err := dr.do(ctx) -+ if err != nil { -+ next = renewJitter / 2 -+ next += time.Duration(pseudoRand.int63n(int64(next))) -+ } -+ testDidRenewLoop(next, err) -+ dr.timer = time.AfterFunc(next, dr.renew) -+} -+ -+// updateState locks and replaces the relevant Manager.state item with the given -+// state. It additionally updates dr.key with the given state's key. -+func (dr *domainRenewal) updateState(state *certState) { -+ dr.m.stateMu.Lock() -+ defer dr.m.stateMu.Unlock() -+ dr.key = state.key -+ dr.m.state[dr.ck] = state -+} -+ -+// do is similar to Manager.createCert but it doesn't lock a Manager.state item. -+// Instead, it requests a new certificate independently and, upon success, -+// replaces dr.m.state item with a new one and updates cache for the given domain. -+// -+// It may lock and update the Manager.state if the expiration date of the currently -+// cached cert is far enough in the future. -+// -+// The returned value is a time interval after which the renewal should occur again. -+func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { -+ // a race is likely unavoidable in a distributed environment -+ // but we try nonetheless -+ if tlscert, err := dr.m.cacheGet(ctx, dr.ck); err == nil { -+ next := dr.next(tlscert.Leaf.NotAfter) -+ if next > dr.m.renewBefore()+renewJitter { -+ signer, ok := tlscert.PrivateKey.(crypto.Signer) -+ if ok { -+ state := &certState{ -+ key: signer, -+ cert: tlscert.Certificate, -+ leaf: tlscert.Leaf, -+ } -+ dr.updateState(state) -+ return next, nil -+ } -+ } -+ } -+ -+ der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.ck) -+ if err != nil { -+ return 0, err -+ } -+ state := &certState{ -+ key: dr.key, -+ cert: der, -+ leaf: leaf, -+ } -+ tlscert, err := state.tlscert() -+ if err != nil { -+ return 0, err -+ } -+ if err := dr.m.cachePut(ctx, dr.ck, tlscert); err != nil { -+ return 0, err -+ } -+ dr.updateState(state) -+ return dr.next(leaf.NotAfter), nil -+} -+ -+func (dr *domainRenewal) next(expiry time.Time) time.Duration { -+ d := expiry.Sub(dr.m.now()) - dr.m.renewBefore() -+ // add a bit of randomness to renew deadline -+ n := pseudoRand.int63n(int64(renewJitter)) -+ d -= time.Duration(n) -+ if d < 0 { -+ return 0 -+ } -+ return d -+} -+ -+var testDidRenewLoop = func(next time.Duration, err error) {} -diff --git a/vendor/golang.org/x/crypto/acme/http.go b/vendor/golang.org/x/crypto/acme/http.go -new file mode 100644 -index 000000000000..2b4c1a10d883 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/http.go -@@ -0,0 +1,325 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "bytes" -+ "context" -+ "crypto" -+ "crypto/rand" -+ "encoding/json" -+ "errors" -+ "fmt" -+ "io/ioutil" -+ "math/big" -+ "net/http" -+ "strconv" -+ "strings" -+ "time" -+) -+ -+// retryTimer encapsulates common logic for retrying unsuccessful requests. -+// It is not safe for concurrent use. -+type retryTimer struct { -+ // backoffFn provides backoff delay sequence for retries. -+ // See Client.RetryBackoff doc comment. -+ backoffFn func(n int, r *http.Request, res *http.Response) time.Duration -+ // n is the current retry attempt. -+ n int -+} -+ -+func (t *retryTimer) inc() { -+ t.n++ -+} -+ -+// backoff pauses the current goroutine as described in Client.RetryBackoff. -+func (t *retryTimer) backoff(ctx context.Context, r *http.Request, res *http.Response) error { -+ d := t.backoffFn(t.n, r, res) -+ if d <= 0 { -+ return fmt.Errorf("acme: no more retries for %s; tried %d time(s)", r.URL, t.n) -+ } -+ wakeup := time.NewTimer(d) -+ defer wakeup.Stop() -+ select { -+ case <-ctx.Done(): -+ return ctx.Err() -+ case <-wakeup.C: -+ return nil -+ } -+} -+ -+func (c *Client) retryTimer() *retryTimer { -+ f := c.RetryBackoff -+ if f == nil { -+ f = defaultBackoff -+ } -+ return &retryTimer{backoffFn: f} -+} -+ -+// defaultBackoff provides default Client.RetryBackoff implementation -+// using a truncated exponential backoff algorithm, -+// as described in Client.RetryBackoff. -+// -+// The n argument is always bounded between 1 and 30. -+// The returned value is always greater than 0. -+func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration { -+ const max = 10 * time.Second -+ var jitter time.Duration -+ if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { -+ // Set the minimum to 1ms to avoid a case where -+ // an invalid Retry-After value is parsed into 0 below, -+ // resulting in the 0 returned value which would unintentionally -+ // stop the retries. -+ jitter = (1 + time.Duration(x.Int64())) * time.Millisecond -+ } -+ if v, ok := res.Header["Retry-After"]; ok { -+ return retryAfter(v[0]) + jitter -+ } -+ -+ if n < 1 { -+ n = 1 -+ } -+ if n > 30 { -+ n = 30 -+ } -+ d := time.Duration(1< max { -+ return max -+ } -+ return d -+} -+ -+// retryAfter parses a Retry-After HTTP header value, -+// trying to convert v into an int (seconds) or use http.ParseTime otherwise. -+// It returns zero value if v cannot be parsed. -+func retryAfter(v string) time.Duration { -+ if i, err := strconv.Atoi(v); err == nil { -+ return time.Duration(i) * time.Second -+ } -+ t, err := http.ParseTime(v) -+ if err != nil { -+ return 0 -+ } -+ return t.Sub(timeNow()) -+} -+ -+// resOkay is a function that reports whether the provided response is okay. -+// It is expected to keep the response body unread. -+type resOkay func(*http.Response) bool -+ -+// wantStatus returns a function which reports whether the code -+// matches the status code of a response. -+func wantStatus(codes ...int) resOkay { -+ return func(res *http.Response) bool { -+ for _, code := range codes { -+ if code == res.StatusCode { -+ return true -+ } -+ } -+ return false -+ } -+} -+ -+// get issues an unsigned GET request to the specified URL. -+// It returns a non-error value only when ok reports true. -+// -+// get retries unsuccessful attempts according to c.RetryBackoff -+// until the context is done or a non-retriable error is received. -+func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Response, error) { -+ retry := c.retryTimer() -+ for { -+ req, err := http.NewRequest("GET", url, nil) -+ if err != nil { -+ return nil, err -+ } -+ res, err := c.doNoRetry(ctx, req) -+ switch { -+ case err != nil: -+ return nil, err -+ case ok(res): -+ return res, nil -+ case isRetriable(res.StatusCode): -+ retry.inc() -+ resErr := responseError(res) -+ res.Body.Close() -+ // Ignore the error value from retry.backoff -+ // and return the one from last retry, as received from the CA. -+ if retry.backoff(ctx, req, res) != nil { -+ return nil, resErr -+ } -+ default: -+ defer res.Body.Close() -+ return nil, responseError(res) -+ } -+ } -+} -+ -+// postAsGet is POST-as-GET, a replacement for GET in RFC8555 -+// as described in https://tools.ietf.org/html/rfc8555#section-6.3. -+// It makes a POST request in KID form with zero JWS payload. -+// See nopayload doc comments in jws.go. -+func (c *Client) postAsGet(ctx context.Context, url string, ok resOkay) (*http.Response, error) { -+ return c.post(ctx, nil, url, noPayload, ok) -+} -+ -+// post issues a signed POST request in JWS format using the provided key -+// to the specified URL. If key is nil, c.Key is used instead. -+// It returns a non-error value only when ok reports true. -+// -+// post retries unsuccessful attempts according to c.RetryBackoff -+// until the context is done or a non-retriable error is received. -+// It uses postNoRetry to make individual requests. -+func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body interface{}, ok resOkay) (*http.Response, error) { -+ retry := c.retryTimer() -+ for { -+ res, req, err := c.postNoRetry(ctx, key, url, body) -+ if err != nil { -+ return nil, err -+ } -+ if ok(res) { -+ return res, nil -+ } -+ resErr := responseError(res) -+ res.Body.Close() -+ switch { -+ // Check for bad nonce before isRetriable because it may have been returned -+ // with an unretriable response code such as 400 Bad Request. -+ case isBadNonce(resErr): -+ // Consider any previously stored nonce values to be invalid. -+ c.clearNonces() -+ case !isRetriable(res.StatusCode): -+ return nil, resErr -+ } -+ retry.inc() -+ // Ignore the error value from retry.backoff -+ // and return the one from last retry, as received from the CA. -+ if err := retry.backoff(ctx, req, res); err != nil { -+ return nil, resErr -+ } -+ } -+} -+ -+// postNoRetry signs the body with the given key and POSTs it to the provided url. -+// It is used by c.post to retry unsuccessful attempts. -+// The body argument must be JSON-serializable. -+// -+// If key argument is nil, c.Key is used to sign the request. -+// If key argument is nil and c.accountKID returns a non-zero keyID, -+// the request is sent in KID form. Otherwise, JWK form is used. -+// -+// In practice, when interfacing with RFC-compliant CAs most requests are sent in KID form -+// and JWK is used only when KID is unavailable: new account endpoint and certificate -+// revocation requests authenticated by a cert key. -+// See jwsEncodeJSON for other details. -+func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) { -+ kid := noKeyID -+ if key == nil { -+ if c.Key == nil { -+ return nil, nil, errors.New("acme: Client.Key must be populated to make POST requests") -+ } -+ key = c.Key -+ kid = c.accountKID(ctx) -+ } -+ nonce, err := c.popNonce(ctx, url) -+ if err != nil { -+ return nil, nil, err -+ } -+ b, err := jwsEncodeJSON(body, key, kid, nonce, url) -+ if err != nil { -+ return nil, nil, err -+ } -+ req, err := http.NewRequest("POST", url, bytes.NewReader(b)) -+ if err != nil { -+ return nil, nil, err -+ } -+ req.Header.Set("Content-Type", "application/jose+json") -+ res, err := c.doNoRetry(ctx, req) -+ if err != nil { -+ return nil, nil, err -+ } -+ c.addNonce(res.Header) -+ return res, req, nil -+} -+ -+// doNoRetry issues a request req, replacing its context (if any) with ctx. -+func (c *Client) doNoRetry(ctx context.Context, req *http.Request) (*http.Response, error) { -+ req.Header.Set("User-Agent", c.userAgent()) -+ res, err := c.httpClient().Do(req.WithContext(ctx)) -+ if err != nil { -+ select { -+ case <-ctx.Done(): -+ // Prefer the unadorned context error. -+ // (The acme package had tests assuming this, previously from ctxhttp's -+ // behavior, predating net/http supporting contexts natively) -+ // TODO(bradfitz): reconsider this in the future. But for now this -+ // requires no test updates. -+ return nil, ctx.Err() -+ default: -+ return nil, err -+ } -+ } -+ return res, nil -+} -+ -+func (c *Client) httpClient() *http.Client { -+ if c.HTTPClient != nil { -+ return c.HTTPClient -+ } -+ return http.DefaultClient -+} -+ -+// packageVersion is the version of the module that contains this package, for -+// sending as part of the User-Agent header. It's set in version_go112.go. -+var packageVersion string -+ -+// userAgent returns the User-Agent header value. It includes the package name, -+// the module version (if available), and the c.UserAgent value (if set). -+func (c *Client) userAgent() string { -+ ua := "golang.org/x/crypto/acme" -+ if packageVersion != "" { -+ ua += "@" + packageVersion -+ } -+ if c.UserAgent != "" { -+ ua = c.UserAgent + " " + ua -+ } -+ return ua -+} -+ -+// isBadNonce reports whether err is an ACME "badnonce" error. -+func isBadNonce(err error) bool { -+ // According to the spec badNonce is urn:ietf:params:acme:error:badNonce. -+ // However, ACME servers in the wild return their versions of the error. -+ // See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 -+ // and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66. -+ ae, ok := err.(*Error) -+ return ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") -+} -+ -+// isRetriable reports whether a request can be retried -+// based on the response status code. -+// -+// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code. -+// Callers should parse the response and check with isBadNonce. -+func isRetriable(code int) bool { -+ return code <= 399 || code >= 500 || code == http.StatusTooManyRequests -+} -+ -+// responseError creates an error of Error type from resp. -+func responseError(resp *http.Response) error { -+ // don't care if ReadAll returns an error: -+ // json.Unmarshal will fail in that case anyway -+ b, _ := ioutil.ReadAll(resp.Body) -+ e := &wireError{Status: resp.StatusCode} -+ if err := json.Unmarshal(b, e); err != nil { -+ // this is not a regular error response: -+ // populate detail with anything we received, -+ // e.Status will already contain HTTP response code value -+ e.Detail = string(b) -+ if e.Detail == "" { -+ e.Detail = resp.Status -+ } -+ } -+ return e.error(resp.Header) -+} -diff --git a/vendor/golang.org/x/crypto/acme/internal/acmeprobe/prober.go b/vendor/golang.org/x/crypto/acme/internal/acmeprobe/prober.go -new file mode 100644 -index 000000000000..471707de024e ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/internal/acmeprobe/prober.go -@@ -0,0 +1,433 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// The acmeprober program runs against an actual ACME CA implementation. -+// It spins up an HTTP server to fulfill authorization challenges -+// or execute a DNS script to provision a response to dns-01 challenge. -+// -+// For http-01 and tls-alpn-01 challenge types this requires the ACME CA -+// to be able to reach the HTTP server. -+// -+// A usage example: -+// -+// go run prober.go \ -+// -d https://acme-staging-v02.api.letsencrypt.org/directory \ -+// -f order \ -+// -t http-01 \ -+// -a :8080 \ -+// -domain some.example.org -+// -+// The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 -+// in order for the test to be able to fulfill http-01 challenge. -+// To test tls-alpn-01 challenge, 443 port would need to be tunneled -+// to 0.0.0.0:8080. -+// When running with dns-01 challenge type, use -s argument instead of -a. -+package main -+ -+import ( -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/tls" -+ "crypto/x509" -+ "encoding/pem" -+ "errors" -+ "flag" -+ "fmt" -+ "log" -+ "net" -+ "net/http" -+ "os" -+ "os/exec" -+ "strings" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+) -+ -+var ( -+ // ACME CA directory URL. -+ // Let's Encrypt v2 prod: https://acme-v02.api.letsencrypt.org/directory -+ // Let's Encrypt v2 staging: https://acme-staging-v02.api.letsencrypt.org/directory -+ // See the following for more CAs implementing ACME protocol: -+ // https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment#CAs_&_PKIs_that_offer_ACME_certificates -+ directory = flag.String("d", "", "ACME directory URL.") -+ reginfo = flag.String("r", "", "ACME account registration info.") -+ flow = flag.String("f", "", `Flow to run: "order" or "preauthz" (RFC8555).`) -+ chaltyp = flag.String("t", "", "Challenge type: tls-alpn-01, http-01 or dns-01.") -+ addr = flag.String("a", "", "Local server address for tls-alpn-01 and http-01.") -+ dnsscript = flag.String("s", "", "Script to run for provisioning dns-01 challenges.") -+ domain = flag.String("domain", "", "Space separate domain identifiers.") -+ ipaddr = flag.String("ip", "", "Space separate IP address identifiers.") -+) -+ -+func main() { -+ flag.Usage = func() { -+ fmt.Fprintln(flag.CommandLine.Output(), ` -+The prober program runs against an actual ACME CA implementation. -+It spins up an HTTP server to fulfill authorization challenges -+or execute a DNS script to provision a response to dns-01 challenge. -+ -+For http-01 and tls-alpn-01 challenge types this requires the ACME CA -+to be able to reach the HTTP server. -+ -+A usage example: -+ -+ go run prober.go \ -+ -d https://acme-staging-v02.api.letsencrypt.org/directory \ -+ -f order \ -+ -t http-01 \ -+ -a :8080 \ -+ -domain some.example.org -+ -+The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 -+in order for the test to be able to fulfill http-01 challenge. -+To test tls-alpn-01 challenge, 443 port would need to be tunneled -+to 0.0.0.0:8080. -+When running with dns-01 challenge type, use -s argument instead of -a. -+ `) -+ flag.PrintDefaults() -+ } -+ flag.Parse() -+ -+ identifiers := acme.DomainIDs(strings.Fields(*domain)...) -+ identifiers = append(identifiers, acme.IPIDs(strings.Fields(*ipaddr)...)...) -+ if len(identifiers) == 0 { -+ log.Fatal("at least one domain or IP addr identifier is required") -+ } -+ -+ // Duration of the whole run. -+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) -+ defer cancel() -+ -+ // Create and register a new account. -+ akey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ log.Fatal(err) -+ } -+ cl := &acme.Client{Key: akey, DirectoryURL: *directory} -+ a := &acme.Account{Contact: strings.Fields(*reginfo)} -+ if _, err := cl.Register(ctx, a, acme.AcceptTOS); err != nil { -+ log.Fatalf("Register: %v", err) -+ } -+ -+ // Run the desired flow test. -+ p := &prober{ -+ client: cl, -+ chalType: *chaltyp, -+ localAddr: *addr, -+ dnsScript: *dnsscript, -+ } -+ switch *flow { -+ case "order": -+ p.runOrder(ctx, identifiers) -+ case "preauthz": -+ p.runPreauthz(ctx, identifiers) -+ default: -+ log.Fatalf("unknown flow: %q", *flow) -+ } -+ if len(p.errors) > 0 { -+ os.Exit(1) -+ } -+} -+ -+type prober struct { -+ client *acme.Client -+ chalType string -+ localAddr string -+ dnsScript string -+ -+ errors []error -+} -+ -+func (p *prober) errorf(format string, a ...interface{}) { -+ err := fmt.Errorf(format, a...) -+ log.Print(err) -+ p.errors = append(p.errors, err) -+} -+ -+func (p *prober) runOrder(ctx context.Context, identifiers []acme.AuthzID) { -+ // Create a new order and pick a challenge. -+ // Note that Let's Encrypt will reply with 400 error:malformed -+ // "NotBefore and NotAfter are not supported" when providing a NotAfter -+ // value like WithOrderNotAfter(time.Now().Add(24 * time.Hour)). -+ o, err := p.client.AuthorizeOrder(ctx, identifiers) -+ if err != nil { -+ log.Fatalf("AuthorizeOrder: %v", err) -+ } -+ -+ var zurls []string -+ for _, u := range o.AuthzURLs { -+ z, err := p.client.GetAuthorization(ctx, u) -+ if err != nil { -+ log.Fatalf("GetAuthorization(%q): %v", u, err) -+ } -+ log.Printf("%+v", z) -+ if z.Status != acme.StatusPending { -+ log.Printf("authz status is %q; skipping", z.Status) -+ continue -+ } -+ if err := p.fulfill(ctx, z); err != nil { -+ log.Fatalf("fulfill(%s): %v", z.URI, err) -+ } -+ zurls = append(zurls, z.URI) -+ log.Printf("authorized for %+v", z.Identifier) -+ } -+ -+ log.Print("all challenges are done") -+ if _, err := p.client.WaitOrder(ctx, o.URI); err != nil { -+ log.Fatalf("WaitOrder(%q): %v", o.URI, err) -+ } -+ csr, certkey := newCSR(identifiers) -+ der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) -+ if err != nil { -+ log.Fatalf("CreateOrderCert: %v", err) -+ } -+ log.Printf("cert URL: %s", curl) -+ if err := checkCert(der, identifiers); err != nil { -+ p.errorf("invalid cert: %v", err) -+ } -+ -+ // Deactivate all authorizations we satisfied earlier. -+ for _, v := range zurls { -+ if err := p.client.RevokeAuthorization(ctx, v); err != nil { -+ p.errorf("RevokAuthorization(%q): %v", v, err) -+ continue -+ } -+ } -+ // Deactivate the account. We don't need it for any further calls. -+ if err := p.client.DeactivateReg(ctx); err != nil { -+ p.errorf("DeactivateReg: %v", err) -+ } -+ // Try revoking the issued cert using its private key. -+ if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { -+ p.errorf("RevokeCert: %v", err) -+ } -+} -+ -+func (p *prober) runPreauthz(ctx context.Context, identifiers []acme.AuthzID) { -+ dir, err := p.client.Discover(ctx) -+ if err != nil { -+ log.Fatalf("Discover: %v", err) -+ } -+ if dir.AuthzURL == "" { -+ log.Fatal("CA does not support pre-authorization") -+ } -+ -+ var zurls []string -+ for _, id := range identifiers { -+ z, err := authorize(ctx, p.client, id) -+ if err != nil { -+ log.Fatalf("AuthorizeID(%+v): %v", z, err) -+ } -+ if z.Status == acme.StatusValid { -+ log.Printf("authz %s is valid; skipping", z.URI) -+ continue -+ } -+ if err := p.fulfill(ctx, z); err != nil { -+ log.Fatalf("fulfill(%s): %v", z.URI, err) -+ } -+ zurls = append(zurls, z.URI) -+ log.Printf("authorized for %+v", id) -+ } -+ -+ // We should be all set now. -+ // Expect all authorizations to be satisfied. -+ log.Print("all challenges are done") -+ o, err := p.client.AuthorizeOrder(ctx, identifiers) -+ if err != nil { -+ log.Fatalf("AuthorizeOrder: %v", err) -+ } -+ waitCtx, cancel := context.WithTimeout(ctx, time.Minute) -+ defer cancel() -+ if _, err := p.client.WaitOrder(waitCtx, o.URI); err != nil { -+ log.Fatalf("WaitOrder(%q): %v", o.URI, err) -+ } -+ csr, certkey := newCSR(identifiers) -+ der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) -+ if err != nil { -+ log.Fatalf("CreateOrderCert: %v", err) -+ } -+ log.Printf("cert URL: %s", curl) -+ if err := checkCert(der, identifiers); err != nil { -+ p.errorf("invalid cert: %v", err) -+ } -+ -+ // Deactivate all authorizations we satisfied earlier. -+ for _, v := range zurls { -+ if err := p.client.RevokeAuthorization(ctx, v); err != nil { -+ p.errorf("RevokeAuthorization(%q): %v", v, err) -+ continue -+ } -+ } -+ // Deactivate the account. We don't need it for any further calls. -+ if err := p.client.DeactivateReg(ctx); err != nil { -+ p.errorf("DeactivateReg: %v", err) -+ } -+ // Try revoking the issued cert using its private key. -+ if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { -+ p.errorf("RevokeCert: %v", err) -+ } -+} -+ -+func (p *prober) fulfill(ctx context.Context, z *acme.Authorization) error { -+ var chal *acme.Challenge -+ for i, c := range z.Challenges { -+ log.Printf("challenge %d: %+v", i, c) -+ if c.Type == p.chalType { -+ log.Printf("picked %s for authz %s", c.URI, z.URI) -+ chal = c -+ } -+ } -+ if chal == nil { -+ return fmt.Errorf("challenge type %q wasn't offered for authz %s", p.chalType, z.URI) -+ } -+ -+ switch chal.Type { -+ case "tls-alpn-01": -+ return p.runTLSALPN01(ctx, z, chal) -+ case "http-01": -+ return p.runHTTP01(ctx, z, chal) -+ case "dns-01": -+ return p.runDNS01(ctx, z, chal) -+ default: -+ return fmt.Errorf("unknown challenge type %q", chal.Type) -+ } -+} -+ -+func (p *prober) runTLSALPN01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { -+ tokenCert, err := p.client.TLSALPN01ChallengeCert(chal.Token, z.Identifier.Value) -+ if err != nil { -+ return fmt.Errorf("TLSALPN01ChallengeCert: %v", err) -+ } -+ s := &http.Server{ -+ Addr: p.localAddr, -+ TLSConfig: &tls.Config{ -+ NextProtos: []string{acme.ALPNProto}, -+ GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { -+ log.Printf("hello: %+v", hello) -+ return &tokenCert, nil -+ }, -+ }, -+ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ log.Printf("%s %s", r.Method, r.URL) -+ w.WriteHeader(http.StatusNotFound) -+ }), -+ } -+ go s.ListenAndServeTLS("", "") -+ defer s.Close() -+ -+ if _, err := p.client.Accept(ctx, chal); err != nil { -+ return fmt.Errorf("Accept(%q): %v", chal.URI, err) -+ } -+ _, zerr := p.client.WaitAuthorization(ctx, z.URI) -+ return zerr -+} -+ -+func (p *prober) runHTTP01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { -+ body, err := p.client.HTTP01ChallengeResponse(chal.Token) -+ if err != nil { -+ return fmt.Errorf("HTTP01ChallengeResponse: %v", err) -+ } -+ s := &http.Server{ -+ Addr: p.localAddr, -+ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ log.Printf("%s %s", r.Method, r.URL) -+ if r.URL.Path != p.client.HTTP01ChallengePath(chal.Token) { -+ w.WriteHeader(http.StatusNotFound) -+ return -+ } -+ w.Write([]byte(body)) -+ }), -+ } -+ go s.ListenAndServe() -+ defer s.Close() -+ -+ if _, err := p.client.Accept(ctx, chal); err != nil { -+ return fmt.Errorf("Accept(%q): %v", chal.URI, err) -+ } -+ _, zerr := p.client.WaitAuthorization(ctx, z.URI) -+ return zerr -+} -+ -+func (p *prober) runDNS01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { -+ token, err := p.client.DNS01ChallengeRecord(chal.Token) -+ if err != nil { -+ return fmt.Errorf("DNS01ChallengeRecord: %v", err) -+ } -+ -+ name := fmt.Sprintf("_acme-challenge.%s", z.Identifier.Value) -+ cmd := exec.CommandContext(ctx, p.dnsScript, name, token) -+ cmd.Stdin = os.Stdin -+ cmd.Stdout = os.Stdout -+ cmd.Stderr = os.Stderr -+ if err := cmd.Run(); err != nil { -+ return fmt.Errorf("%s: %v", p.dnsScript, err) -+ } -+ -+ if _, err := p.client.Accept(ctx, chal); err != nil { -+ return fmt.Errorf("Accept(%q): %v", chal.URI, err) -+ } -+ _, zerr := p.client.WaitAuthorization(ctx, z.URI) -+ return zerr -+} -+ -+func authorize(ctx context.Context, client *acme.Client, id acme.AuthzID) (*acme.Authorization, error) { -+ if id.Type == "ip" { -+ return client.AuthorizeIP(ctx, id.Value) -+ } -+ return client.Authorize(ctx, id.Value) -+} -+ -+func checkCert(derChain [][]byte, id []acme.AuthzID) error { -+ if len(derChain) == 0 { -+ return errors.New("cert chain is zero bytes") -+ } -+ for i, b := range derChain { -+ crt, err := x509.ParseCertificate(b) -+ if err != nil { -+ return fmt.Errorf("%d: ParseCertificate: %v", i, err) -+ } -+ log.Printf("%d: serial: 0x%s", i, crt.SerialNumber) -+ log.Printf("%d: subject: %s", i, crt.Subject) -+ log.Printf("%d: issuer: %s", i, crt.Issuer) -+ log.Printf("%d: expires in %.1f day(s)", i, time.Until(crt.NotAfter).Hours()/24) -+ if i > 0 { // not a leaf cert -+ continue -+ } -+ p := &pem.Block{Type: "CERTIFICATE", Bytes: b} -+ log.Printf("%d: leaf:\n%s", i, pem.EncodeToMemory(p)) -+ for _, v := range id { -+ if err := crt.VerifyHostname(v.Value); err != nil { -+ return err -+ } -+ } -+ } -+ return nil -+} -+ -+func newCSR(identifiers []acme.AuthzID) ([]byte, crypto.Signer) { -+ var csr x509.CertificateRequest -+ for _, id := range identifiers { -+ switch id.Type { -+ case "dns": -+ csr.DNSNames = append(csr.DNSNames, id.Value) -+ case "ip": -+ csr.IPAddresses = append(csr.IPAddresses, net.ParseIP(id.Value)) -+ default: -+ panic(fmt.Sprintf("newCSR: unknown identifier type %q", id.Type)) -+ } -+ } -+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ panic(fmt.Sprintf("newCSR: ecdsa.GenerateKey for a cert: %v", err)) -+ } -+ b, err := x509.CreateCertificateRequest(rand.Reader, &csr, k) -+ if err != nil { -+ panic(fmt.Sprintf("newCSR: x509.CreateCertificateRequest: %v", err)) -+ } -+ return b, k -+} -diff --git a/vendor/golang.org/x/crypto/acme/jws.go b/vendor/golang.org/x/crypto/acme/jws.go -new file mode 100644 -index 000000000000..403e5b0c233c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/jws.go -@@ -0,0 +1,232 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/hmac" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/sha256" -+ _ "crypto/sha512" // need for EC keys -+ "encoding/asn1" -+ "encoding/base64" -+ "encoding/json" -+ "errors" -+ "fmt" -+ "math/big" -+) -+ -+// KeyID is the account key identity provided by a CA during registration. -+type KeyID string -+ -+// noKeyID indicates that jwsEncodeJSON should compute and use JWK instead of a KID. -+// See jwsEncodeJSON for details. -+const noKeyID = KeyID("") -+ -+// noPayload indicates jwsEncodeJSON will encode zero-length octet string -+// in a JWS request. This is called POST-as-GET in RFC 8555 and is used to make -+// authenticated GET requests via POSTing with an empty payload. -+// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details. -+const noPayload = "" -+ -+// jsonWebSignature can be easily serialized into a JWS following -+// https://tools.ietf.org/html/rfc7515#section-3.2. -+type jsonWebSignature struct { -+ Protected string `json:"protected"` -+ Payload string `json:"payload"` -+ Sig string `json:"signature"` -+} -+ -+// jwsEncodeJSON signs claimset using provided key and a nonce. -+// The result is serialized in JSON format containing either kid or jwk -+// fields based on the provided KeyID value. -+// -+// If kid is non-empty, its quoted value is inserted in the protected head -+// as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted -+// as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive. -+// -+// See https://tools.ietf.org/html/rfc7515#section-7. -+func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, url string) ([]byte, error) { -+ if key == nil { -+ return nil, errors.New("nil key") -+ } -+ alg, sha := jwsHasher(key.Public()) -+ if alg == "" || !sha.Available() { -+ return nil, ErrUnsupportedKey -+ } -+ var phead string -+ switch kid { -+ case noKeyID: -+ jwk, err := jwkEncode(key.Public()) -+ if err != nil { -+ return nil, err -+ } -+ phead = fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q,"url":%q}`, alg, jwk, nonce, url) -+ default: -+ phead = fmt.Sprintf(`{"alg":%q,"kid":%q,"nonce":%q,"url":%q}`, alg, kid, nonce, url) -+ } -+ phead = base64.RawURLEncoding.EncodeToString([]byte(phead)) -+ var payload string -+ if claimset != noPayload { -+ cs, err := json.Marshal(claimset) -+ if err != nil { -+ return nil, err -+ } -+ payload = base64.RawURLEncoding.EncodeToString(cs) -+ } -+ hash := sha.New() -+ hash.Write([]byte(phead + "." + payload)) -+ sig, err := jwsSign(key, sha, hash.Sum(nil)) -+ if err != nil { -+ return nil, err -+ } -+ enc := jsonWebSignature{ -+ Protected: phead, -+ Payload: payload, -+ Sig: base64.RawURLEncoding.EncodeToString(sig), -+ } -+ return json.Marshal(&enc) -+} -+ -+// jwsWithMAC creates and signs a JWS using the given key and the HS256 -+// algorithm. kid and url are included in the protected header. rawPayload -+// should not be base64-URL-encoded. -+func jwsWithMAC(key []byte, kid, url string, rawPayload []byte) (*jsonWebSignature, error) { -+ if len(key) == 0 { -+ return nil, errors.New("acme: cannot sign JWS with an empty MAC key") -+ } -+ header := struct { -+ Algorithm string `json:"alg"` -+ KID string `json:"kid"` -+ URL string `json:"url,omitempty"` -+ }{ -+ // Only HMAC-SHA256 is supported. -+ Algorithm: "HS256", -+ KID: kid, -+ URL: url, -+ } -+ rawProtected, err := json.Marshal(header) -+ if err != nil { -+ return nil, err -+ } -+ protected := base64.RawURLEncoding.EncodeToString(rawProtected) -+ payload := base64.RawURLEncoding.EncodeToString(rawPayload) -+ -+ h := hmac.New(sha256.New, key) -+ if _, err := h.Write([]byte(protected + "." + payload)); err != nil { -+ return nil, err -+ } -+ mac := h.Sum(nil) -+ -+ return &jsonWebSignature{ -+ Protected: protected, -+ Payload: payload, -+ Sig: base64.RawURLEncoding.EncodeToString(mac), -+ }, nil -+} -+ -+// jwkEncode encodes public part of an RSA or ECDSA key into a JWK. -+// The result is also suitable for creating a JWK thumbprint. -+// https://tools.ietf.org/html/rfc7517 -+func jwkEncode(pub crypto.PublicKey) (string, error) { -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ // https://tools.ietf.org/html/rfc7518#section-6.3.1 -+ n := pub.N -+ e := big.NewInt(int64(pub.E)) -+ // Field order is important. -+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. -+ return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`, -+ base64.RawURLEncoding.EncodeToString(e.Bytes()), -+ base64.RawURLEncoding.EncodeToString(n.Bytes()), -+ ), nil -+ case *ecdsa.PublicKey: -+ // https://tools.ietf.org/html/rfc7518#section-6.2.1 -+ p := pub.Curve.Params() -+ n := p.BitSize / 8 -+ if p.BitSize%8 != 0 { -+ n++ -+ } -+ x := pub.X.Bytes() -+ if n > len(x) { -+ x = append(make([]byte, n-len(x)), x...) -+ } -+ y := pub.Y.Bytes() -+ if n > len(y) { -+ y = append(make([]byte, n-len(y)), y...) -+ } -+ // Field order is important. -+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. -+ return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`, -+ p.Name, -+ base64.RawURLEncoding.EncodeToString(x), -+ base64.RawURLEncoding.EncodeToString(y), -+ ), nil -+ } -+ return "", ErrUnsupportedKey -+} -+ -+// jwsSign signs the digest using the given key. -+// The hash is unused for ECDSA keys. -+func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) { -+ switch pub := key.Public().(type) { -+ case *rsa.PublicKey: -+ return key.Sign(rand.Reader, digest, hash) -+ case *ecdsa.PublicKey: -+ sigASN1, err := key.Sign(rand.Reader, digest, hash) -+ if err != nil { -+ return nil, err -+ } -+ -+ var rs struct{ R, S *big.Int } -+ if _, err := asn1.Unmarshal(sigASN1, &rs); err != nil { -+ return nil, err -+ } -+ -+ rb, sb := rs.R.Bytes(), rs.S.Bytes() -+ size := pub.Params().BitSize / 8 -+ if size%8 > 0 { -+ size++ -+ } -+ sig := make([]byte, size*2) -+ copy(sig[size-len(rb):], rb) -+ copy(sig[size*2-len(sb):], sb) -+ return sig, nil -+ } -+ return nil, ErrUnsupportedKey -+} -+ -+// jwsHasher indicates suitable JWS algorithm name and a hash function -+// to use for signing a digest with the provided key. -+// It returns ("", 0) if the key is not supported. -+func jwsHasher(pub crypto.PublicKey) (string, crypto.Hash) { -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ return "RS256", crypto.SHA256 -+ case *ecdsa.PublicKey: -+ switch pub.Params().Name { -+ case "P-256": -+ return "ES256", crypto.SHA256 -+ case "P-384": -+ return "ES384", crypto.SHA384 -+ case "P-521": -+ return "ES512", crypto.SHA512 -+ } -+ } -+ return "", 0 -+} -+ -+// JWKThumbprint creates a JWK thumbprint out of pub -+// as specified in https://tools.ietf.org/html/rfc7638. -+func JWKThumbprint(pub crypto.PublicKey) (string, error) { -+ jwk, err := jwkEncode(pub) -+ if err != nil { -+ return "", err -+ } -+ b := sha256.Sum256([]byte(jwk)) -+ return base64.RawURLEncoding.EncodeToString(b[:]), nil -+} -diff --git a/vendor/golang.org/x/crypto/acme/rfc8555.go b/vendor/golang.org/x/crypto/acme/rfc8555.go -new file mode 100644 -index 000000000000..928a5aa03631 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/rfc8555.go -@@ -0,0 +1,438 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "context" -+ "crypto" -+ "encoding/base64" -+ "encoding/json" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "io" -+ "io/ioutil" -+ "net/http" -+ "time" -+) -+ -+// DeactivateReg permanently disables an existing account associated with c.Key. -+// A deactivated account can no longer request certificate issuance or access -+// resources related to the account, such as orders or authorizations. -+// -+// It only works with CAs implementing RFC 8555. -+func (c *Client) DeactivateReg(ctx context.Context) error { -+ url := string(c.accountKID(ctx)) -+ if url == "" { -+ return ErrNoAccount -+ } -+ req := json.RawMessage(`{"status": "deactivated"}`) -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return err -+ } -+ res.Body.Close() -+ return nil -+} -+ -+// registerRFC is equivalent to c.Register but for CAs implementing RFC 8555. -+// It expects c.Discover to have already been called. -+func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { -+ c.cacheMu.Lock() // guard c.kid access -+ defer c.cacheMu.Unlock() -+ -+ req := struct { -+ TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"` -+ Contact []string `json:"contact,omitempty"` -+ ExternalAccountBinding *jsonWebSignature `json:"externalAccountBinding,omitempty"` -+ }{ -+ Contact: acct.Contact, -+ } -+ if c.dir.Terms != "" { -+ req.TermsAgreed = prompt(c.dir.Terms) -+ } -+ -+ // set 'externalAccountBinding' field if requested -+ if acct.ExternalAccountBinding != nil { -+ eabJWS, err := c.encodeExternalAccountBinding(acct.ExternalAccountBinding) -+ if err != nil { -+ return nil, fmt.Errorf("acme: failed to encode external account binding: %v", err) -+ } -+ req.ExternalAccountBinding = eabJWS -+ } -+ -+ res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus( -+ http.StatusOK, // account with this key already registered -+ http.StatusCreated, // new account created -+ )) -+ if err != nil { -+ return nil, err -+ } -+ -+ defer res.Body.Close() -+ a, err := responseAccount(res) -+ if err != nil { -+ return nil, err -+ } -+ // Cache Account URL even if we return an error to the caller. -+ // It is by all means a valid and usable "kid" value for future requests. -+ c.KID = KeyID(a.URI) -+ if res.StatusCode == http.StatusOK { -+ return nil, ErrAccountAlreadyExists -+ } -+ return a, nil -+} -+ -+// encodeExternalAccountBinding will encode an external account binding stanza -+// as described in https://tools.ietf.org/html/rfc8555#section-7.3.4. -+func (c *Client) encodeExternalAccountBinding(eab *ExternalAccountBinding) (*jsonWebSignature, error) { -+ jwk, err := jwkEncode(c.Key.Public()) -+ if err != nil { -+ return nil, err -+ } -+ return jwsWithMAC(eab.Key, eab.KID, c.dir.RegURL, []byte(jwk)) -+} -+ -+// updateRegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555. -+// It expects c.Discover to have already been called. -+func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) { -+ url := string(c.accountKID(ctx)) -+ if url == "" { -+ return nil, ErrNoAccount -+ } -+ req := struct { -+ Contact []string `json:"contact,omitempty"` -+ }{ -+ Contact: a.Contact, -+ } -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ return responseAccount(res) -+} -+ -+// getGegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555. -+// It expects c.Discover to have already been called. -+func (c *Client) getRegRFC(ctx context.Context) (*Account, error) { -+ req := json.RawMessage(`{"onlyReturnExisting": true}`) -+ res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK)) -+ if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" { -+ return nil, ErrNoAccount -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ defer res.Body.Close() -+ return responseAccount(res) -+} -+ -+func responseAccount(res *http.Response) (*Account, error) { -+ var v struct { -+ Status string -+ Contact []string -+ Orders string -+ } -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid account response: %v", err) -+ } -+ return &Account{ -+ URI: res.Header.Get("Location"), -+ Status: v.Status, -+ Contact: v.Contact, -+ OrdersURL: v.Orders, -+ }, nil -+} -+ -+// AuthorizeOrder initiates the order-based application for certificate issuance, -+// as opposed to pre-authorization in Authorize. -+// It is only supported by CAs implementing RFC 8555. -+// -+// The caller then needs to fetch each authorization with GetAuthorization, -+// identify those with StatusPending status and fulfill a challenge using Accept. -+// Once all authorizations are satisfied, the caller will typically want to poll -+// order status using WaitOrder until it's in StatusReady state. -+// To finalize the order and obtain a certificate, the caller submits a CSR with CreateOrderCert. -+func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderOption) (*Order, error) { -+ dir, err := c.Discover(ctx) -+ if err != nil { -+ return nil, err -+ } -+ -+ req := struct { -+ Identifiers []wireAuthzID `json:"identifiers"` -+ NotBefore string `json:"notBefore,omitempty"` -+ NotAfter string `json:"notAfter,omitempty"` -+ }{} -+ for _, v := range id { -+ req.Identifiers = append(req.Identifiers, wireAuthzID{ -+ Type: v.Type, -+ Value: v.Value, -+ }) -+ } -+ for _, o := range opt { -+ switch o := o.(type) { -+ case orderNotBeforeOpt: -+ req.NotBefore = time.Time(o).Format(time.RFC3339) -+ case orderNotAfterOpt: -+ req.NotAfter = time.Time(o).Format(time.RFC3339) -+ default: -+ // Package's fault if we let this happen. -+ panic(fmt.Sprintf("unsupported order option type %T", o)) -+ } -+ } -+ -+ res, err := c.post(ctx, nil, dir.OrderURL, req, wantStatus(http.StatusCreated)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ return responseOrder(res) -+} -+ -+// GetOrder retrives an order identified by the given URL. -+// For orders created with AuthorizeOrder, the url value is Order.URI. -+// -+// If a caller needs to poll an order until its status is final, -+// see the WaitOrder method. -+func (c *Client) GetOrder(ctx context.Context, url string) (*Order, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ return responseOrder(res) -+} -+ -+// WaitOrder polls an order from the given URL until it is in one of the final states, -+// StatusReady, StatusValid or StatusInvalid, the CA responded with a non-retryable error -+// or the context is done. -+// -+// It returns a non-nil Order only if its Status is StatusReady or StatusValid. -+// In all other cases WaitOrder returns an error. -+// If the Status is StatusInvalid, the returned error is of type *OrderError. -+func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ for { -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ o, err := responseOrder(res) -+ res.Body.Close() -+ switch { -+ case err != nil: -+ // Skip and retry. -+ case o.Status == StatusInvalid: -+ return nil, &OrderError{OrderURL: o.URI, Status: o.Status} -+ case o.Status == StatusReady || o.Status == StatusValid: -+ return o, nil -+ } -+ -+ d := retryAfter(res.Header.Get("Retry-After")) -+ if d == 0 { -+ // Default retry-after. -+ // Same reasoning as in WaitAuthorization. -+ d = time.Second -+ } -+ t := time.NewTimer(d) -+ select { -+ case <-ctx.Done(): -+ t.Stop() -+ return nil, ctx.Err() -+ case <-t.C: -+ // Retry. -+ } -+ } -+} -+ -+func responseOrder(res *http.Response) (*Order, error) { -+ var v struct { -+ Status string -+ Expires time.Time -+ Identifiers []wireAuthzID -+ NotBefore time.Time -+ NotAfter time.Time -+ Error *wireError -+ Authorizations []string -+ Finalize string -+ Certificate string -+ } -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: error reading order: %v", err) -+ } -+ o := &Order{ -+ URI: res.Header.Get("Location"), -+ Status: v.Status, -+ Expires: v.Expires, -+ NotBefore: v.NotBefore, -+ NotAfter: v.NotAfter, -+ AuthzURLs: v.Authorizations, -+ FinalizeURL: v.Finalize, -+ CertURL: v.Certificate, -+ } -+ for _, id := range v.Identifiers { -+ o.Identifiers = append(o.Identifiers, AuthzID{Type: id.Type, Value: id.Value}) -+ } -+ if v.Error != nil { -+ o.Error = v.Error.error(nil /* headers */) -+ } -+ return o, nil -+} -+ -+// CreateOrderCert submits the CSR (Certificate Signing Request) to a CA at the specified URL. -+// The URL is the FinalizeURL field of an Order created with AuthorizeOrder. -+// -+// If the bundle argument is true, the returned value also contain the CA (issuer) -+// certificate chain. Otherwise, only a leaf certificate is returned. -+// The returned URL can be used to re-fetch the certificate using FetchCert. -+// -+// This method is only supported by CAs implementing RFC 8555. See CreateCert for pre-RFC CAs. -+// -+// CreateOrderCert returns an error if the CA's response is unreasonably large. -+// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features. -+func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bundle bool) (der [][]byte, certURL string, err error) { -+ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID -+ return nil, "", err -+ } -+ -+ // RFC describes this as "finalize order" request. -+ req := struct { -+ CSR string `json:"csr"` -+ }{ -+ CSR: base64.RawURLEncoding.EncodeToString(csr), -+ } -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, "", err -+ } -+ defer res.Body.Close() -+ o, err := responseOrder(res) -+ if err != nil { -+ return nil, "", err -+ } -+ -+ // Wait for CA to issue the cert if they haven't. -+ if o.Status != StatusValid { -+ o, err = c.WaitOrder(ctx, o.URI) -+ } -+ if err != nil { -+ return nil, "", err -+ } -+ // The only acceptable status post finalize and WaitOrder is "valid". -+ if o.Status != StatusValid { -+ return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status} -+ } -+ crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle) -+ return crt, o.CertURL, err -+} -+ -+// fetchCertRFC downloads issued certificate from the given URL. -+// It expects the CA to respond with PEM-encoded certificate chain. -+// -+// The URL argument is the CertURL field of Order. -+func (c *Client) fetchCertRFC(ctx context.Context, url string, bundle bool) ([][]byte, error) { -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ // Get all the bytes up to a sane maximum. -+ // Account very roughly for base64 overhead. -+ const max = maxCertChainSize + maxCertChainSize/33 -+ b, err := ioutil.ReadAll(io.LimitReader(res.Body, max+1)) -+ if err != nil { -+ return nil, fmt.Errorf("acme: fetch cert response stream: %v", err) -+ } -+ if len(b) > max { -+ return nil, errors.New("acme: certificate chain is too big") -+ } -+ -+ // Decode PEM chain. -+ var chain [][]byte -+ for { -+ var p *pem.Block -+ p, b = pem.Decode(b) -+ if p == nil { -+ break -+ } -+ if p.Type != "CERTIFICATE" { -+ return nil, fmt.Errorf("acme: invalid PEM cert type %q", p.Type) -+ } -+ -+ chain = append(chain, p.Bytes) -+ if !bundle { -+ return chain, nil -+ } -+ if len(chain) > maxChainLen { -+ return nil, errors.New("acme: certificate chain is too long") -+ } -+ } -+ if len(chain) == 0 { -+ return nil, errors.New("acme: certificate chain is empty") -+ } -+ return chain, nil -+} -+ -+// sends a cert revocation request in either JWK form when key is non-nil or KID form otherwise. -+func (c *Client) revokeCertRFC(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { -+ req := &struct { -+ Cert string `json:"certificate"` -+ Reason int `json:"reason"` -+ }{ -+ Cert: base64.RawURLEncoding.EncodeToString(cert), -+ Reason: int(reason), -+ } -+ res, err := c.post(ctx, key, c.dir.RevokeURL, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ if isAlreadyRevoked(err) { -+ // Assume it is not an error to revoke an already revoked cert. -+ return nil -+ } -+ return err -+ } -+ defer res.Body.Close() -+ return nil -+} -+ -+func isAlreadyRevoked(err error) bool { -+ e, ok := err.(*Error) -+ return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked" -+} -+ -+// ListCertAlternates retrieves any alternate certificate chain URLs for the -+// given certificate chain URL. These alternate URLs can be passed to FetchCert -+// in order to retrieve the alternate certificate chains. -+// -+// If there are no alternate issuer certificate chains, a nil slice will be -+// returned. -+func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error) { -+ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ // We don't need the body but we need to discard it so we don't end up -+ // preventing keep-alive -+ if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { -+ return nil, fmt.Errorf("acme: cert alternates response stream: %v", err) -+ } -+ alts := linkHeader(res.Header, "alternate") -+ return alts, nil -+} -diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go -new file mode 100644 -index 000000000000..67b825201e50 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/types.go -@@ -0,0 +1,614 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "crypto" -+ "crypto/x509" -+ "errors" -+ "fmt" -+ "net/http" -+ "strings" -+ "time" -+) -+ -+// ACME status values of Account, Order, Authorization and Challenge objects. -+// See https://tools.ietf.org/html/rfc8555#section-7.1.6 for details. -+const ( -+ StatusDeactivated = "deactivated" -+ StatusExpired = "expired" -+ StatusInvalid = "invalid" -+ StatusPending = "pending" -+ StatusProcessing = "processing" -+ StatusReady = "ready" -+ StatusRevoked = "revoked" -+ StatusUnknown = "unknown" -+ StatusValid = "valid" -+) -+ -+// CRLReasonCode identifies the reason for a certificate revocation. -+type CRLReasonCode int -+ -+// CRL reason codes as defined in RFC 5280. -+const ( -+ CRLReasonUnspecified CRLReasonCode = 0 -+ CRLReasonKeyCompromise CRLReasonCode = 1 -+ CRLReasonCACompromise CRLReasonCode = 2 -+ CRLReasonAffiliationChanged CRLReasonCode = 3 -+ CRLReasonSuperseded CRLReasonCode = 4 -+ CRLReasonCessationOfOperation CRLReasonCode = 5 -+ CRLReasonCertificateHold CRLReasonCode = 6 -+ CRLReasonRemoveFromCRL CRLReasonCode = 8 -+ CRLReasonPrivilegeWithdrawn CRLReasonCode = 9 -+ CRLReasonAACompromise CRLReasonCode = 10 -+) -+ -+var ( -+ // ErrUnsupportedKey is returned when an unsupported key type is encountered. -+ ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported") -+ -+ // ErrAccountAlreadyExists indicates that the Client's key has already been registered -+ // with the CA. It is returned by Register method. -+ ErrAccountAlreadyExists = errors.New("acme: account already exists") -+ -+ // ErrNoAccount indicates that the Client's key has not been registered with the CA. -+ ErrNoAccount = errors.New("acme: account does not exist") -+) -+ -+// A Subproblem describes an ACME subproblem as reported in an Error. -+type Subproblem struct { -+ // Type is a URI reference that identifies the problem type, -+ // typically in a "urn:acme:error:xxx" form. -+ Type string -+ // Detail is a human-readable explanation specific to this occurrence of the problem. -+ Detail string -+ // Instance indicates a URL that the client should direct a human user to visit -+ // in order for instructions on how to agree to the updated Terms of Service. -+ // In such an event CA sets StatusCode to 403, Type to -+ // "urn:ietf:params:acme:error:userActionRequired", and adds a Link header with relation -+ // "terms-of-service" containing the latest TOS URL. -+ Instance string -+ // Identifier may contain the ACME identifier that the error is for. -+ Identifier *AuthzID -+} -+ -+func (sp Subproblem) String() string { -+ str := fmt.Sprintf("%s: ", sp.Type) -+ if sp.Identifier != nil { -+ str += fmt.Sprintf("[%s: %s] ", sp.Identifier.Type, sp.Identifier.Value) -+ } -+ str += sp.Detail -+ return str -+} -+ -+// Error is an ACME error, defined in Problem Details for HTTP APIs doc -+// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem. -+type Error struct { -+ // StatusCode is The HTTP status code generated by the origin server. -+ StatusCode int -+ // ProblemType is a URI reference that identifies the problem type, -+ // typically in a "urn:acme:error:xxx" form. -+ ProblemType string -+ // Detail is a human-readable explanation specific to this occurrence of the problem. -+ Detail string -+ // Instance indicates a URL that the client should direct a human user to visit -+ // in order for instructions on how to agree to the updated Terms of Service. -+ // In such an event CA sets StatusCode to 403, ProblemType to -+ // "urn:ietf:params:acme:error:userActionRequired" and a Link header with relation -+ // "terms-of-service" containing the latest TOS URL. -+ Instance string -+ // Header is the original server error response headers. -+ // It may be nil. -+ Header http.Header -+ // Subproblems may contain more detailed information about the individual problems -+ // that caused the error. This field is only sent by RFC 8555 compatible ACME -+ // servers. Defined in RFC 8555 Section 6.7.1. -+ Subproblems []Subproblem -+} -+ -+func (e *Error) Error() string { -+ str := fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail) -+ if len(e.Subproblems) > 0 { -+ str += fmt.Sprintf("; subproblems:") -+ for _, sp := range e.Subproblems { -+ str += fmt.Sprintf("\n\t%s", sp) -+ } -+ } -+ return str -+} -+ -+// AuthorizationError indicates that an authorization for an identifier -+// did not succeed. -+// It contains all errors from Challenge items of the failed Authorization. -+type AuthorizationError struct { -+ // URI uniquely identifies the failed Authorization. -+ URI string -+ -+ // Identifier is an AuthzID.Value of the failed Authorization. -+ Identifier string -+ -+ // Errors is a collection of non-nil error values of Challenge items -+ // of the failed Authorization. -+ Errors []error -+} -+ -+func (a *AuthorizationError) Error() string { -+ e := make([]string, len(a.Errors)) -+ for i, err := range a.Errors { -+ e[i] = err.Error() -+ } -+ -+ if a.Identifier != "" { -+ return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; ")) -+ } -+ -+ return fmt.Sprintf("acme: authorization error: %s", strings.Join(e, "; ")) -+} -+ -+// OrderError is returned from Client's order related methods. -+// It indicates the order is unusable and the clients should start over with -+// AuthorizeOrder. -+// -+// The clients can still fetch the order object from CA using GetOrder -+// to inspect its state. -+type OrderError struct { -+ OrderURL string -+ Status string -+} -+ -+func (oe *OrderError) Error() string { -+ return fmt.Sprintf("acme: order %s status: %s", oe.OrderURL, oe.Status) -+} -+ -+// RateLimit reports whether err represents a rate limit error and -+// any Retry-After duration returned by the server. -+// -+// See the following for more details on rate limiting: -+// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6 -+func RateLimit(err error) (time.Duration, bool) { -+ e, ok := err.(*Error) -+ if !ok { -+ return 0, false -+ } -+ // Some CA implementations may return incorrect values. -+ // Use case-insensitive comparison. -+ if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") { -+ return 0, false -+ } -+ if e.Header == nil { -+ return 0, true -+ } -+ return retryAfter(e.Header.Get("Retry-After")), true -+} -+ -+// Account is a user account. It is associated with a private key. -+// Non-RFC 8555 fields are empty when interfacing with a compliant CA. -+type Account struct { -+ // URI is the account unique ID, which is also a URL used to retrieve -+ // account data from the CA. -+ // When interfacing with RFC 8555-compliant CAs, URI is the "kid" field -+ // value in JWS signed requests. -+ URI string -+ -+ // Contact is a slice of contact info used during registration. -+ // See https://tools.ietf.org/html/rfc8555#section-7.3 for supported -+ // formats. -+ Contact []string -+ -+ // Status indicates current account status as returned by the CA. -+ // Possible values are StatusValid, StatusDeactivated, and StatusRevoked. -+ Status string -+ -+ // OrdersURL is a URL from which a list of orders submitted by this account -+ // can be fetched. -+ OrdersURL string -+ -+ // The terms user has agreed to. -+ // A value not matching CurrentTerms indicates that the user hasn't agreed -+ // to the actual Terms of Service of the CA. -+ // -+ // It is non-RFC 8555 compliant. Package users can store the ToS they agree to -+ // during Client's Register call in the prompt callback function. -+ AgreedTerms string -+ -+ // Actual terms of a CA. -+ // -+ // It is non-RFC 8555 compliant. Use Directory's Terms field. -+ // When a CA updates their terms and requires an account agreement, -+ // a URL at which instructions to do so is available in Error's Instance field. -+ CurrentTerms string -+ -+ // Authz is the authorization URL used to initiate a new authz flow. -+ // -+ // It is non-RFC 8555 compliant. Use Directory's AuthzURL or OrderURL. -+ Authz string -+ -+ // Authorizations is a URI from which a list of authorizations -+ // granted to this account can be fetched via a GET request. -+ // -+ // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. -+ Authorizations string -+ -+ // Certificates is a URI from which a list of certificates -+ // issued for this account can be fetched via a GET request. -+ // -+ // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. -+ Certificates string -+ -+ // ExternalAccountBinding represents an arbitrary binding to an account of -+ // the CA which the ACME server is tied to. -+ // See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. -+ ExternalAccountBinding *ExternalAccountBinding -+} -+ -+// ExternalAccountBinding contains the data needed to form a request with -+// an external account binding. -+// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. -+type ExternalAccountBinding struct { -+ // KID is the Key ID of the symmetric MAC key that the CA provides to -+ // identify an external account from ACME. -+ KID string -+ -+ // Key is the bytes of the symmetric key that the CA provides to identify -+ // the account. Key must correspond to the KID. -+ Key []byte -+} -+ -+func (e *ExternalAccountBinding) String() string { -+ return fmt.Sprintf("&{KID: %q, Key: redacted}", e.KID) -+} -+ -+// Directory is ACME server discovery data. -+// See https://tools.ietf.org/html/rfc8555#section-7.1.1 for more details. -+type Directory struct { -+ // NonceURL indicates an endpoint where to fetch fresh nonce values from. -+ NonceURL string -+ -+ // RegURL is an account endpoint URL, allowing for creating new accounts. -+ // Pre-RFC 8555 CAs also allow modifying existing accounts at this URL. -+ RegURL string -+ -+ // OrderURL is used to initiate the certificate issuance flow -+ // as described in RFC 8555. -+ OrderURL string -+ -+ // AuthzURL is used to initiate identifier pre-authorization flow. -+ // Empty string indicates the flow is unsupported by the CA. -+ AuthzURL string -+ -+ // CertURL is a new certificate issuance endpoint URL. -+ // It is non-RFC 8555 compliant and is obsoleted by OrderURL. -+ CertURL string -+ -+ // RevokeURL is used to initiate a certificate revocation flow. -+ RevokeURL string -+ -+ // KeyChangeURL allows to perform account key rollover flow. -+ KeyChangeURL string -+ -+ // Term is a URI identifying the current terms of service. -+ Terms string -+ -+ // Website is an HTTP or HTTPS URL locating a website -+ // providing more information about the ACME server. -+ Website string -+ -+ // CAA consists of lowercase hostname elements, which the ACME server -+ // recognises as referring to itself for the purposes of CAA record validation -+ // as defined in RFC6844. -+ CAA []string -+ -+ // ExternalAccountRequired indicates that the CA requires for all account-related -+ // requests to include external account binding information. -+ ExternalAccountRequired bool -+} -+ -+// Order represents a client's request for a certificate. -+// It tracks the request flow progress through to issuance. -+type Order struct { -+ // URI uniquely identifies an order. -+ URI string -+ -+ // Status represents the current status of the order. -+ // It indicates which action the client should take. -+ // -+ // Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid. -+ // Pending means the CA does not believe that the client has fulfilled the requirements. -+ // Ready indicates that the client has fulfilled all the requirements and can submit a CSR -+ // to obtain a certificate. This is done with Client's CreateOrderCert. -+ // Processing means the certificate is being issued. -+ // Valid indicates the CA has issued the certificate. It can be downloaded -+ // from the Order's CertURL. This is done with Client's FetchCert. -+ // Invalid means the certificate will not be issued. Users should consider this order -+ // abandoned. -+ Status string -+ -+ // Expires is the timestamp after which CA considers this order invalid. -+ Expires time.Time -+ -+ // Identifiers contains all identifier objects which the order pertains to. -+ Identifiers []AuthzID -+ -+ // NotBefore is the requested value of the notBefore field in the certificate. -+ NotBefore time.Time -+ -+ // NotAfter is the requested value of the notAfter field in the certificate. -+ NotAfter time.Time -+ -+ // AuthzURLs represents authorizations to complete before a certificate -+ // for identifiers specified in the order can be issued. -+ // It also contains unexpired authorizations that the client has completed -+ // in the past. -+ // -+ // Authorization objects can be fetched using Client's GetAuthorization method. -+ // -+ // The required authorizations are dictated by CA policies. -+ // There may not be a 1:1 relationship between the identifiers and required authorizations. -+ // Required authorizations can be identified by their StatusPending status. -+ // -+ // For orders in the StatusValid or StatusInvalid state these are the authorizations -+ // which were completed. -+ AuthzURLs []string -+ -+ // FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate -+ // once all the authorizations are satisfied. -+ FinalizeURL string -+ -+ // CertURL points to the certificate that has been issued in response to this order. -+ CertURL string -+ -+ // The error that occurred while processing the order as received from a CA, if any. -+ Error *Error -+} -+ -+// OrderOption allows customizing Client.AuthorizeOrder call. -+type OrderOption interface { -+ privateOrderOpt() -+} -+ -+// WithOrderNotBefore sets order's NotBefore field. -+func WithOrderNotBefore(t time.Time) OrderOption { -+ return orderNotBeforeOpt(t) -+} -+ -+// WithOrderNotAfter sets order's NotAfter field. -+func WithOrderNotAfter(t time.Time) OrderOption { -+ return orderNotAfterOpt(t) -+} -+ -+type orderNotBeforeOpt time.Time -+ -+func (orderNotBeforeOpt) privateOrderOpt() {} -+ -+type orderNotAfterOpt time.Time -+ -+func (orderNotAfterOpt) privateOrderOpt() {} -+ -+// Authorization encodes an authorization response. -+type Authorization struct { -+ // URI uniquely identifies a authorization. -+ URI string -+ -+ // Status is the current status of an authorization. -+ // Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated, -+ // StatusExpired and StatusRevoked. -+ Status string -+ -+ // Identifier is what the account is authorized to represent. -+ Identifier AuthzID -+ -+ // The timestamp after which the CA considers the authorization invalid. -+ Expires time.Time -+ -+ // Wildcard is true for authorizations of a wildcard domain name. -+ Wildcard bool -+ -+ // Challenges that the client needs to fulfill in order to prove possession -+ // of the identifier (for pending authorizations). -+ // For valid authorizations, the challenge that was validated. -+ // For invalid authorizations, the challenge that was attempted and failed. -+ // -+ // RFC 8555 compatible CAs require users to fuflfill only one of the challenges. -+ Challenges []*Challenge -+ -+ // A collection of sets of challenges, each of which would be sufficient -+ // to prove possession of the identifier. -+ // Clients must complete a set of challenges that covers at least one set. -+ // Challenges are identified by their indices in the challenges array. -+ // If this field is empty, the client needs to complete all challenges. -+ // -+ // This field is unused in RFC 8555. -+ Combinations [][]int -+} -+ -+// AuthzID is an identifier that an account is authorized to represent. -+type AuthzID struct { -+ Type string // The type of identifier, "dns" or "ip". -+ Value string // The identifier itself, e.g. "example.org". -+} -+ -+// DomainIDs creates a slice of AuthzID with "dns" identifier type. -+func DomainIDs(names ...string) []AuthzID { -+ a := make([]AuthzID, len(names)) -+ for i, v := range names { -+ a[i] = AuthzID{Type: "dns", Value: v} -+ } -+ return a -+} -+ -+// IPIDs creates a slice of AuthzID with "ip" identifier type. -+// Each element of addr is textual form of an address as defined -+// in RFC1123 Section 2.1 for IPv4 and in RFC5952 Section 4 for IPv6. -+func IPIDs(addr ...string) []AuthzID { -+ a := make([]AuthzID, len(addr)) -+ for i, v := range addr { -+ a[i] = AuthzID{Type: "ip", Value: v} -+ } -+ return a -+} -+ -+// wireAuthzID is ACME JSON representation of authorization identifier objects. -+type wireAuthzID struct { -+ Type string `json:"type"` -+ Value string `json:"value"` -+} -+ -+// wireAuthz is ACME JSON representation of Authorization objects. -+type wireAuthz struct { -+ Identifier wireAuthzID -+ Status string -+ Expires time.Time -+ Wildcard bool -+ Challenges []wireChallenge -+ Combinations [][]int -+ Error *wireError -+} -+ -+func (z *wireAuthz) authorization(uri string) *Authorization { -+ a := &Authorization{ -+ URI: uri, -+ Status: z.Status, -+ Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value}, -+ Expires: z.Expires, -+ Wildcard: z.Wildcard, -+ Challenges: make([]*Challenge, len(z.Challenges)), -+ Combinations: z.Combinations, // shallow copy -+ } -+ for i, v := range z.Challenges { -+ a.Challenges[i] = v.challenge() -+ } -+ return a -+} -+ -+func (z *wireAuthz) error(uri string) *AuthorizationError { -+ err := &AuthorizationError{ -+ URI: uri, -+ Identifier: z.Identifier.Value, -+ } -+ -+ if z.Error != nil { -+ err.Errors = append(err.Errors, z.Error.error(nil)) -+ } -+ -+ for _, raw := range z.Challenges { -+ if raw.Error != nil { -+ err.Errors = append(err.Errors, raw.Error.error(nil)) -+ } -+ } -+ -+ return err -+} -+ -+// Challenge encodes a returned CA challenge. -+// Its Error field may be non-nil if the challenge is part of an Authorization -+// with StatusInvalid. -+type Challenge struct { -+ // Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01". -+ Type string -+ -+ // URI is where a challenge response can be posted to. -+ URI string -+ -+ // Token is a random value that uniquely identifies the challenge. -+ Token string -+ -+ // Status identifies the status of this challenge. -+ // In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid, -+ // and StatusInvalid. -+ Status string -+ -+ // Validated is the time at which the CA validated this challenge. -+ // Always zero value in pre-RFC 8555. -+ Validated time.Time -+ -+ // Error indicates the reason for an authorization failure -+ // when this challenge was used. -+ // The type of a non-nil value is *Error. -+ Error error -+} -+ -+// wireChallenge is ACME JSON challenge representation. -+type wireChallenge struct { -+ URL string `json:"url"` // RFC -+ URI string `json:"uri"` // pre-RFC -+ Type string -+ Token string -+ Status string -+ Validated time.Time -+ Error *wireError -+} -+ -+func (c *wireChallenge) challenge() *Challenge { -+ v := &Challenge{ -+ URI: c.URL, -+ Type: c.Type, -+ Token: c.Token, -+ Status: c.Status, -+ } -+ if v.URI == "" { -+ v.URI = c.URI // c.URL was empty; use legacy -+ } -+ if v.Status == "" { -+ v.Status = StatusPending -+ } -+ if c.Error != nil { -+ v.Error = c.Error.error(nil) -+ } -+ return v -+} -+ -+// wireError is a subset of fields of the Problem Details object -+// as described in https://tools.ietf.org/html/rfc7807#section-3.1. -+type wireError struct { -+ Status int -+ Type string -+ Detail string -+ Instance string -+ Subproblems []Subproblem -+} -+ -+func (e *wireError) error(h http.Header) *Error { -+ err := &Error{ -+ StatusCode: e.Status, -+ ProblemType: e.Type, -+ Detail: e.Detail, -+ Instance: e.Instance, -+ Header: h, -+ Subproblems: e.Subproblems, -+ } -+ return err -+} -+ -+// CertOption is an optional argument type for the TLS ChallengeCert methods for -+// customizing a temporary certificate for TLS-based challenges. -+type CertOption interface { -+ privateCertOpt() -+} -+ -+// WithKey creates an option holding a private/public key pair. -+// The private part signs a certificate, and the public part represents the signee. -+func WithKey(key crypto.Signer) CertOption { -+ return &certOptKey{key} -+} -+ -+type certOptKey struct { -+ key crypto.Signer -+} -+ -+func (*certOptKey) privateCertOpt() {} -+ -+// WithTemplate creates an option for specifying a certificate template. -+// See x509.CreateCertificate for template usage details. -+// -+// In TLS ChallengeCert methods, the template is also used as parent, -+// resulting in a self-signed certificate. -+// The DNSNames field of t is always overwritten for tls-sni challenge certs. -+func WithTemplate(t *x509.Certificate) CertOption { -+ return (*certOptTemplate)(t) -+} -+ -+type certOptTemplate x509.Certificate -+ -+func (*certOptTemplate) privateCertOpt() {} -diff --git a/vendor/golang.org/x/crypto/acme/version_go112.go b/vendor/golang.org/x/crypto/acme/version_go112.go -new file mode 100644 -index 000000000000..b9efdb59e585 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/acme/version_go112.go -@@ -0,0 +1,28 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.12 -+// +build go1.12 -+ -+package acme -+ -+import "runtime/debug" -+ -+func init() { -+ // Set packageVersion if the binary was built in modules mode and x/crypto -+ // was not replaced with a different module. -+ info, ok := debug.ReadBuildInfo() -+ if !ok { -+ return -+ } -+ for _, m := range info.Deps { -+ if m.Path != "golang.org/x/crypto" { -+ continue -+ } -+ if m.Replace == nil { -+ packageVersion = m.Version -+ } -+ break -+ } -+} -diff --git a/vendor/golang.org/x/crypto/argon2/argon2.go b/vendor/golang.org/x/crypto/argon2/argon2.go -new file mode 100644 -index 000000000000..b423feaea9f2 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/argon2/argon2.go -@@ -0,0 +1,285 @@ -+// 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 argon2 implements the key derivation function Argon2. -+// Argon2 was selected as the winner of the Password Hashing Competition and can -+// be used to derive cryptographic keys from passwords. -+// -+// For a detailed specification of Argon2 see [1]. -+// -+// If you aren't sure which function you need, use Argon2id (IDKey) and -+// the parameter recommendations for your scenario. -+// -+// -+// Argon2i -+// -+// Argon2i (implemented by Key) is the side-channel resistant version of Argon2. -+// It uses data-independent memory access, which is preferred for password -+// hashing and password-based key derivation. Argon2i requires more passes over -+// memory than Argon2id to protect from trade-off attacks. The recommended -+// parameters (taken from [2]) for non-interactive operations are time=3 and to -+// use the maximum available memory. -+// -+// -+// Argon2id -+// -+// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining -+// Argon2i and Argon2d. It uses data-independent memory access for the first -+// half of the first iteration over the memory and data-dependent memory access -+// for the rest. Argon2id is side-channel resistant and provides better brute- -+// force cost savings due to time-memory tradeoffs than Argon2i. The recommended -+// parameters for non-interactive operations (taken from [2]) are time=1 and to -+// use the maximum available memory. -+// -+// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf -+// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3 -+package argon2 -+ -+import ( -+ "encoding/binary" -+ "sync" -+ -+ "golang.org/x/crypto/blake2b" -+) -+ -+// The Argon2 version implemented by this package. -+const Version = 0x13 -+ -+const ( -+ argon2d = iota -+ argon2i -+ argon2id -+) -+ -+// Key derives a key from the password, salt, and cost parameters using Argon2i -+// returning a byte slice of length keyLen that can be used as cryptographic -+// key. The CPU cost and parallelism degree must be greater than zero. -+// -+// For example, you can get a derived key for e.g. AES-256 (which needs a -+// 32-byte key) by doing: -+// -+// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) -+// -+// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number. -+// If using that amount of memory (32 MB) is not possible in some contexts then -+// the time parameter can be increased to compensate. -+// -+// The time parameter specifies the number of passes over the memory and the -+// memory parameter specifies the size of the memory in KiB. For example -+// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be -+// adjusted to the number of available CPUs. The cost parameters should be -+// increased as memory latency and CPU parallelism increases. Remember to get a -+// good random salt. -+func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { -+ return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) -+} -+ -+// IDKey derives a key from the password, salt, and cost parameters using -+// Argon2id returning a byte slice of length keyLen that can be used as -+// cryptographic key. The CPU cost and parallelism degree must be greater than -+// zero. -+// -+// For example, you can get a derived key for e.g. AES-256 (which needs a -+// 32-byte key) by doing: -+// -+// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32) -+// -+// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number. -+// If using that amount of memory (64 MB) is not possible in some contexts then -+// the time parameter can be increased to compensate. -+// -+// The time parameter specifies the number of passes over the memory and the -+// memory parameter specifies the size of the memory in KiB. For example -+// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be -+// adjusted to the numbers of available CPUs. The cost parameters should be -+// increased as memory latency and CPU parallelism increases. Remember to get a -+// good random salt. -+func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { -+ return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen) -+} -+ -+func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { -+ if time < 1 { -+ panic("argon2: number of rounds too small") -+ } -+ if threads < 1 { -+ panic("argon2: parallelism degree too low") -+ } -+ h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode) -+ -+ memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads)) -+ if memory < 2*syncPoints*uint32(threads) { -+ memory = 2 * syncPoints * uint32(threads) -+ } -+ B := initBlocks(&h0, memory, uint32(threads)) -+ processBlocks(B, time, memory, uint32(threads), mode) -+ return extractKey(B, memory, uint32(threads), keyLen) -+} -+ -+const ( -+ blockLength = 128 -+ syncPoints = 4 -+) -+ -+type block [blockLength]uint64 -+ -+func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte { -+ var ( -+ h0 [blake2b.Size + 8]byte -+ params [24]byte -+ tmp [4]byte -+ ) -+ -+ b2, _ := blake2b.New512(nil) -+ binary.LittleEndian.PutUint32(params[0:4], threads) -+ binary.LittleEndian.PutUint32(params[4:8], keyLen) -+ binary.LittleEndian.PutUint32(params[8:12], memory) -+ binary.LittleEndian.PutUint32(params[12:16], time) -+ binary.LittleEndian.PutUint32(params[16:20], uint32(Version)) -+ binary.LittleEndian.PutUint32(params[20:24], uint32(mode)) -+ b2.Write(params[:]) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(password))) -+ b2.Write(tmp[:]) -+ b2.Write(password) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt))) -+ b2.Write(tmp[:]) -+ b2.Write(salt) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(key))) -+ b2.Write(tmp[:]) -+ b2.Write(key) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(data))) -+ b2.Write(tmp[:]) -+ b2.Write(data) -+ b2.Sum(h0[:0]) -+ return h0 -+} -+ -+func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block { -+ var block0 [1024]byte -+ B := make([]block, memory) -+ for lane := uint32(0); lane < threads; lane++ { -+ j := lane * (memory / threads) -+ binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane) -+ -+ binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0) -+ blake2bHash(block0[:], h0[:]) -+ for i := range B[j+0] { -+ B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:]) -+ } -+ -+ binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1) -+ blake2bHash(block0[:], h0[:]) -+ for i := range B[j+1] { -+ B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:]) -+ } -+ } -+ return B -+} -+ -+func processBlocks(B []block, time, memory, threads uint32, mode int) { -+ lanes := memory / threads -+ segments := lanes / syncPoints -+ -+ processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) { -+ var addresses, in, zero block -+ if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { -+ in[0] = uint64(n) -+ in[1] = uint64(lane) -+ in[2] = uint64(slice) -+ in[3] = uint64(memory) -+ in[4] = uint64(time) -+ in[5] = uint64(mode) -+ } -+ -+ index := uint32(0) -+ if n == 0 && slice == 0 { -+ index = 2 // we have already generated the first two blocks -+ if mode == argon2i || mode == argon2id { -+ in[6]++ -+ processBlock(&addresses, &in, &zero) -+ processBlock(&addresses, &addresses, &zero) -+ } -+ } -+ -+ offset := lane*lanes + slice*segments + index -+ var random uint64 -+ for index < segments { -+ prev := offset - 1 -+ if index == 0 && slice == 0 { -+ prev += lanes // last block in lane -+ } -+ if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { -+ if index%blockLength == 0 { -+ in[6]++ -+ processBlock(&addresses, &in, &zero) -+ processBlock(&addresses, &addresses, &zero) -+ } -+ random = addresses[index%blockLength] -+ } else { -+ random = B[prev][0] -+ } -+ newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index) -+ processBlockXOR(&B[offset], &B[prev], &B[newOffset]) -+ index, offset = index+1, offset+1 -+ } -+ wg.Done() -+ } -+ -+ for n := uint32(0); n < time; n++ { -+ for slice := uint32(0); slice < syncPoints; slice++ { -+ var wg sync.WaitGroup -+ for lane := uint32(0); lane < threads; lane++ { -+ wg.Add(1) -+ go processSegment(n, slice, lane, &wg) -+ } -+ wg.Wait() -+ } -+ } -+ -+} -+ -+func extractKey(B []block, memory, threads, keyLen uint32) []byte { -+ lanes := memory / threads -+ for lane := uint32(0); lane < threads-1; lane++ { -+ for i, v := range B[(lane*lanes)+lanes-1] { -+ B[memory-1][i] ^= v -+ } -+ } -+ -+ var block [1024]byte -+ for i, v := range B[memory-1] { -+ binary.LittleEndian.PutUint64(block[i*8:], v) -+ } -+ key := make([]byte, keyLen) -+ blake2bHash(key, block[:]) -+ return key -+} -+ -+func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 { -+ refLane := uint32(rand>>32) % threads -+ if n == 0 && slice == 0 { -+ refLane = lane -+ } -+ m, s := 3*segments, ((slice+1)%syncPoints)*segments -+ if lane == refLane { -+ m += index -+ } -+ if n == 0 { -+ m, s = slice*segments, 0 -+ if slice == 0 || lane == refLane { -+ m += index -+ } -+ } -+ if index == 0 || lane == refLane { -+ m-- -+ } -+ return phi(rand, uint64(m), uint64(s), refLane, lanes) -+} -+ -+func phi(rand, m, s uint64, lane, lanes uint32) uint32 { -+ p := rand & 0xFFFFFFFF -+ p = (p * p) >> 32 -+ p = (p * m) >> 32 -+ return lane*lanes + uint32((s+m-(p+1))%uint64(lanes)) -+} -diff --git a/vendor/golang.org/x/crypto/argon2/blake2b.go b/vendor/golang.org/x/crypto/argon2/blake2b.go -new file mode 100644 -index 000000000000..10f46948dc10 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/argon2/blake2b.go -@@ -0,0 +1,53 @@ -+// 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 argon2 -+ -+import ( -+ "encoding/binary" -+ "hash" -+ -+ "golang.org/x/crypto/blake2b" -+) -+ -+// blake2bHash computes an arbitrary long hash value of in -+// and writes the hash to out. -+func blake2bHash(out []byte, in []byte) { -+ var b2 hash.Hash -+ if n := len(out); n < blake2b.Size { -+ b2, _ = blake2b.New(n, nil) -+ } else { -+ b2, _ = blake2b.New512(nil) -+ } -+ -+ var buffer [blake2b.Size]byte -+ binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out))) -+ b2.Write(buffer[:4]) -+ b2.Write(in) -+ -+ if len(out) <= blake2b.Size { -+ b2.Sum(out[:0]) -+ return -+ } -+ -+ outLen := len(out) -+ b2.Sum(buffer[:0]) -+ b2.Reset() -+ copy(out, buffer[:32]) -+ out = out[32:] -+ for len(out) > blake2b.Size { -+ b2.Write(buffer[:]) -+ b2.Sum(buffer[:0]) -+ copy(out, buffer[:32]) -+ out = out[32:] -+ b2.Reset() -+ } -+ -+ if outLen%blake2b.Size > 0 { // outLen > 64 -+ r := ((outLen + 31) / 32) - 2 // ⌈τ /32⌉-2 -+ b2, _ = blake2b.New(outLen-32*r, nil) -+ } -+ b2.Write(buffer[:]) -+ b2.Sum(out[:0]) -+} -diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go -new file mode 100644 -index 000000000000..a014ac92aa9f ---- /dev/null -+++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go -@@ -0,0 +1,61 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+package argon2 -+ -+import "golang.org/x/sys/cpu" -+ -+func init() { -+ useSSE4 = cpu.X86.HasSSE41 -+} -+ -+//go:noescape -+func mixBlocksSSE2(out, a, b, c *block) -+ -+//go:noescape -+func xorBlocksSSE2(out, a, b, c *block) -+ -+//go:noescape -+func blamkaSSE4(b *block) -+ -+func processBlockSSE(out, in1, in2 *block, xor bool) { -+ var t block -+ mixBlocksSSE2(&t, in1, in2, &t) -+ if useSSE4 { -+ blamkaSSE4(&t) -+ } else { -+ for i := 0; i < blockLength; i += 16 { -+ blamkaGeneric( -+ &t[i+0], &t[i+1], &t[i+2], &t[i+3], -+ &t[i+4], &t[i+5], &t[i+6], &t[i+7], -+ &t[i+8], &t[i+9], &t[i+10], &t[i+11], -+ &t[i+12], &t[i+13], &t[i+14], &t[i+15], -+ ) -+ } -+ for i := 0; i < blockLength/8; i += 2 { -+ blamkaGeneric( -+ &t[i], &t[i+1], &t[16+i], &t[16+i+1], -+ &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], -+ &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], -+ &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], -+ ) -+ } -+ } -+ if xor { -+ xorBlocksSSE2(out, in1, in2, &t) -+ } else { -+ mixBlocksSSE2(out, in1, in2, &t) -+ } -+} -+ -+func processBlock(out, in1, in2 *block) { -+ processBlockSSE(out, in1, in2, false) -+} -+ -+func processBlockXOR(out, in1, in2 *block) { -+ processBlockSSE(out, in1, in2, true) -+} -diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s -new file mode 100644 -index 000000000000..b2cc0515049a ---- /dev/null -+++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s -@@ -0,0 +1,244 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 -+ -+#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v6, t1; \ -+ PUNPCKLQDQ v6, t2; \ -+ PUNPCKHQDQ v7, v6; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ v7, t2; \ -+ MOVO t1, v7; \ -+ MOVO v2, t1; \ -+ PUNPCKHQDQ t2, v7; \ -+ PUNPCKLQDQ v3, t2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v3 -+ -+#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v2, t1; \ -+ PUNPCKLQDQ v2, t2; \ -+ PUNPCKHQDQ v3, v2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ v3, t2; \ -+ MOVO t1, v3; \ -+ MOVO v6, t1; \ -+ PUNPCKHQDQ t2, v3; \ -+ PUNPCKLQDQ v7, t2; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v7 -+ -+#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48) \ -+ MOVO v0, t0; \ -+ PMULULQ v2, t0; \ -+ PADDQ v2, v0; \ -+ PADDQ t0, v0; \ -+ PADDQ t0, v0; \ -+ PXOR v0, v6; \ -+ PSHUFD $0xB1, v6, v6; \ -+ MOVO v4, t0; \ -+ PMULULQ v6, t0; \ -+ PADDQ v6, v4; \ -+ PADDQ t0, v4; \ -+ PADDQ t0, v4; \ -+ PXOR v4, v2; \ -+ PSHUFB c40, v2; \ -+ MOVO v0, t0; \ -+ PMULULQ v2, t0; \ -+ PADDQ v2, v0; \ -+ PADDQ t0, v0; \ -+ PADDQ t0, v0; \ -+ PXOR v0, v6; \ -+ PSHUFB c48, v6; \ -+ MOVO v4, t0; \ -+ PMULULQ v6, t0; \ -+ PADDQ v6, v4; \ -+ PADDQ t0, v4; \ -+ PADDQ t0, v4; \ -+ PXOR v4, v2; \ -+ MOVO v2, t0; \ -+ PADDQ v2, t0; \ -+ PSRLQ $63, v2; \ -+ PXOR t0, v2; \ -+ MOVO v1, t0; \ -+ PMULULQ v3, t0; \ -+ PADDQ v3, v1; \ -+ PADDQ t0, v1; \ -+ PADDQ t0, v1; \ -+ PXOR v1, v7; \ -+ PSHUFD $0xB1, v7, v7; \ -+ MOVO v5, t0; \ -+ PMULULQ v7, t0; \ -+ PADDQ v7, v5; \ -+ PADDQ t0, v5; \ -+ PADDQ t0, v5; \ -+ PXOR v5, v3; \ -+ PSHUFB c40, v3; \ -+ MOVO v1, t0; \ -+ PMULULQ v3, t0; \ -+ PADDQ v3, v1; \ -+ PADDQ t0, v1; \ -+ PADDQ t0, v1; \ -+ PXOR v1, v7; \ -+ PSHUFB c48, v7; \ -+ MOVO v5, t0; \ -+ PMULULQ v7, t0; \ -+ PADDQ v7, v5; \ -+ PADDQ t0, v5; \ -+ PADDQ t0, v5; \ -+ PXOR v5, v3; \ -+ MOVO v3, t0; \ -+ PADDQ v3, t0; \ -+ PSRLQ $63, v3; \ -+ PXOR t0, v3 -+ -+#define LOAD_MSG_0(block, off) \ -+ MOVOU 8*(off+0)(block), X0; \ -+ MOVOU 8*(off+2)(block), X1; \ -+ MOVOU 8*(off+4)(block), X2; \ -+ MOVOU 8*(off+6)(block), X3; \ -+ MOVOU 8*(off+8)(block), X4; \ -+ MOVOU 8*(off+10)(block), X5; \ -+ MOVOU 8*(off+12)(block), X6; \ -+ MOVOU 8*(off+14)(block), X7 -+ -+#define STORE_MSG_0(block, off) \ -+ MOVOU X0, 8*(off+0)(block); \ -+ MOVOU X1, 8*(off+2)(block); \ -+ MOVOU X2, 8*(off+4)(block); \ -+ MOVOU X3, 8*(off+6)(block); \ -+ MOVOU X4, 8*(off+8)(block); \ -+ MOVOU X5, 8*(off+10)(block); \ -+ MOVOU X6, 8*(off+12)(block); \ -+ MOVOU X7, 8*(off+14)(block) -+ -+#define LOAD_MSG_1(block, off) \ -+ MOVOU 8*off+0*8(block), X0; \ -+ MOVOU 8*off+16*8(block), X1; \ -+ MOVOU 8*off+32*8(block), X2; \ -+ MOVOU 8*off+48*8(block), X3; \ -+ MOVOU 8*off+64*8(block), X4; \ -+ MOVOU 8*off+80*8(block), X5; \ -+ MOVOU 8*off+96*8(block), X6; \ -+ MOVOU 8*off+112*8(block), X7 -+ -+#define STORE_MSG_1(block, off) \ -+ MOVOU X0, 8*off+0*8(block); \ -+ MOVOU X1, 8*off+16*8(block); \ -+ MOVOU X2, 8*off+32*8(block); \ -+ MOVOU X3, 8*off+48*8(block); \ -+ MOVOU X4, 8*off+64*8(block); \ -+ MOVOU X5, 8*off+80*8(block); \ -+ MOVOU X6, 8*off+96*8(block); \ -+ MOVOU X7, 8*off+112*8(block) -+ -+#define BLAMKA_ROUND_0(block, off, t0, t1, c40, c48) \ -+ LOAD_MSG_0(block, off); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ STORE_MSG_0(block, off) -+ -+#define BLAMKA_ROUND_1(block, off, t0, t1, c40, c48) \ -+ LOAD_MSG_1(block, off); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ STORE_MSG_1(block, off) -+ -+// func blamkaSSE4(b *block) -+TEXT ·blamkaSSE4(SB), 4, $0-8 -+ MOVQ b+0(FP), AX -+ -+ MOVOU ·c40<>(SB), X10 -+ MOVOU ·c48<>(SB), X11 -+ -+ BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11) -+ -+ BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11) -+ RET -+ -+// func mixBlocksSSE2(out, a, b, c *block) -+TEXT ·mixBlocksSSE2(SB), 4, $0-32 -+ MOVQ out+0(FP), DX -+ MOVQ a+8(FP), AX -+ MOVQ b+16(FP), BX -+ MOVQ a+24(FP), CX -+ MOVQ $128, BP -+ -+loop: -+ MOVOU 0(AX), X0 -+ MOVOU 0(BX), X1 -+ MOVOU 0(CX), X2 -+ PXOR X1, X0 -+ PXOR X2, X0 -+ MOVOU X0, 0(DX) -+ ADDQ $16, AX -+ ADDQ $16, BX -+ ADDQ $16, CX -+ ADDQ $16, DX -+ SUBQ $2, BP -+ JA loop -+ RET -+ -+// func xorBlocksSSE2(out, a, b, c *block) -+TEXT ·xorBlocksSSE2(SB), 4, $0-32 -+ MOVQ out+0(FP), DX -+ MOVQ a+8(FP), AX -+ MOVQ b+16(FP), BX -+ MOVQ a+24(FP), CX -+ MOVQ $128, BP -+ -+loop: -+ MOVOU 0(AX), X0 -+ MOVOU 0(BX), X1 -+ MOVOU 0(CX), X2 -+ MOVOU 0(DX), X3 -+ PXOR X1, X0 -+ PXOR X2, X0 -+ PXOR X3, X0 -+ MOVOU X0, 0(DX) -+ ADDQ $16, AX -+ ADDQ $16, BX -+ ADDQ $16, CX -+ ADDQ $16, DX -+ SUBQ $2, BP -+ JA loop -+ RET -diff --git a/vendor/golang.org/x/crypto/argon2/blamka_generic.go b/vendor/golang.org/x/crypto/argon2/blamka_generic.go -new file mode 100644 -index 000000000000..a481b2243f85 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/argon2/blamka_generic.go -@@ -0,0 +1,163 @@ -+// 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 argon2 -+ -+var useSSE4 bool -+ -+func processBlockGeneric(out, in1, in2 *block, xor bool) { -+ var t block -+ for i := range t { -+ t[i] = in1[i] ^ in2[i] -+ } -+ for i := 0; i < blockLength; i += 16 { -+ blamkaGeneric( -+ &t[i+0], &t[i+1], &t[i+2], &t[i+3], -+ &t[i+4], &t[i+5], &t[i+6], &t[i+7], -+ &t[i+8], &t[i+9], &t[i+10], &t[i+11], -+ &t[i+12], &t[i+13], &t[i+14], &t[i+15], -+ ) -+ } -+ for i := 0; i < blockLength/8; i += 2 { -+ blamkaGeneric( -+ &t[i], &t[i+1], &t[16+i], &t[16+i+1], -+ &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], -+ &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], -+ &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], -+ ) -+ } -+ if xor { -+ for i := range t { -+ out[i] ^= in1[i] ^ in2[i] ^ t[i] -+ } -+ } else { -+ for i := range t { -+ out[i] = in1[i] ^ in2[i] ^ t[i] -+ } -+ } -+} -+ -+func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) { -+ v00, v01, v02, v03 := *t00, *t01, *t02, *t03 -+ v04, v05, v06, v07 := *t04, *t05, *t06, *t07 -+ v08, v09, v10, v11 := *t08, *t09, *t10, *t11 -+ v12, v13, v14, v15 := *t12, *t13, *t14, *t15 -+ -+ v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) -+ v12 ^= v00 -+ v12 = v12>>32 | v12<<32 -+ v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) -+ v04 ^= v08 -+ v04 = v04>>24 | v04<<40 -+ -+ v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) -+ v12 ^= v00 -+ v12 = v12>>16 | v12<<48 -+ v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) -+ v04 ^= v08 -+ v04 = v04>>63 | v04<<1 -+ -+ v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) -+ v13 ^= v01 -+ v13 = v13>>32 | v13<<32 -+ v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) -+ v05 ^= v09 -+ v05 = v05>>24 | v05<<40 -+ -+ v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) -+ v13 ^= v01 -+ v13 = v13>>16 | v13<<48 -+ v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) -+ v05 ^= v09 -+ v05 = v05>>63 | v05<<1 -+ -+ v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) -+ v14 ^= v02 -+ v14 = v14>>32 | v14<<32 -+ v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) -+ v06 ^= v10 -+ v06 = v06>>24 | v06<<40 -+ -+ v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) -+ v14 ^= v02 -+ v14 = v14>>16 | v14<<48 -+ v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) -+ v06 ^= v10 -+ v06 = v06>>63 | v06<<1 -+ -+ v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) -+ v15 ^= v03 -+ v15 = v15>>32 | v15<<32 -+ v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) -+ v07 ^= v11 -+ v07 = v07>>24 | v07<<40 -+ -+ v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) -+ v15 ^= v03 -+ v15 = v15>>16 | v15<<48 -+ v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) -+ v07 ^= v11 -+ v07 = v07>>63 | v07<<1 -+ -+ v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) -+ v15 ^= v00 -+ v15 = v15>>32 | v15<<32 -+ v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) -+ v05 ^= v10 -+ v05 = v05>>24 | v05<<40 -+ -+ v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) -+ v15 ^= v00 -+ v15 = v15>>16 | v15<<48 -+ v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) -+ v05 ^= v10 -+ v05 = v05>>63 | v05<<1 -+ -+ v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) -+ v12 ^= v01 -+ v12 = v12>>32 | v12<<32 -+ v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) -+ v06 ^= v11 -+ v06 = v06>>24 | v06<<40 -+ -+ v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) -+ v12 ^= v01 -+ v12 = v12>>16 | v12<<48 -+ v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) -+ v06 ^= v11 -+ v06 = v06>>63 | v06<<1 -+ -+ v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) -+ v13 ^= v02 -+ v13 = v13>>32 | v13<<32 -+ v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) -+ v07 ^= v08 -+ v07 = v07>>24 | v07<<40 -+ -+ v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) -+ v13 ^= v02 -+ v13 = v13>>16 | v13<<48 -+ v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) -+ v07 ^= v08 -+ v07 = v07>>63 | v07<<1 -+ -+ v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) -+ v14 ^= v03 -+ v14 = v14>>32 | v14<<32 -+ v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) -+ v04 ^= v09 -+ v04 = v04>>24 | v04<<40 -+ -+ v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) -+ v14 ^= v03 -+ v14 = v14>>16 | v14<<48 -+ v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) -+ v04 ^= v09 -+ v04 = v04>>63 | v04<<1 -+ -+ *t00, *t01, *t02, *t03 = v00, v01, v02, v03 -+ *t04, *t05, *t06, *t07 = v04, v05, v06, v07 -+ *t08, *t09, *t10, *t11 = v08, v09, v10, v11 -+ *t12, *t13, *t14, *t15 = v12, v13, v14, v15 -+} -diff --git a/vendor/golang.org/x/crypto/argon2/blamka_ref.go b/vendor/golang.org/x/crypto/argon2/blamka_ref.go -new file mode 100644 -index 000000000000..167c59d2d5ab ---- /dev/null -+++ b/vendor/golang.org/x/crypto/argon2/blamka_ref.go -@@ -0,0 +1,16 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc -+ -+package argon2 -+ -+func processBlock(out, in1, in2 *block) { -+ processBlockGeneric(out, in1, in2, false) -+} -+ -+func processBlockXOR(out, in1, in2 *block) { -+ processBlockGeneric(out, in1, in2, true) -+} -diff --git a/vendor/golang.org/x/crypto/bcrypt/base64.go b/vendor/golang.org/x/crypto/bcrypt/base64.go -new file mode 100644 -index 000000000000..fc3116090818 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bcrypt/base64.go -@@ -0,0 +1,35 @@ -+// 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 bcrypt -+ -+import "encoding/base64" -+ -+const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -+ -+var bcEncoding = base64.NewEncoding(alphabet) -+ -+func base64Encode(src []byte) []byte { -+ n := bcEncoding.EncodedLen(len(src)) -+ dst := make([]byte, n) -+ bcEncoding.Encode(dst, src) -+ for dst[n-1] == '=' { -+ n-- -+ } -+ return dst[:n] -+} -+ -+func base64Decode(src []byte) ([]byte, error) { -+ numOfEquals := 4 - (len(src) % 4) -+ for i := 0; i < numOfEquals; i++ { -+ src = append(src, '=') -+ } -+ -+ dst := make([]byte, bcEncoding.DecodedLen(len(src))) -+ n, err := bcEncoding.Decode(dst, src) -+ if err != nil { -+ return nil, err -+ } -+ return dst[:n], nil -+} -diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go -new file mode 100644 -index 000000000000..aeb73f81a14c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go -@@ -0,0 +1,295 @@ -+// 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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing -+// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf -+package bcrypt // import "golang.org/x/crypto/bcrypt" -+ -+// The code is a port of Provos and Mazières's C implementation. -+import ( -+ "crypto/rand" -+ "crypto/subtle" -+ "errors" -+ "fmt" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/blowfish" -+) -+ -+const ( -+ MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword -+ MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword -+ DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword -+) -+ -+// The error returned from CompareHashAndPassword when a password and hash do -+// not match. -+var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") -+ -+// The error returned from CompareHashAndPassword when a hash is too short to -+// be a bcrypt hash. -+var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") -+ -+// The error returned from CompareHashAndPassword when a hash was created with -+// a bcrypt algorithm newer than this implementation. -+type HashVersionTooNewError byte -+ -+func (hv HashVersionTooNewError) Error() string { -+ return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) -+} -+ -+// The error returned from CompareHashAndPassword when a hash starts with something other than '$' -+type InvalidHashPrefixError byte -+ -+func (ih InvalidHashPrefixError) Error() string { -+ return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) -+} -+ -+type InvalidCostError int -+ -+func (ic InvalidCostError) Error() string { -+ return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) -+} -+ -+const ( -+ majorVersion = '2' -+ minorVersion = 'a' -+ maxSaltSize = 16 -+ maxCryptedHashSize = 23 -+ encodedSaltSize = 22 -+ encodedHashSize = 31 -+ minHashSize = 59 -+) -+ -+// magicCipherData is an IV for the 64 Blowfish encryption calls in -+// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. -+var magicCipherData = []byte{ -+ 0x4f, 0x72, 0x70, 0x68, -+ 0x65, 0x61, 0x6e, 0x42, -+ 0x65, 0x68, 0x6f, 0x6c, -+ 0x64, 0x65, 0x72, 0x53, -+ 0x63, 0x72, 0x79, 0x44, -+ 0x6f, 0x75, 0x62, 0x74, -+} -+ -+type hashed struct { -+ hash []byte -+ salt []byte -+ cost int // allowed range is MinCost to MaxCost -+ major byte -+ minor byte -+} -+ -+// GenerateFromPassword returns the bcrypt hash of the password at the given -+// cost. If the cost given is less than MinCost, the cost will be set to -+// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, -+// to compare the returned hashed password with its cleartext version. -+func GenerateFromPassword(password []byte, cost int) ([]byte, error) { -+ p, err := newFromPassword(password, cost) -+ if err != nil { -+ return nil, err -+ } -+ return p.Hash(), nil -+} -+ -+// CompareHashAndPassword compares a bcrypt hashed password with its possible -+// plaintext equivalent. Returns nil on success, or an error on failure. -+func CompareHashAndPassword(hashedPassword, password []byte) error { -+ p, err := newFromHash(hashedPassword) -+ if err != nil { -+ return err -+ } -+ -+ otherHash, err := bcrypt(password, p.cost, p.salt) -+ if err != nil { -+ return err -+ } -+ -+ otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} -+ if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { -+ return nil -+ } -+ -+ return ErrMismatchedHashAndPassword -+} -+ -+// Cost returns the hashing cost used to create the given hashed -+// password. When, in the future, the hashing cost of a password system needs -+// to be increased in order to adjust for greater computational power, this -+// function allows one to establish which passwords need to be updated. -+func Cost(hashedPassword []byte) (int, error) { -+ p, err := newFromHash(hashedPassword) -+ if err != nil { -+ return 0, err -+ } -+ return p.cost, nil -+} -+ -+func newFromPassword(password []byte, cost int) (*hashed, error) { -+ if cost < MinCost { -+ cost = DefaultCost -+ } -+ p := new(hashed) -+ p.major = majorVersion -+ p.minor = minorVersion -+ -+ err := checkCost(cost) -+ if err != nil { -+ return nil, err -+ } -+ p.cost = cost -+ -+ unencodedSalt := make([]byte, maxSaltSize) -+ _, err = io.ReadFull(rand.Reader, unencodedSalt) -+ if err != nil { -+ return nil, err -+ } -+ -+ p.salt = base64Encode(unencodedSalt) -+ hash, err := bcrypt(password, p.cost, p.salt) -+ if err != nil { -+ return nil, err -+ } -+ p.hash = hash -+ return p, err -+} -+ -+func newFromHash(hashedSecret []byte) (*hashed, error) { -+ if len(hashedSecret) < minHashSize { -+ return nil, ErrHashTooShort -+ } -+ p := new(hashed) -+ n, err := p.decodeVersion(hashedSecret) -+ if err != nil { -+ return nil, err -+ } -+ hashedSecret = hashedSecret[n:] -+ n, err = p.decodeCost(hashedSecret) -+ if err != nil { -+ return nil, err -+ } -+ hashedSecret = hashedSecret[n:] -+ -+ // The "+2" is here because we'll have to append at most 2 '=' to the salt -+ // when base64 decoding it in expensiveBlowfishSetup(). -+ p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) -+ copy(p.salt, hashedSecret[:encodedSaltSize]) -+ -+ hashedSecret = hashedSecret[encodedSaltSize:] -+ p.hash = make([]byte, len(hashedSecret)) -+ copy(p.hash, hashedSecret) -+ -+ return p, nil -+} -+ -+func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { -+ cipherData := make([]byte, len(magicCipherData)) -+ copy(cipherData, magicCipherData) -+ -+ c, err := expensiveBlowfishSetup(password, uint32(cost), salt) -+ if err != nil { -+ return nil, err -+ } -+ -+ for i := 0; i < 24; i += 8 { -+ for j := 0; j < 64; j++ { -+ c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) -+ } -+ } -+ -+ // Bug compatibility with C bcrypt implementations. We only encode 23 of -+ // the 24 bytes encrypted. -+ hsh := base64Encode(cipherData[:maxCryptedHashSize]) -+ return hsh, nil -+} -+ -+func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { -+ csalt, err := base64Decode(salt) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Bug compatibility with C bcrypt implementations. They use the trailing -+ // NULL in the key string during expansion. -+ // We copy the key to prevent changing the underlying array. -+ ckey := append(key[:len(key):len(key)], 0) -+ -+ c, err := blowfish.NewSaltedCipher(ckey, csalt) -+ if err != nil { -+ return nil, err -+ } -+ -+ var i, rounds uint64 -+ rounds = 1 << cost -+ for i = 0; i < rounds; i++ { -+ blowfish.ExpandKey(ckey, c) -+ blowfish.ExpandKey(csalt, c) -+ } -+ -+ return c, nil -+} -+ -+func (p *hashed) Hash() []byte { -+ arr := make([]byte, 60) -+ arr[0] = '$' -+ arr[1] = p.major -+ n := 2 -+ if p.minor != 0 { -+ arr[2] = p.minor -+ n = 3 -+ } -+ arr[n] = '$' -+ n++ -+ copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) -+ n += 2 -+ arr[n] = '$' -+ n++ -+ copy(arr[n:], p.salt) -+ n += encodedSaltSize -+ copy(arr[n:], p.hash) -+ n += encodedHashSize -+ return arr[:n] -+} -+ -+func (p *hashed) decodeVersion(sbytes []byte) (int, error) { -+ if sbytes[0] != '$' { -+ return -1, InvalidHashPrefixError(sbytes[0]) -+ } -+ if sbytes[1] > majorVersion { -+ return -1, HashVersionTooNewError(sbytes[1]) -+ } -+ p.major = sbytes[1] -+ n := 3 -+ if sbytes[2] != '$' { -+ p.minor = sbytes[2] -+ n++ -+ } -+ return n, nil -+} -+ -+// sbytes should begin where decodeVersion left off. -+func (p *hashed) decodeCost(sbytes []byte) (int, error) { -+ cost, err := strconv.Atoi(string(sbytes[0:2])) -+ if err != nil { -+ return -1, err -+ } -+ err = checkCost(cost) -+ if err != nil { -+ return -1, err -+ } -+ p.cost = cost -+ return 3, nil -+} -+ -+func (p *hashed) String() string { -+ return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) -+} -+ -+func checkCost(cost int) error { -+ if cost < MinCost || cost > MaxCost { -+ return InvalidCostError(cost) -+ } -+ return nil -+} -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go -new file mode 100644 -index 000000000000..d2e98d4295bd ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go -@@ -0,0 +1,291 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 -+// and the extendable output function (XOF) BLAKE2Xb. -+// -+// BLAKE2b is optimized for 64-bit platforms—including NEON-enabled ARMs—and -+// produces digests of any size between 1 and 64 bytes. -+// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf -+// and for BLAKE2Xb see https://blake2.net/blake2x.pdf -+// -+// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). -+// If you need a secret-key MAC (message authentication code), use the New512 -+// function with a non-nil key. -+// -+// BLAKE2X is a construction to compute hash values larger than 64 bytes. It -+// can produce hash values between 0 and 4 GiB. -+package blake2b -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "hash" -+) -+ -+const ( -+ // The blocksize of BLAKE2b in bytes. -+ BlockSize = 128 -+ // The hash size of BLAKE2b-512 in bytes. -+ Size = 64 -+ // The hash size of BLAKE2b-384 in bytes. -+ Size384 = 48 -+ // The hash size of BLAKE2b-256 in bytes. -+ Size256 = 32 -+) -+ -+var ( -+ useAVX2 bool -+ useAVX bool -+ useSSE4 bool -+) -+ -+var ( -+ errKeySize = errors.New("blake2b: invalid key size") -+ errHashSize = errors.New("blake2b: invalid hash size") -+) -+ -+var iv = [8]uint64{ -+ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, -+ 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, -+} -+ -+// Sum512 returns the BLAKE2b-512 checksum of the data. -+func Sum512(data []byte) [Size]byte { -+ var sum [Size]byte -+ checkSum(&sum, Size, data) -+ return sum -+} -+ -+// Sum384 returns the BLAKE2b-384 checksum of the data. -+func Sum384(data []byte) [Size384]byte { -+ var sum [Size]byte -+ var sum384 [Size384]byte -+ checkSum(&sum, Size384, data) -+ copy(sum384[:], sum[:Size384]) -+ return sum384 -+} -+ -+// Sum256 returns the BLAKE2b-256 checksum of the data. -+func Sum256(data []byte) [Size256]byte { -+ var sum [Size]byte -+ var sum256 [Size256]byte -+ checkSum(&sum, Size256, data) -+ copy(sum256[:], sum[:Size256]) -+ return sum256 -+} -+ -+// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil -+// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } -+ -+// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil -+// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } -+ -+// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil -+// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } -+ -+// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. -+// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+// The hash size can be a value between 1 and 64 but it is highly recommended to use -+// values equal or greater than: -+// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). -+// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). -+// When the key is nil, the returned hash.Hash implements BinaryMarshaler -+// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. -+func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } -+ -+func newDigest(hashSize int, key []byte) (*digest, error) { -+ if hashSize < 1 || hashSize > Size { -+ return nil, errHashSize -+ } -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ d := &digest{ -+ size: hashSize, -+ keyLen: len(key), -+ } -+ copy(d.key[:], key) -+ d.Reset() -+ return d, nil -+} -+ -+func checkSum(sum *[Size]byte, hashSize int, data []byte) { -+ h := iv -+ h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) -+ var c [2]uint64 -+ -+ if length := len(data); length > BlockSize { -+ n := length &^ (BlockSize - 1) -+ if length == n { -+ n -= BlockSize -+ } -+ hashBlocks(&h, &c, 0, data[:n]) -+ data = data[n:] -+ } -+ -+ var block [BlockSize]byte -+ offset := copy(block[:], data) -+ remaining := uint64(BlockSize - offset) -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) -+ -+ for i, v := range h[:(hashSize+7)/8] { -+ binary.LittleEndian.PutUint64(sum[8*i:], v) -+ } -+} -+ -+type digest struct { -+ h [8]uint64 -+ c [2]uint64 -+ size int -+ block [BlockSize]byte -+ offset int -+ -+ key [BlockSize]byte -+ keyLen int -+} -+ -+const ( -+ magic = "b2b" -+ marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 -+) -+ -+func (d *digest) MarshalBinary() ([]byte, error) { -+ if d.keyLen != 0 { -+ return nil, errors.New("crypto/blake2b: cannot marshal MACs") -+ } -+ b := make([]byte, 0, marshaledSize) -+ b = append(b, magic...) -+ for i := 0; i < 8; i++ { -+ b = appendUint64(b, d.h[i]) -+ } -+ b = appendUint64(b, d.c[0]) -+ b = appendUint64(b, d.c[1]) -+ // Maximum value for size is 64 -+ b = append(b, byte(d.size)) -+ b = append(b, d.block[:]...) -+ b = append(b, byte(d.offset)) -+ return b, nil -+} -+ -+func (d *digest) UnmarshalBinary(b []byte) error { -+ if len(b) < len(magic) || string(b[:len(magic)]) != magic { -+ return errors.New("crypto/blake2b: invalid hash state identifier") -+ } -+ if len(b) != marshaledSize { -+ return errors.New("crypto/blake2b: invalid hash state size") -+ } -+ b = b[len(magic):] -+ for i := 0; i < 8; i++ { -+ b, d.h[i] = consumeUint64(b) -+ } -+ b, d.c[0] = consumeUint64(b) -+ b, d.c[1] = consumeUint64(b) -+ d.size = int(b[0]) -+ b = b[1:] -+ copy(d.block[:], b[:BlockSize]) -+ b = b[BlockSize:] -+ d.offset = int(b[0]) -+ return nil -+} -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Size() int { return d.size } -+ -+func (d *digest) Reset() { -+ d.h = iv -+ d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ if d.keyLen > 0 { -+ d.block = d.key -+ d.offset = BlockSize -+ } -+} -+ -+func (d *digest) Write(p []byte) (n int, err error) { -+ n = len(p) -+ -+ if d.offset > 0 { -+ remaining := BlockSize - d.offset -+ if n <= remaining { -+ d.offset += copy(d.block[d.offset:], p) -+ return -+ } -+ copy(d.block[d.offset:], p[:remaining]) -+ hashBlocks(&d.h, &d.c, 0, d.block[:]) -+ d.offset = 0 -+ p = p[remaining:] -+ } -+ -+ if length := len(p); length > BlockSize { -+ nn := length &^ (BlockSize - 1) -+ if length == nn { -+ nn -= BlockSize -+ } -+ hashBlocks(&d.h, &d.c, 0, p[:nn]) -+ p = p[nn:] -+ } -+ -+ if len(p) > 0 { -+ d.offset += copy(d.block[:], p) -+ } -+ -+ return -+} -+ -+func (d *digest) Sum(sum []byte) []byte { -+ var hash [Size]byte -+ d.finalize(&hash) -+ return append(sum, hash[:d.size]...) -+} -+ -+func (d *digest) finalize(hash *[Size]byte) { -+ var block [BlockSize]byte -+ copy(block[:], d.block[:d.offset]) -+ remaining := uint64(BlockSize - d.offset) -+ -+ c := d.c -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ h := d.h -+ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) -+ -+ for i, v := range h { -+ binary.LittleEndian.PutUint64(hash[8*i:], v) -+ } -+} -+ -+func appendUint64(b []byte, x uint64) []byte { -+ var a [8]byte -+ binary.BigEndian.PutUint64(a[:], x) -+ return append(b, a[:]...) -+} -+ -+func appendUint32(b []byte, x uint32) []byte { -+ var a [4]byte -+ binary.BigEndian.PutUint32(a[:], x) -+ return append(b, a[:]...) -+} -+ -+func consumeUint64(b []byte) ([]byte, uint64) { -+ x := binary.BigEndian.Uint64(b) -+ return b[8:], x -+} -+ -+func consumeUint32(b []byte) ([]byte, uint32) { -+ x := binary.BigEndian.Uint32(b) -+ return b[4:], x -+} -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go -new file mode 100644 -index 000000000000..56bfaaa17da6 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go -@@ -0,0 +1,38 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.7 && amd64 && gc && !purego -+// +build go1.7,amd64,gc,!purego -+ -+package blake2b -+ -+import "golang.org/x/sys/cpu" -+ -+func init() { -+ useAVX2 = cpu.X86.HasAVX2 -+ useAVX = cpu.X86.HasAVX -+ useSSE4 = cpu.X86.HasSSE41 -+} -+ -+//go:noescape -+func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+//go:noescape -+func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ switch { -+ case useAVX2: -+ hashBlocksAVX2(h, c, flag, blocks) -+ case useAVX: -+ hashBlocksAVX(h, c, flag, blocks) -+ case useSSE4: -+ hashBlocksSSE4(h, c, flag, blocks) -+ default: -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s -new file mode 100644 -index 000000000000..4b9daa18d9d9 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s -@@ -0,0 +1,745 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.7 && amd64 && gc && !purego -+// +build go1.7,amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -+DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -+DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b -+DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 -+GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 -+ -+DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 -+DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -+DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b -+DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 -+GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 -+ -+DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 -+DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 -+ -+DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 -+DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 -+ -+DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -+DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -+GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -+DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -+GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 -+DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -+GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -+DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -+GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 -+ -+#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 -+#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 -+#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e -+#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 -+#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 -+ -+#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ -+ VPADDQ m0, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFD $-79, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPSHUFB c40, Y1, Y1; \ -+ VPADDQ m1, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFB c48, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPADDQ Y1, Y1, t; \ -+ VPSRLQ $63, Y1, Y1; \ -+ VPXOR t, Y1, Y1; \ -+ VPERMQ_0x39_Y1_Y1; \ -+ VPERMQ_0x4E_Y2_Y2; \ -+ VPERMQ_0x93_Y3_Y3; \ -+ VPADDQ m2, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFD $-79, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPSHUFB c40, Y1, Y1; \ -+ VPADDQ m3, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFB c48, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPADDQ Y1, Y1, t; \ -+ VPSRLQ $63, Y1, Y1; \ -+ VPXOR t, Y1, Y1; \ -+ VPERMQ_0x39_Y3_Y3; \ -+ VPERMQ_0x4E_Y2_Y2; \ -+ VPERMQ_0x93_Y1_Y1 -+ -+#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E -+#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 -+#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E -+#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 -+#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E -+ -+#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n -+#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n -+#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n -+#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n -+#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n -+ -+#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 -+#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 -+#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 -+#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 -+#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 -+ -+#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 -+ -+#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 -+#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 -+ -+// load msg: Y12 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ -+ VMOVQ_SI_X12(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X12(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y12, Y12 -+ -+// load msg: Y13 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ -+ VMOVQ_SI_X13(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X13(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y13, Y13 -+ -+// load msg: Y14 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ -+ VMOVQ_SI_X14(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X14(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y14, Y14 -+ -+// load msg: Y15 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ -+ VMOVQ_SI_X15(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X15(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ -+ VMOVQ_SI_X12_0; \ -+ VMOVQ_SI_X11(4*8); \ -+ VPINSRQ_1_SI_X12(2*8); \ -+ VPINSRQ_1_SI_X11(6*8); \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ -+ LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ -+ LOAD_MSG_AVX2_Y15(9, 11, 13, 15) -+ -+#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ -+ LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ -+ LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ -+ VMOVQ_SI_X11(11*8); \ -+ VPSHUFD $0x4E, 0*8(SI), X14; \ -+ VPINSRQ_1_SI_X11(5*8); \ -+ VINSERTI128 $1, X11, Y14, Y14; \ -+ LOAD_MSG_AVX2_Y15(12, 2, 7, 3) -+ -+#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ -+ VMOVQ_SI_X11(5*8); \ -+ VMOVDQU 11*8(SI), X12; \ -+ VPINSRQ_1_SI_X11(15*8); \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ VMOVQ_SI_X13(8*8); \ -+ VMOVQ_SI_X11(2*8); \ -+ VPINSRQ_1_SI_X13_0; \ -+ VPINSRQ_1_SI_X11(13*8); \ -+ VINSERTI128 $1, X11, Y13, Y13; \ -+ LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ -+ LOAD_MSG_AVX2_Y15(14, 6, 1, 4) -+ -+#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ -+ LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ -+ LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ -+ LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ -+ VMOVQ_SI_X15(6*8); \ -+ VMOVQ_SI_X11_0; \ -+ VPINSRQ_1_SI_X15(10*8); \ -+ VPINSRQ_1_SI_X11(8*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ -+ LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ -+ VMOVQ_SI_X13_0; \ -+ VMOVQ_SI_X11(4*8); \ -+ VPINSRQ_1_SI_X13(7*8); \ -+ VPINSRQ_1_SI_X11(15*8); \ -+ VINSERTI128 $1, X11, Y13, Y13; \ -+ LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ -+ LOAD_MSG_AVX2_Y15(1, 12, 8, 13) -+ -+#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ -+ VMOVQ_SI_X12(2*8); \ -+ VMOVQ_SI_X11_0; \ -+ VPINSRQ_1_SI_X12(6*8); \ -+ VPINSRQ_1_SI_X11(8*8); \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ -+ LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ -+ LOAD_MSG_AVX2_Y15(13, 5, 14, 9) -+ -+#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ -+ LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ -+ LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ -+ VMOVQ_SI_X14_0; \ -+ VPSHUFD $0x4E, 8*8(SI), X11; \ -+ VPINSRQ_1_SI_X14(6*8); \ -+ VINSERTI128 $1, X11, Y14, Y14; \ -+ LOAD_MSG_AVX2_Y15(7, 3, 2, 11) -+ -+#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ -+ LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ -+ LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ -+ LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ -+ VMOVQ_SI_X15_0; \ -+ VMOVQ_SI_X11(6*8); \ -+ VPINSRQ_1_SI_X15(4*8); \ -+ VPINSRQ_1_SI_X11(10*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ -+ VMOVQ_SI_X12(6*8); \ -+ VMOVQ_SI_X11(11*8); \ -+ VPINSRQ_1_SI_X12(14*8); \ -+ VPINSRQ_1_SI_X11_0; \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ -+ VMOVQ_SI_X11(1*8); \ -+ VMOVDQU 12*8(SI), X14; \ -+ VPINSRQ_1_SI_X11(10*8); \ -+ VINSERTI128 $1, X11, Y14, Y14; \ -+ VMOVQ_SI_X15(2*8); \ -+ VMOVDQU 4*8(SI), X11; \ -+ VPINSRQ_1_SI_X15(7*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ -+ LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ -+ VMOVQ_SI_X13(2*8); \ -+ VPSHUFD $0x4E, 5*8(SI), X11; \ -+ VPINSRQ_1_SI_X13(4*8); \ -+ VINSERTI128 $1, X11, Y13, Y13; \ -+ LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ -+ VMOVQ_SI_X15(11*8); \ -+ VMOVQ_SI_X11(12*8); \ -+ VPINSRQ_1_SI_X15(14*8); \ -+ VPINSRQ_1_SI_X11_0; \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+TEXT ·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment -+ MOVQ h+0(FP), AX -+ MOVQ c+8(FP), BX -+ MOVQ flag+16(FP), CX -+ MOVQ blocks_base+24(FP), SI -+ MOVQ blocks_len+32(FP), DI -+ -+ MOVQ SP, DX -+ ADDQ $31, DX -+ ANDQ $~31, DX -+ -+ MOVQ CX, 16(DX) -+ XORQ CX, CX -+ MOVQ CX, 24(DX) -+ -+ VMOVDQU ·AVX2_c40<>(SB), Y4 -+ VMOVDQU ·AVX2_c48<>(SB), Y5 -+ -+ VMOVDQU 0(AX), Y8 -+ VMOVDQU 32(AX), Y9 -+ VMOVDQU ·AVX2_iv0<>(SB), Y6 -+ VMOVDQU ·AVX2_iv1<>(SB), Y7 -+ -+ MOVQ 0(BX), R8 -+ MOVQ 8(BX), R9 -+ MOVQ R9, 8(DX) -+ -+loop: -+ ADDQ $128, R8 -+ MOVQ R8, 0(DX) -+ CMPQ R8, $128 -+ JGE noinc -+ INCQ R9 -+ MOVQ R9, 8(DX) -+ -+noinc: -+ VMOVDQA Y8, Y0 -+ VMOVDQA Y9, Y1 -+ VMOVDQA Y6, Y2 -+ VPXOR 0(DX), Y7, Y3 -+ -+ LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() -+ VMOVDQA Y12, 32(DX) -+ VMOVDQA Y13, 64(DX) -+ VMOVDQA Y14, 96(DX) -+ VMOVDQA Y15, 128(DX) -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() -+ VMOVDQA Y12, 160(DX) -+ VMOVDQA Y13, 192(DX) -+ VMOVDQA Y14, 224(DX) -+ VMOVDQA Y15, 256(DX) -+ -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ -+ ROUND_AVX2(32(DX), 64(DX), 96(DX), 128(DX), Y10, Y4, Y5) -+ ROUND_AVX2(160(DX), 192(DX), 224(DX), 256(DX), Y10, Y4, Y5) -+ -+ VPXOR Y0, Y8, Y8 -+ VPXOR Y1, Y9, Y9 -+ VPXOR Y2, Y8, Y8 -+ VPXOR Y3, Y9, Y9 -+ -+ LEAQ 128(SI), SI -+ SUBQ $128, DI -+ JNE loop -+ -+ MOVQ R8, 0(BX) -+ MOVQ R9, 8(BX) -+ -+ VMOVDQU Y8, 0(AX) -+ VMOVDQU Y9, 32(AX) -+ VZEROUPPER -+ -+ RET -+ -+#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA -+#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB -+#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF -+#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD -+#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE -+ -+#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 -+#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF -+#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 -+#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF -+#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 -+#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 -+#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF -+#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF -+ -+#define SHUFFLE_AVX() \ -+ VMOVDQA X6, X13; \ -+ VMOVDQA X2, X14; \ -+ VMOVDQA X4, X6; \ -+ VPUNPCKLQDQ_X13_X13_X15; \ -+ VMOVDQA X5, X4; \ -+ VMOVDQA X6, X5; \ -+ VPUNPCKHQDQ_X15_X7_X6; \ -+ VPUNPCKLQDQ_X7_X7_X15; \ -+ VPUNPCKHQDQ_X15_X13_X7; \ -+ VPUNPCKLQDQ_X3_X3_X15; \ -+ VPUNPCKHQDQ_X15_X2_X2; \ -+ VPUNPCKLQDQ_X14_X14_X15; \ -+ VPUNPCKHQDQ_X15_X3_X3; \ -+ -+#define SHUFFLE_AVX_INV() \ -+ VMOVDQA X2, X13; \ -+ VMOVDQA X4, X14; \ -+ VPUNPCKLQDQ_X2_X2_X15; \ -+ VMOVDQA X5, X4; \ -+ VPUNPCKHQDQ_X15_X3_X2; \ -+ VMOVDQA X14, X5; \ -+ VPUNPCKLQDQ_X3_X3_X15; \ -+ VMOVDQA X6, X14; \ -+ VPUNPCKHQDQ_X15_X13_X3; \ -+ VPUNPCKLQDQ_X7_X7_X15; \ -+ VPUNPCKHQDQ_X15_X6_X6; \ -+ VPUNPCKLQDQ_X14_X14_X15; \ -+ VPUNPCKHQDQ_X15_X7_X7; \ -+ -+#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ -+ VPADDQ m0, v0, v0; \ -+ VPADDQ v2, v0, v0; \ -+ VPADDQ m1, v1, v1; \ -+ VPADDQ v3, v1, v1; \ -+ VPXOR v0, v6, v6; \ -+ VPXOR v1, v7, v7; \ -+ VPSHUFD $-79, v6, v6; \ -+ VPSHUFD $-79, v7, v7; \ -+ VPADDQ v6, v4, v4; \ -+ VPADDQ v7, v5, v5; \ -+ VPXOR v4, v2, v2; \ -+ VPXOR v5, v3, v3; \ -+ VPSHUFB c40, v2, v2; \ -+ VPSHUFB c40, v3, v3; \ -+ VPADDQ m2, v0, v0; \ -+ VPADDQ v2, v0, v0; \ -+ VPADDQ m3, v1, v1; \ -+ VPADDQ v3, v1, v1; \ -+ VPXOR v0, v6, v6; \ -+ VPXOR v1, v7, v7; \ -+ VPSHUFB c48, v6, v6; \ -+ VPSHUFB c48, v7, v7; \ -+ VPADDQ v6, v4, v4; \ -+ VPADDQ v7, v5, v5; \ -+ VPXOR v4, v2, v2; \ -+ VPXOR v5, v3, v3; \ -+ VPADDQ v2, v2, t0; \ -+ VPSRLQ $63, v2, v2; \ -+ VPXOR t0, v2, v2; \ -+ VPADDQ v3, v3, t0; \ -+ VPSRLQ $63, v3, v3; \ -+ VPXOR t0, v3, v3 -+ -+// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) -+// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 -+#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ -+ VMOVQ_SI_X12(i0*8); \ -+ VMOVQ_SI_X13(i2*8); \ -+ VMOVQ_SI_X14(i4*8); \ -+ VMOVQ_SI_X15(i6*8); \ -+ VPINSRQ_1_SI_X12(i1*8); \ -+ VPINSRQ_1_SI_X13(i3*8); \ -+ VPINSRQ_1_SI_X14(i5*8); \ -+ VPINSRQ_1_SI_X15(i7*8) -+ -+// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) -+#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ -+ VMOVQ_SI_X12_0; \ -+ VMOVQ_SI_X13(4*8); \ -+ VMOVQ_SI_X14(1*8); \ -+ VMOVQ_SI_X15(5*8); \ -+ VPINSRQ_1_SI_X12(2*8); \ -+ VPINSRQ_1_SI_X13(6*8); \ -+ VPINSRQ_1_SI_X14(3*8); \ -+ VPINSRQ_1_SI_X15(7*8) -+ -+// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) -+#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ -+ VPSHUFD $0x4E, 0*8(SI), X12; \ -+ VMOVQ_SI_X13(11*8); \ -+ VMOVQ_SI_X14(12*8); \ -+ VMOVQ_SI_X15(7*8); \ -+ VPINSRQ_1_SI_X13(5*8); \ -+ VPINSRQ_1_SI_X14(2*8); \ -+ VPINSRQ_1_SI_X15(3*8) -+ -+// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) -+#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ -+ VMOVDQU 11*8(SI), X12; \ -+ VMOVQ_SI_X13(5*8); \ -+ VMOVQ_SI_X14(8*8); \ -+ VMOVQ_SI_X15(2*8); \ -+ VPINSRQ_1_SI_X13(15*8); \ -+ VPINSRQ_1_SI_X14_0; \ -+ VPINSRQ_1_SI_X15(13*8) -+ -+// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) -+#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ -+ VMOVQ_SI_X12(2*8); \ -+ VMOVQ_SI_X13(4*8); \ -+ VMOVQ_SI_X14(6*8); \ -+ VMOVQ_SI_X15_0; \ -+ VPINSRQ_1_SI_X12(5*8); \ -+ VPINSRQ_1_SI_X13(15*8); \ -+ VPINSRQ_1_SI_X14(10*8); \ -+ VPINSRQ_1_SI_X15(8*8) -+ -+// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) -+#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ -+ VMOVQ_SI_X12(9*8); \ -+ VMOVQ_SI_X13(2*8); \ -+ VMOVQ_SI_X14_0; \ -+ VMOVQ_SI_X15(4*8); \ -+ VPINSRQ_1_SI_X12(5*8); \ -+ VPINSRQ_1_SI_X13(10*8); \ -+ VPINSRQ_1_SI_X14(7*8); \ -+ VPINSRQ_1_SI_X15(15*8) -+ -+// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) -+#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ -+ VMOVQ_SI_X12(2*8); \ -+ VMOVQ_SI_X13_0; \ -+ VMOVQ_SI_X14(12*8); \ -+ VMOVQ_SI_X15(11*8); \ -+ VPINSRQ_1_SI_X12(6*8); \ -+ VPINSRQ_1_SI_X13(8*8); \ -+ VPINSRQ_1_SI_X14(10*8); \ -+ VPINSRQ_1_SI_X15(3*8) -+ -+// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) -+#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ -+ MOVQ 0*8(SI), X12; \ -+ VPSHUFD $0x4E, 8*8(SI), X13; \ -+ MOVQ 7*8(SI), X14; \ -+ MOVQ 2*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(6*8); \ -+ VPINSRQ_1_SI_X14(3*8); \ -+ VPINSRQ_1_SI_X15(11*8) -+ -+// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) -+#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ -+ MOVQ 6*8(SI), X12; \ -+ MOVQ 11*8(SI), X13; \ -+ MOVQ 15*8(SI), X14; \ -+ MOVQ 3*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(14*8); \ -+ VPINSRQ_1_SI_X13_0; \ -+ VPINSRQ_1_SI_X14(9*8); \ -+ VPINSRQ_1_SI_X15(8*8) -+ -+// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) -+#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ -+ MOVQ 5*8(SI), X12; \ -+ MOVQ 8*8(SI), X13; \ -+ MOVQ 0*8(SI), X14; \ -+ MOVQ 6*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(15*8); \ -+ VPINSRQ_1_SI_X13(2*8); \ -+ VPINSRQ_1_SI_X14(4*8); \ -+ VPINSRQ_1_SI_X15(10*8) -+ -+// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) -+#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ -+ VMOVDQU 12*8(SI), X12; \ -+ MOVQ 1*8(SI), X13; \ -+ MOVQ 2*8(SI), X14; \ -+ VPINSRQ_1_SI_X13(10*8); \ -+ VPINSRQ_1_SI_X14(7*8); \ -+ VMOVDQU 4*8(SI), X15 -+ -+// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) -+#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ -+ MOVQ 15*8(SI), X12; \ -+ MOVQ 3*8(SI), X13; \ -+ MOVQ 11*8(SI), X14; \ -+ MOVQ 12*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(9*8); \ -+ VPINSRQ_1_SI_X13(13*8); \ -+ VPINSRQ_1_SI_X14(14*8); \ -+ VPINSRQ_1_SI_X15_0 -+ -+// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment -+ MOVQ h+0(FP), AX -+ MOVQ c+8(FP), BX -+ MOVQ flag+16(FP), CX -+ MOVQ blocks_base+24(FP), SI -+ MOVQ blocks_len+32(FP), DI -+ -+ MOVQ SP, R10 -+ ADDQ $15, R10 -+ ANDQ $~15, R10 -+ -+ VMOVDQU ·AVX_c40<>(SB), X0 -+ VMOVDQU ·AVX_c48<>(SB), X1 -+ VMOVDQA X0, X8 -+ VMOVDQA X1, X9 -+ -+ VMOVDQU ·AVX_iv3<>(SB), X0 -+ VMOVDQA X0, 0(R10) -+ XORQ CX, 0(R10) // 0(R10) = ·AVX_iv3 ^ (CX || 0) -+ -+ VMOVDQU 0(AX), X10 -+ VMOVDQU 16(AX), X11 -+ VMOVDQU 32(AX), X2 -+ VMOVDQU 48(AX), X3 -+ -+ MOVQ 0(BX), R8 -+ MOVQ 8(BX), R9 -+ -+loop: -+ ADDQ $128, R8 -+ CMPQ R8, $128 -+ JGE noinc -+ INCQ R9 -+ -+noinc: -+ VMOVQ_R8_X15 -+ VPINSRQ_1_R9_X15 -+ -+ VMOVDQA X10, X0 -+ VMOVDQA X11, X1 -+ VMOVDQU ·AVX_iv0<>(SB), X4 -+ VMOVDQU ·AVX_iv1<>(SB), X5 -+ VMOVDQU ·AVX_iv2<>(SB), X6 -+ -+ VPXOR X15, X6, X6 -+ VMOVDQA 0(R10), X7 -+ -+ LOAD_MSG_AVX_0_2_4_6_1_3_5_7() -+ VMOVDQA X12, 16(R10) -+ VMOVDQA X13, 32(R10) -+ VMOVDQA X14, 48(R10) -+ VMOVDQA X15, 64(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) -+ VMOVDQA X12, 80(R10) -+ VMOVDQA X13, 96(R10) -+ VMOVDQA X14, 112(R10) -+ VMOVDQA X15, 128(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) -+ VMOVDQA X12, 144(R10) -+ VMOVDQA X13, 160(R10) -+ VMOVDQA X14, 176(R10) -+ VMOVDQA X15, 192(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_1_0_11_5_12_2_7_3() -+ VMOVDQA X12, 208(R10) -+ VMOVDQA X13, 224(R10) -+ VMOVDQA X14, 240(R10) -+ VMOVDQA X15, 256(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_11_12_5_15_8_0_2_13() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_2_5_4_15_6_10_0_8() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_9_5_2_10_0_7_4_15() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_2_6_0_8_12_10_11_3() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_0_6_9_8_7_3_2_11() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_5_15_8_2_0_4_6_10() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_6_14_11_0_15_9_3_8() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_12_13_1_10_2_7_4_5() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_15_9_3_13_11_14_12_0() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X15, X8, X9) -+ SHUFFLE_AVX() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X15, X8, X9) -+ SHUFFLE_AVX() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ VMOVDQU 32(AX), X14 -+ VMOVDQU 48(AX), X15 -+ VPXOR X0, X10, X10 -+ VPXOR X1, X11, X11 -+ VPXOR X2, X14, X14 -+ VPXOR X3, X15, X15 -+ VPXOR X4, X10, X10 -+ VPXOR X5, X11, X11 -+ VPXOR X6, X14, X2 -+ VPXOR X7, X15, X3 -+ VMOVDQU X2, 32(AX) -+ VMOVDQU X3, 48(AX) -+ -+ LEAQ 128(SI), SI -+ SUBQ $128, DI -+ JNE loop -+ -+ VMOVDQU X10, 0(AX) -+ VMOVDQU X11, 16(AX) -+ -+ MOVQ R8, 0(BX) -+ MOVQ R9, 8(BX) -+ VZEROUPPER -+ -+ RET -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go -new file mode 100644 -index 000000000000..5fa1b32841df ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go -@@ -0,0 +1,25 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !go1.7 && amd64 && gc && !purego -+// +build !go1.7,amd64,gc,!purego -+ -+package blake2b -+ -+import "golang.org/x/sys/cpu" -+ -+func init() { -+ useSSE4 = cpu.X86.HasSSE41 -+} -+ -+//go:noescape -+func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ if useSSE4 { -+ hashBlocksSSE4(h, c, flag, blocks) -+ } else { -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s -new file mode 100644 -index 000000000000..ae75eb9afcd7 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s -@@ -0,0 +1,279 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -+DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -+GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -+DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -+GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 -+DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -+GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -+DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -+GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 -+ -+DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 -+ -+#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v6, t1; \ -+ PUNPCKLQDQ v6, t2; \ -+ PUNPCKHQDQ v7, v6; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ v7, t2; \ -+ MOVO t1, v7; \ -+ MOVO v2, t1; \ -+ PUNPCKHQDQ t2, v7; \ -+ PUNPCKLQDQ v3, t2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v3 -+ -+#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v2, t1; \ -+ PUNPCKLQDQ v2, t2; \ -+ PUNPCKHQDQ v3, v2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ v3, t2; \ -+ MOVO t1, v3; \ -+ MOVO v6, t1; \ -+ PUNPCKHQDQ t2, v3; \ -+ PUNPCKLQDQ v7, t2; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v7 -+ -+#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ -+ PADDQ m0, v0; \ -+ PADDQ m1, v1; \ -+ PADDQ v2, v0; \ -+ PADDQ v3, v1; \ -+ PXOR v0, v6; \ -+ PXOR v1, v7; \ -+ PSHUFD $0xB1, v6, v6; \ -+ PSHUFD $0xB1, v7, v7; \ -+ PADDQ v6, v4; \ -+ PADDQ v7, v5; \ -+ PXOR v4, v2; \ -+ PXOR v5, v3; \ -+ PSHUFB c40, v2; \ -+ PSHUFB c40, v3; \ -+ PADDQ m2, v0; \ -+ PADDQ m3, v1; \ -+ PADDQ v2, v0; \ -+ PADDQ v3, v1; \ -+ PXOR v0, v6; \ -+ PXOR v1, v7; \ -+ PSHUFB c48, v6; \ -+ PSHUFB c48, v7; \ -+ PADDQ v6, v4; \ -+ PADDQ v7, v5; \ -+ PXOR v4, v2; \ -+ PXOR v5, v3; \ -+ MOVOU v2, t0; \ -+ PADDQ v2, t0; \ -+ PSRLQ $63, v2; \ -+ PXOR t0, v2; \ -+ MOVOU v3, t0; \ -+ PADDQ v3, t0; \ -+ PSRLQ $63, v3; \ -+ PXOR t0, v3 -+ -+#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \ -+ MOVQ i0*8(src), m0; \ -+ PINSRQ $1, i1*8(src), m0; \ -+ MOVQ i2*8(src), m1; \ -+ PINSRQ $1, i3*8(src), m1; \ -+ MOVQ i4*8(src), m2; \ -+ PINSRQ $1, i5*8(src), m2; \ -+ MOVQ i6*8(src), m3; \ -+ PINSRQ $1, i7*8(src), m3 -+ -+// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+TEXT ·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment -+ MOVQ h+0(FP), AX -+ MOVQ c+8(FP), BX -+ MOVQ flag+16(FP), CX -+ MOVQ blocks_base+24(FP), SI -+ MOVQ blocks_len+32(FP), DI -+ -+ MOVQ SP, R10 -+ ADDQ $15, R10 -+ ANDQ $~15, R10 -+ -+ MOVOU ·iv3<>(SB), X0 -+ MOVO X0, 0(R10) -+ XORQ CX, 0(R10) // 0(R10) = ·iv3 ^ (CX || 0) -+ -+ MOVOU ·c40<>(SB), X13 -+ MOVOU ·c48<>(SB), X14 -+ -+ MOVOU 0(AX), X12 -+ MOVOU 16(AX), X15 -+ -+ MOVQ 0(BX), R8 -+ MOVQ 8(BX), R9 -+ -+loop: -+ ADDQ $128, R8 -+ CMPQ R8, $128 -+ JGE noinc -+ INCQ R9 -+ -+noinc: -+ MOVQ R8, X8 -+ PINSRQ $1, R9, X8 -+ -+ MOVO X12, X0 -+ MOVO X15, X1 -+ MOVOU 32(AX), X2 -+ MOVOU 48(AX), X3 -+ MOVOU ·iv0<>(SB), X4 -+ MOVOU ·iv1<>(SB), X5 -+ MOVOU ·iv2<>(SB), X6 -+ -+ PXOR X8, X6 -+ MOVO 0(R10), X7 -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) -+ MOVO X8, 16(R10) -+ MOVO X9, 32(R10) -+ MOVO X10, 48(R10) -+ MOVO X11, 64(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) -+ MOVO X8, 80(R10) -+ MOVO X9, 96(R10) -+ MOVO X10, 112(R10) -+ MOVO X11, 128(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) -+ MOVO X8, 144(R10) -+ MOVO X9, 160(R10) -+ MOVO X10, 176(R10) -+ MOVO X11, 192(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) -+ MOVO X8, 208(R10) -+ MOVO X9, 224(R10) -+ MOVO X10, 240(R10) -+ MOVO X11, 256(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ MOVOU 32(AX), X10 -+ MOVOU 48(AX), X11 -+ PXOR X0, X12 -+ PXOR X1, X15 -+ PXOR X2, X10 -+ PXOR X3, X11 -+ PXOR X4, X12 -+ PXOR X5, X15 -+ PXOR X6, X10 -+ PXOR X7, X11 -+ MOVOU X10, 32(AX) -+ MOVOU X11, 48(AX) -+ -+ LEAQ 128(SI), SI -+ SUBQ $128, DI -+ JNE loop -+ -+ MOVOU X12, 0(AX) -+ MOVOU X15, 16(AX) -+ -+ MOVQ R8, 0(BX) -+ MOVQ R9, 8(BX) -+ -+ RET -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go -new file mode 100644 -index 000000000000..3168a8aa3c83 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go -@@ -0,0 +1,182 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2b -+ -+import ( -+ "encoding/binary" -+ "math/bits" -+) -+ -+// the precomputed values for BLAKE2b -+// there are 12 16-byte arrays - one for each round -+// the entries are calculated from the sigma constants. -+var precomputed = [12][16]byte{ -+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, -+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, -+ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, -+ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, -+ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, -+ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, -+ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, -+ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, -+ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, -+ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, -+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first -+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second -+} -+ -+func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ var m [16]uint64 -+ c0, c1 := c[0], c[1] -+ -+ for i := 0; i < len(blocks); { -+ c0 += BlockSize -+ if c0 < BlockSize { -+ c1++ -+ } -+ -+ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] -+ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] -+ v12 ^= c0 -+ v13 ^= c1 -+ v14 ^= flag -+ -+ for j := range m { -+ m[j] = binary.LittleEndian.Uint64(blocks[i:]) -+ i += 8 -+ } -+ -+ for j := range precomputed { -+ s := &(precomputed[j]) -+ -+ v0 += m[s[0]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft64(v12, -32) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft64(v4, -24) -+ v1 += m[s[1]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft64(v13, -32) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft64(v5, -24) -+ v2 += m[s[2]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft64(v14, -32) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft64(v6, -24) -+ v3 += m[s[3]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft64(v15, -32) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft64(v7, -24) -+ -+ v0 += m[s[4]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft64(v12, -16) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft64(v4, -63) -+ v1 += m[s[5]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft64(v13, -16) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft64(v5, -63) -+ v2 += m[s[6]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft64(v14, -16) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft64(v6, -63) -+ v3 += m[s[7]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft64(v15, -16) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft64(v7, -63) -+ -+ v0 += m[s[8]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft64(v15, -32) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft64(v5, -24) -+ v1 += m[s[9]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft64(v12, -32) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft64(v6, -24) -+ v2 += m[s[10]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft64(v13, -32) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft64(v7, -24) -+ v3 += m[s[11]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft64(v14, -32) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft64(v4, -24) -+ -+ v0 += m[s[12]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft64(v15, -16) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft64(v5, -63) -+ v1 += m[s[13]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft64(v12, -16) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft64(v6, -63) -+ v2 += m[s[14]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft64(v13, -16) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft64(v7, -63) -+ v3 += m[s[15]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft64(v14, -16) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft64(v4, -63) -+ -+ } -+ -+ h[0] ^= v0 ^ v8 -+ h[1] ^= v1 ^ v9 -+ h[2] ^= v2 ^ v10 -+ h[3] ^= v3 ^ v11 -+ h[4] ^= v4 ^ v12 -+ h[5] ^= v5 ^ v13 -+ h[6] ^= v6 ^ v14 -+ h[7] ^= v7 ^ v15 -+ } -+ c[0], c[1] = c0, c1 -+} -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go -new file mode 100644 -index 000000000000..b0137cdf025c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go -@@ -0,0 +1,12 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc -+ -+package blake2b -+ -+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ hashBlocksGeneric(h, c, flag, blocks) -+} -diff --git a/vendor/golang.org/x/crypto/blake2b/blake2x.go b/vendor/golang.org/x/crypto/blake2b/blake2x.go -new file mode 100644 -index 000000000000..52c414db0e64 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/blake2x.go -@@ -0,0 +1,177 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2b -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "io" -+) -+ -+// XOF defines the interface to hash functions that -+// support arbitrary-length output. -+type XOF interface { -+ // Write absorbs more data into the hash's state. It panics if called -+ // after Read. -+ io.Writer -+ -+ // Read reads more output from the hash. It returns io.EOF if the limit -+ // has been reached. -+ io.Reader -+ -+ // Clone returns a copy of the XOF in its current state. -+ Clone() XOF -+ -+ // Reset resets the XOF to its initial state. -+ Reset() -+} -+ -+// OutputLengthUnknown can be used as the size argument to NewXOF to indicate -+// the length of the output is not known in advance. -+const OutputLengthUnknown = 0 -+ -+// magicUnknownOutputLength is a magic value for the output size that indicates -+// an unknown number of output bytes. -+const magicUnknownOutputLength = (1 << 32) - 1 -+ -+// maxOutputLength is the absolute maximum number of bytes to produce when the -+// number of output bytes is unknown. -+const maxOutputLength = (1 << 32) * 64 -+ -+// NewXOF creates a new variable-output-length hash. The hash either produce a -+// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes -+// (size == OutputLengthUnknown). In the latter case, an absolute limit of -+// 256GiB applies. -+// -+// A non-nil key turns the hash into a MAC. The key must between -+// zero and 32 bytes long. -+func NewXOF(size uint32, key []byte) (XOF, error) { -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ if size == magicUnknownOutputLength { -+ // 2^32-1 indicates an unknown number of bytes and thus isn't a -+ // valid length. -+ return nil, errors.New("blake2b: XOF length too large") -+ } -+ if size == OutputLengthUnknown { -+ size = magicUnknownOutputLength -+ } -+ x := &xof{ -+ d: digest{ -+ size: Size, -+ keyLen: len(key), -+ }, -+ length: size, -+ } -+ copy(x.d.key[:], key) -+ x.Reset() -+ return x, nil -+} -+ -+type xof struct { -+ d digest -+ length uint32 -+ remaining uint64 -+ cfg, root, block [Size]byte -+ offset int -+ nodeOffset uint32 -+ readMode bool -+} -+ -+func (x *xof) Write(p []byte) (n int, err error) { -+ if x.readMode { -+ panic("blake2b: write to XOF after read") -+ } -+ return x.d.Write(p) -+} -+ -+func (x *xof) Clone() XOF { -+ clone := *x -+ return &clone -+} -+ -+func (x *xof) Reset() { -+ x.cfg[0] = byte(Size) -+ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length -+ binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length -+ x.cfg[17] = byte(Size) // inner hash size -+ -+ x.d.Reset() -+ x.d.h[1] ^= uint64(x.length) << 32 -+ -+ x.remaining = uint64(x.length) -+ if x.remaining == magicUnknownOutputLength { -+ x.remaining = maxOutputLength -+ } -+ x.offset, x.nodeOffset = 0, 0 -+ x.readMode = false -+} -+ -+func (x *xof) Read(p []byte) (n int, err error) { -+ if !x.readMode { -+ x.d.finalize(&x.root) -+ x.readMode = true -+ } -+ -+ if x.remaining == 0 { -+ return 0, io.EOF -+ } -+ -+ n = len(p) -+ if uint64(n) > x.remaining { -+ n = int(x.remaining) -+ p = p[:n] -+ } -+ -+ if x.offset > 0 { -+ blockRemaining := Size - x.offset -+ if n < blockRemaining { -+ x.offset += copy(p, x.block[x.offset:]) -+ x.remaining -= uint64(n) -+ return -+ } -+ copy(p, x.block[x.offset:]) -+ p = p[blockRemaining:] -+ x.offset = 0 -+ x.remaining -= uint64(blockRemaining) -+ } -+ -+ for len(p) >= Size { -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ copy(p, x.block[:]) -+ p = p[Size:] -+ x.remaining -= uint64(Size) -+ } -+ -+ if todo := len(p); todo > 0 { -+ if x.remaining < uint64(Size) { -+ x.cfg[0] = byte(x.remaining) -+ } -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ x.offset = copy(p, x.block[:todo]) -+ x.remaining -= uint64(todo) -+ } -+ return -+} -+ -+func (d *digest) initConfig(cfg *[Size]byte) { -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ for i := range d.h { -+ d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) -+ } -+} -diff --git a/vendor/golang.org/x/crypto/blake2b/register.go b/vendor/golang.org/x/crypto/blake2b/register.go -new file mode 100644 -index 000000000000..9d8633963cb6 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2b/register.go -@@ -0,0 +1,33 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.9 -+// +build go1.9 -+ -+package blake2b -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ newHash256 := func() hash.Hash { -+ h, _ := New256(nil) -+ return h -+ } -+ newHash384 := func() hash.Hash { -+ h, _ := New384(nil) -+ return h -+ } -+ -+ newHash512 := func() hash.Hash { -+ h, _ := New512(nil) -+ return h -+ } -+ -+ crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) -+ crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) -+ crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) -+} -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s.go b/vendor/golang.org/x/crypto/blake2s/blake2s.go -new file mode 100644 -index 000000000000..e3f46aab3a1a ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2s.go -@@ -0,0 +1,246 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package blake2s implements the BLAKE2s hash algorithm defined by RFC 7693 -+// and the extendable output function (XOF) BLAKE2Xs. -+// -+// BLAKE2s is optimized for 8- to 32-bit platforms and produces digests of any -+// size between 1 and 32 bytes. -+// For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf -+// and for BLAKE2Xs see https://blake2.net/blake2x.pdf -+// -+// If you aren't sure which function you need, use BLAKE2s (Sum256 or New256). -+// If you need a secret-key MAC (message authentication code), use the New256 -+// function with a non-nil key. -+// -+// BLAKE2X is a construction to compute hash values larger than 32 bytes. It -+// can produce hash values between 0 and 65535 bytes. -+package blake2s // import "golang.org/x/crypto/blake2s" -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "hash" -+) -+ -+const ( -+ // The blocksize of BLAKE2s in bytes. -+ BlockSize = 64 -+ -+ // The hash size of BLAKE2s-256 in bytes. -+ Size = 32 -+ -+ // The hash size of BLAKE2s-128 in bytes. -+ Size128 = 16 -+) -+ -+var errKeySize = errors.New("blake2s: invalid key size") -+ -+var iv = [8]uint32{ -+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, -+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, -+} -+ -+// Sum256 returns the BLAKE2s-256 checksum of the data. -+func Sum256(data []byte) [Size]byte { -+ var sum [Size]byte -+ checkSum(&sum, Size, data) -+ return sum -+} -+ -+// New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil -+// key turns the hash into a MAC. The key must between zero and 32 bytes long. -+// When the key is nil, the returned hash.Hash implements BinaryMarshaler -+// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. -+func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } -+ -+// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a -+// non-empty key. Note that a 128-bit digest is too small to be secure as a -+// cryptographic hash and should only be used as a MAC, thus the key argument -+// is not optional. -+func New128(key []byte) (hash.Hash, error) { -+ if len(key) == 0 { -+ return nil, errors.New("blake2s: a key is required for a 128-bit hash") -+ } -+ return newDigest(Size128, key) -+} -+ -+func newDigest(hashSize int, key []byte) (*digest, error) { -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ d := &digest{ -+ size: hashSize, -+ keyLen: len(key), -+ } -+ copy(d.key[:], key) -+ d.Reset() -+ return d, nil -+} -+ -+func checkSum(sum *[Size]byte, hashSize int, data []byte) { -+ var ( -+ h [8]uint32 -+ c [2]uint32 -+ ) -+ -+ h = iv -+ h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24) -+ -+ if length := len(data); length > BlockSize { -+ n := length &^ (BlockSize - 1) -+ if length == n { -+ n -= BlockSize -+ } -+ hashBlocks(&h, &c, 0, data[:n]) -+ data = data[n:] -+ } -+ -+ var block [BlockSize]byte -+ offset := copy(block[:], data) -+ remaining := uint32(BlockSize - offset) -+ -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) -+ -+ for i, v := range h { -+ binary.LittleEndian.PutUint32(sum[4*i:], v) -+ } -+} -+ -+type digest struct { -+ h [8]uint32 -+ c [2]uint32 -+ size int -+ block [BlockSize]byte -+ offset int -+ -+ key [BlockSize]byte -+ keyLen int -+} -+ -+const ( -+ magic = "b2s" -+ marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1 -+) -+ -+func (d *digest) MarshalBinary() ([]byte, error) { -+ if d.keyLen != 0 { -+ return nil, errors.New("crypto/blake2s: cannot marshal MACs") -+ } -+ b := make([]byte, 0, marshaledSize) -+ b = append(b, magic...) -+ for i := 0; i < 8; i++ { -+ b = appendUint32(b, d.h[i]) -+ } -+ b = appendUint32(b, d.c[0]) -+ b = appendUint32(b, d.c[1]) -+ // Maximum value for size is 32 -+ b = append(b, byte(d.size)) -+ b = append(b, d.block[:]...) -+ b = append(b, byte(d.offset)) -+ return b, nil -+} -+ -+func (d *digest) UnmarshalBinary(b []byte) error { -+ if len(b) < len(magic) || string(b[:len(magic)]) != magic { -+ return errors.New("crypto/blake2s: invalid hash state identifier") -+ } -+ if len(b) != marshaledSize { -+ return errors.New("crypto/blake2s: invalid hash state size") -+ } -+ b = b[len(magic):] -+ for i := 0; i < 8; i++ { -+ b, d.h[i] = consumeUint32(b) -+ } -+ b, d.c[0] = consumeUint32(b) -+ b, d.c[1] = consumeUint32(b) -+ d.size = int(b[0]) -+ b = b[1:] -+ copy(d.block[:], b[:BlockSize]) -+ b = b[BlockSize:] -+ d.offset = int(b[0]) -+ return nil -+} -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Size() int { return d.size } -+ -+func (d *digest) Reset() { -+ d.h = iv -+ d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24) -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ if d.keyLen > 0 { -+ d.block = d.key -+ d.offset = BlockSize -+ } -+} -+ -+func (d *digest) Write(p []byte) (n int, err error) { -+ n = len(p) -+ -+ if d.offset > 0 { -+ remaining := BlockSize - d.offset -+ if n <= remaining { -+ d.offset += copy(d.block[d.offset:], p) -+ return -+ } -+ copy(d.block[d.offset:], p[:remaining]) -+ hashBlocks(&d.h, &d.c, 0, d.block[:]) -+ d.offset = 0 -+ p = p[remaining:] -+ } -+ -+ if length := len(p); length > BlockSize { -+ nn := length &^ (BlockSize - 1) -+ if length == nn { -+ nn -= BlockSize -+ } -+ hashBlocks(&d.h, &d.c, 0, p[:nn]) -+ p = p[nn:] -+ } -+ -+ d.offset += copy(d.block[:], p) -+ return -+} -+ -+func (d *digest) Sum(sum []byte) []byte { -+ var hash [Size]byte -+ d.finalize(&hash) -+ return append(sum, hash[:d.size]...) -+} -+ -+func (d *digest) finalize(hash *[Size]byte) { -+ var block [BlockSize]byte -+ h := d.h -+ c := d.c -+ -+ copy(block[:], d.block[:d.offset]) -+ remaining := uint32(BlockSize - d.offset) -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) -+ for i, v := range h { -+ binary.LittleEndian.PutUint32(hash[4*i:], v) -+ } -+} -+ -+func appendUint32(b []byte, x uint32) []byte { -+ var a [4]byte -+ binary.BigEndian.PutUint32(a[:], x) -+ return append(b, a[:]...) -+} -+ -+func consumeUint32(b []byte) ([]byte, uint32) { -+ x := binary.BigEndian.Uint32(b) -+ return b[4:], x -+} -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_386.go b/vendor/golang.org/x/crypto/blake2s/blake2s_386.go -new file mode 100644 -index 000000000000..b4463fb4dc0e ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2s_386.go -@@ -0,0 +1,33 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build 386 && gc && !purego -+// +build 386,gc,!purego -+ -+package blake2s -+ -+import "golang.org/x/sys/cpu" -+ -+var ( -+ useSSE4 = false -+ useSSSE3 = cpu.X86.HasSSSE3 -+ useSSE2 = cpu.X86.HasSSE2 -+) -+ -+//go:noescape -+func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ switch { -+ case useSSSE3: -+ hashBlocksSSSE3(h, c, flag, blocks) -+ case useSSE2: -+ hashBlocksSSE2(h, c, flag, blocks) -+ default: -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_386.s b/vendor/golang.org/x/crypto/blake2s/blake2s_386.s -new file mode 100644 -index 000000000000..603d00ca3201 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2s_386.s -@@ -0,0 +1,430 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build 386 && gc && !purego -+// +build 386,gc,!purego -+ -+#include "textflag.h" -+ -+DATA iv0<>+0x00(SB)/4, $0x6a09e667 -+DATA iv0<>+0x04(SB)/4, $0xbb67ae85 -+DATA iv0<>+0x08(SB)/4, $0x3c6ef372 -+DATA iv0<>+0x0c(SB)/4, $0xa54ff53a -+GLOBL iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA iv1<>+0x00(SB)/4, $0x510e527f -+DATA iv1<>+0x04(SB)/4, $0x9b05688c -+DATA iv1<>+0x08(SB)/4, $0x1f83d9ab -+DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 -+GLOBL iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol16<>+0x00(SB)/8, $0x0504070601000302 -+DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -+GLOBL rol16<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol8<>+0x00(SB)/8, $0x0407060500030201 -+DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 -+GLOBL rol8<>(SB), (NOPTR+RODATA), $16 -+ -+DATA counter<>+0x00(SB)/8, $0x40 -+DATA counter<>+0x08(SB)/8, $0x0 -+GLOBL counter<>(SB), (NOPTR+RODATA), $16 -+ -+#define ROTL_SSE2(n, t, v) \ -+ MOVO v, t; \ -+ PSLLL $n, t; \ -+ PSRLL $(32-n), v; \ -+ PXOR t, v -+ -+#define ROTL_SSSE3(c, v) \ -+ PSHUFB c, v -+ -+#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+#define PRECOMPUTE(dst, off, src, t) \ -+ MOVL 0*4(src), t; \ -+ MOVL t, 0*4+off+0(dst); \ -+ MOVL t, 9*4+off+64(dst); \ -+ MOVL t, 5*4+off+128(dst); \ -+ MOVL t, 14*4+off+192(dst); \ -+ MOVL t, 4*4+off+256(dst); \ -+ MOVL t, 2*4+off+320(dst); \ -+ MOVL t, 8*4+off+384(dst); \ -+ MOVL t, 12*4+off+448(dst); \ -+ MOVL t, 3*4+off+512(dst); \ -+ MOVL t, 15*4+off+576(dst); \ -+ MOVL 1*4(src), t; \ -+ MOVL t, 4*4+off+0(dst); \ -+ MOVL t, 8*4+off+64(dst); \ -+ MOVL t, 14*4+off+128(dst); \ -+ MOVL t, 5*4+off+192(dst); \ -+ MOVL t, 12*4+off+256(dst); \ -+ MOVL t, 11*4+off+320(dst); \ -+ MOVL t, 1*4+off+384(dst); \ -+ MOVL t, 6*4+off+448(dst); \ -+ MOVL t, 10*4+off+512(dst); \ -+ MOVL t, 3*4+off+576(dst); \ -+ MOVL 2*4(src), t; \ -+ MOVL t, 1*4+off+0(dst); \ -+ MOVL t, 13*4+off+64(dst); \ -+ MOVL t, 6*4+off+128(dst); \ -+ MOVL t, 8*4+off+192(dst); \ -+ MOVL t, 2*4+off+256(dst); \ -+ MOVL t, 0*4+off+320(dst); \ -+ MOVL t, 14*4+off+384(dst); \ -+ MOVL t, 11*4+off+448(dst); \ -+ MOVL t, 12*4+off+512(dst); \ -+ MOVL t, 4*4+off+576(dst); \ -+ MOVL 3*4(src), t; \ -+ MOVL t, 5*4+off+0(dst); \ -+ MOVL t, 15*4+off+64(dst); \ -+ MOVL t, 9*4+off+128(dst); \ -+ MOVL t, 1*4+off+192(dst); \ -+ MOVL t, 11*4+off+256(dst); \ -+ MOVL t, 7*4+off+320(dst); \ -+ MOVL t, 13*4+off+384(dst); \ -+ MOVL t, 3*4+off+448(dst); \ -+ MOVL t, 6*4+off+512(dst); \ -+ MOVL t, 10*4+off+576(dst); \ -+ MOVL 4*4(src), t; \ -+ MOVL t, 2*4+off+0(dst); \ -+ MOVL t, 1*4+off+64(dst); \ -+ MOVL t, 15*4+off+128(dst); \ -+ MOVL t, 10*4+off+192(dst); \ -+ MOVL t, 6*4+off+256(dst); \ -+ MOVL t, 8*4+off+320(dst); \ -+ MOVL t, 3*4+off+384(dst); \ -+ MOVL t, 13*4+off+448(dst); \ -+ MOVL t, 14*4+off+512(dst); \ -+ MOVL t, 5*4+off+576(dst); \ -+ MOVL 5*4(src), t; \ -+ MOVL t, 6*4+off+0(dst); \ -+ MOVL t, 11*4+off+64(dst); \ -+ MOVL t, 2*4+off+128(dst); \ -+ MOVL t, 9*4+off+192(dst); \ -+ MOVL t, 1*4+off+256(dst); \ -+ MOVL t, 13*4+off+320(dst); \ -+ MOVL t, 4*4+off+384(dst); \ -+ MOVL t, 8*4+off+448(dst); \ -+ MOVL t, 15*4+off+512(dst); \ -+ MOVL t, 7*4+off+576(dst); \ -+ MOVL 6*4(src), t; \ -+ MOVL t, 3*4+off+0(dst); \ -+ MOVL t, 7*4+off+64(dst); \ -+ MOVL t, 13*4+off+128(dst); \ -+ MOVL t, 12*4+off+192(dst); \ -+ MOVL t, 10*4+off+256(dst); \ -+ MOVL t, 1*4+off+320(dst); \ -+ MOVL t, 9*4+off+384(dst); \ -+ MOVL t, 14*4+off+448(dst); \ -+ MOVL t, 0*4+off+512(dst); \ -+ MOVL t, 6*4+off+576(dst); \ -+ MOVL 7*4(src), t; \ -+ MOVL t, 7*4+off+0(dst); \ -+ MOVL t, 14*4+off+64(dst); \ -+ MOVL t, 10*4+off+128(dst); \ -+ MOVL t, 0*4+off+192(dst); \ -+ MOVL t, 5*4+off+256(dst); \ -+ MOVL t, 9*4+off+320(dst); \ -+ MOVL t, 12*4+off+384(dst); \ -+ MOVL t, 1*4+off+448(dst); \ -+ MOVL t, 13*4+off+512(dst); \ -+ MOVL t, 2*4+off+576(dst); \ -+ MOVL 8*4(src), t; \ -+ MOVL t, 8*4+off+0(dst); \ -+ MOVL t, 5*4+off+64(dst); \ -+ MOVL t, 4*4+off+128(dst); \ -+ MOVL t, 15*4+off+192(dst); \ -+ MOVL t, 14*4+off+256(dst); \ -+ MOVL t, 3*4+off+320(dst); \ -+ MOVL t, 11*4+off+384(dst); \ -+ MOVL t, 10*4+off+448(dst); \ -+ MOVL t, 7*4+off+512(dst); \ -+ MOVL t, 1*4+off+576(dst); \ -+ MOVL 9*4(src), t; \ -+ MOVL t, 12*4+off+0(dst); \ -+ MOVL t, 2*4+off+64(dst); \ -+ MOVL t, 11*4+off+128(dst); \ -+ MOVL t, 4*4+off+192(dst); \ -+ MOVL t, 0*4+off+256(dst); \ -+ MOVL t, 15*4+off+320(dst); \ -+ MOVL t, 10*4+off+384(dst); \ -+ MOVL t, 7*4+off+448(dst); \ -+ MOVL t, 5*4+off+512(dst); \ -+ MOVL t, 9*4+off+576(dst); \ -+ MOVL 10*4(src), t; \ -+ MOVL t, 9*4+off+0(dst); \ -+ MOVL t, 4*4+off+64(dst); \ -+ MOVL t, 8*4+off+128(dst); \ -+ MOVL t, 13*4+off+192(dst); \ -+ MOVL t, 3*4+off+256(dst); \ -+ MOVL t, 5*4+off+320(dst); \ -+ MOVL t, 7*4+off+384(dst); \ -+ MOVL t, 15*4+off+448(dst); \ -+ MOVL t, 11*4+off+512(dst); \ -+ MOVL t, 0*4+off+576(dst); \ -+ MOVL 11*4(src), t; \ -+ MOVL t, 13*4+off+0(dst); \ -+ MOVL t, 10*4+off+64(dst); \ -+ MOVL t, 0*4+off+128(dst); \ -+ MOVL t, 3*4+off+192(dst); \ -+ MOVL t, 9*4+off+256(dst); \ -+ MOVL t, 6*4+off+320(dst); \ -+ MOVL t, 15*4+off+384(dst); \ -+ MOVL t, 4*4+off+448(dst); \ -+ MOVL t, 2*4+off+512(dst); \ -+ MOVL t, 12*4+off+576(dst); \ -+ MOVL 12*4(src), t; \ -+ MOVL t, 10*4+off+0(dst); \ -+ MOVL t, 12*4+off+64(dst); \ -+ MOVL t, 1*4+off+128(dst); \ -+ MOVL t, 6*4+off+192(dst); \ -+ MOVL t, 13*4+off+256(dst); \ -+ MOVL t, 4*4+off+320(dst); \ -+ MOVL t, 0*4+off+384(dst); \ -+ MOVL t, 2*4+off+448(dst); \ -+ MOVL t, 8*4+off+512(dst); \ -+ MOVL t, 14*4+off+576(dst); \ -+ MOVL 13*4(src), t; \ -+ MOVL t, 14*4+off+0(dst); \ -+ MOVL t, 3*4+off+64(dst); \ -+ MOVL t, 7*4+off+128(dst); \ -+ MOVL t, 2*4+off+192(dst); \ -+ MOVL t, 15*4+off+256(dst); \ -+ MOVL t, 12*4+off+320(dst); \ -+ MOVL t, 6*4+off+384(dst); \ -+ MOVL t, 0*4+off+448(dst); \ -+ MOVL t, 9*4+off+512(dst); \ -+ MOVL t, 11*4+off+576(dst); \ -+ MOVL 14*4(src), t; \ -+ MOVL t, 11*4+off+0(dst); \ -+ MOVL t, 0*4+off+64(dst); \ -+ MOVL t, 12*4+off+128(dst); \ -+ MOVL t, 7*4+off+192(dst); \ -+ MOVL t, 8*4+off+256(dst); \ -+ MOVL t, 14*4+off+320(dst); \ -+ MOVL t, 2*4+off+384(dst); \ -+ MOVL t, 5*4+off+448(dst); \ -+ MOVL t, 1*4+off+512(dst); \ -+ MOVL t, 13*4+off+576(dst); \ -+ MOVL 15*4(src), t; \ -+ MOVL t, 15*4+off+0(dst); \ -+ MOVL t, 6*4+off+64(dst); \ -+ MOVL t, 3*4+off+128(dst); \ -+ MOVL t, 11*4+off+192(dst); \ -+ MOVL t, 7*4+off+256(dst); \ -+ MOVL t, 10*4+off+320(dst); \ -+ MOVL t, 5*4+off+384(dst); \ -+ MOVL t, 9*4+off+448(dst); \ -+ MOVL t, 4*4+off+512(dst); \ -+ MOVL t, 8*4+off+576(dst) -+ -+// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT ·hashBlocksSSE2(SB), 0, $672-24 // frame = 656 + 16 byte alignment -+ MOVL h+0(FP), AX -+ MOVL c+4(FP), BX -+ MOVL flag+8(FP), CX -+ MOVL blocks_base+12(FP), SI -+ MOVL blocks_len+16(FP), DX -+ -+ MOVL SP, DI -+ ADDL $15, DI -+ ANDL $~15, DI -+ -+ MOVL CX, 8(DI) -+ MOVL 0(BX), CX -+ MOVL CX, 0(DI) -+ MOVL 4(BX), CX -+ MOVL CX, 4(DI) -+ XORL CX, CX -+ MOVL CX, 12(DI) -+ -+ MOVOU 0(AX), X0 -+ MOVOU 16(AX), X1 -+ MOVOU counter<>(SB), X2 -+ -+loop: -+ MOVO X0, X4 -+ MOVO X1, X5 -+ MOVOU iv0<>(SB), X6 -+ MOVOU iv1<>(SB), X7 -+ -+ MOVO 0(DI), X3 -+ PADDQ X2, X3 -+ PXOR X3, X7 -+ MOVO X3, 0(DI) -+ -+ PRECOMPUTE(DI, 16, SI, CX) -+ ROUND_SSE2(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3) -+ -+ PXOR X4, X0 -+ PXOR X5, X1 -+ PXOR X6, X0 -+ PXOR X7, X1 -+ -+ LEAL 64(SI), SI -+ SUBL $64, DX -+ JNE loop -+ -+ MOVL 0(DI), CX -+ MOVL CX, 0(BX) -+ MOVL 4(DI), CX -+ MOVL CX, 4(BX) -+ -+ MOVOU X0, 0(AX) -+ MOVOU X1, 16(AX) -+ -+ RET -+ -+// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT ·hashBlocksSSSE3(SB), 0, $704-24 // frame = 688 + 16 byte alignment -+ MOVL h+0(FP), AX -+ MOVL c+4(FP), BX -+ MOVL flag+8(FP), CX -+ MOVL blocks_base+12(FP), SI -+ MOVL blocks_len+16(FP), DX -+ -+ MOVL SP, DI -+ ADDL $15, DI -+ ANDL $~15, DI -+ -+ MOVL CX, 8(DI) -+ MOVL 0(BX), CX -+ MOVL CX, 0(DI) -+ MOVL 4(BX), CX -+ MOVL CX, 4(DI) -+ XORL CX, CX -+ MOVL CX, 12(DI) -+ -+ MOVOU 0(AX), X0 -+ MOVOU 16(AX), X1 -+ MOVOU counter<>(SB), X2 -+ -+loop: -+ MOVO X0, 656(DI) -+ MOVO X1, 672(DI) -+ MOVO X0, X4 -+ MOVO X1, X5 -+ MOVOU iv0<>(SB), X6 -+ MOVOU iv1<>(SB), X7 -+ -+ MOVO 0(DI), X3 -+ PADDQ X2, X3 -+ PXOR X3, X7 -+ MOVO X3, 0(DI) -+ -+ MOVOU rol16<>(SB), X0 -+ MOVOU rol8<>(SB), X1 -+ -+ PRECOMPUTE(DI, 16, SI, CX) -+ ROUND_SSSE3(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3, X0, X1) -+ -+ MOVO 656(DI), X0 -+ MOVO 672(DI), X1 -+ PXOR X4, X0 -+ PXOR X5, X1 -+ PXOR X6, X0 -+ PXOR X7, X1 -+ -+ LEAL 64(SI), SI -+ SUBL $64, DX -+ JNE loop -+ -+ MOVL 0(DI), CX -+ MOVL CX, 0(BX) -+ MOVL 4(DI), CX -+ MOVL CX, 4(BX) -+ -+ MOVOU X0, 0(AX) -+ MOVOU X1, 16(AX) -+ -+ RET -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go -new file mode 100644 -index 000000000000..becdaa120ff8 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go -@@ -0,0 +1,38 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+package blake2s -+ -+import "golang.org/x/sys/cpu" -+ -+var ( -+ useSSE4 = cpu.X86.HasSSE41 -+ useSSSE3 = cpu.X86.HasSSSE3 -+ useSSE2 = cpu.X86.HasSSE2 -+) -+ -+//go:noescape -+func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ switch { -+ case useSSE4: -+ hashBlocksSSE4(h, c, flag, blocks) -+ case useSSSE3: -+ hashBlocksSSSE3(h, c, flag, blocks) -+ case useSSE2: -+ hashBlocksSSE2(h, c, flag, blocks) -+ default: -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s -new file mode 100644 -index 000000000000..e9df7a7c2199 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s -@@ -0,0 +1,433 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA iv0<>+0x00(SB)/4, $0x6a09e667 -+DATA iv0<>+0x04(SB)/4, $0xbb67ae85 -+DATA iv0<>+0x08(SB)/4, $0x3c6ef372 -+DATA iv0<>+0x0c(SB)/4, $0xa54ff53a -+GLOBL iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA iv1<>+0x00(SB)/4, $0x510e527f -+DATA iv1<>+0x04(SB)/4, $0x9b05688c -+DATA iv1<>+0x08(SB)/4, $0x1f83d9ab -+DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 -+GLOBL iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol16<>+0x00(SB)/8, $0x0504070601000302 -+DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -+GLOBL rol16<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol8<>+0x00(SB)/8, $0x0407060500030201 -+DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 -+GLOBL rol8<>(SB), (NOPTR+RODATA), $16 -+ -+DATA counter<>+0x00(SB)/8, $0x40 -+DATA counter<>+0x08(SB)/8, $0x0 -+GLOBL counter<>(SB), (NOPTR+RODATA), $16 -+ -+#define ROTL_SSE2(n, t, v) \ -+ MOVO v, t; \ -+ PSLLL $n, t; \ -+ PSRLL $(32-n), v; \ -+ PXOR t, v -+ -+#define ROTL_SSSE3(c, v) \ -+ PSHUFB c, v -+ -+#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+ -+#define LOAD_MSG_SSE4(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \ -+ MOVL i0*4(src), m0; \ -+ PINSRD $1, i1*4(src), m0; \ -+ PINSRD $2, i2*4(src), m0; \ -+ PINSRD $3, i3*4(src), m0; \ -+ MOVL i4*4(src), m1; \ -+ PINSRD $1, i5*4(src), m1; \ -+ PINSRD $2, i6*4(src), m1; \ -+ PINSRD $3, i7*4(src), m1; \ -+ MOVL i8*4(src), m2; \ -+ PINSRD $1, i9*4(src), m2; \ -+ PINSRD $2, i10*4(src), m2; \ -+ PINSRD $3, i11*4(src), m2; \ -+ MOVL i12*4(src), m3; \ -+ PINSRD $1, i13*4(src), m3; \ -+ PINSRD $2, i14*4(src), m3; \ -+ PINSRD $3, i15*4(src), m3 -+ -+#define PRECOMPUTE_MSG(dst, off, src, R8, R9, R10, R11, R12, R13, R14, R15) \ -+ MOVQ 0*4(src), R8; \ -+ MOVQ 2*4(src), R9; \ -+ MOVQ 4*4(src), R10; \ -+ MOVQ 6*4(src), R11; \ -+ MOVQ 8*4(src), R12; \ -+ MOVQ 10*4(src), R13; \ -+ MOVQ 12*4(src), R14; \ -+ MOVQ 14*4(src), R15; \ -+ \ -+ MOVL R8, 0*4+off+0(dst); \ -+ MOVL R8, 9*4+off+64(dst); \ -+ MOVL R8, 5*4+off+128(dst); \ -+ MOVL R8, 14*4+off+192(dst); \ -+ MOVL R8, 4*4+off+256(dst); \ -+ MOVL R8, 2*4+off+320(dst); \ -+ MOVL R8, 8*4+off+384(dst); \ -+ MOVL R8, 12*4+off+448(dst); \ -+ MOVL R8, 3*4+off+512(dst); \ -+ MOVL R8, 15*4+off+576(dst); \ -+ SHRQ $32, R8; \ -+ MOVL R8, 4*4+off+0(dst); \ -+ MOVL R8, 8*4+off+64(dst); \ -+ MOVL R8, 14*4+off+128(dst); \ -+ MOVL R8, 5*4+off+192(dst); \ -+ MOVL R8, 12*4+off+256(dst); \ -+ MOVL R8, 11*4+off+320(dst); \ -+ MOVL R8, 1*4+off+384(dst); \ -+ MOVL R8, 6*4+off+448(dst); \ -+ MOVL R8, 10*4+off+512(dst); \ -+ MOVL R8, 3*4+off+576(dst); \ -+ \ -+ MOVL R9, 1*4+off+0(dst); \ -+ MOVL R9, 13*4+off+64(dst); \ -+ MOVL R9, 6*4+off+128(dst); \ -+ MOVL R9, 8*4+off+192(dst); \ -+ MOVL R9, 2*4+off+256(dst); \ -+ MOVL R9, 0*4+off+320(dst); \ -+ MOVL R9, 14*4+off+384(dst); \ -+ MOVL R9, 11*4+off+448(dst); \ -+ MOVL R9, 12*4+off+512(dst); \ -+ MOVL R9, 4*4+off+576(dst); \ -+ SHRQ $32, R9; \ -+ MOVL R9, 5*4+off+0(dst); \ -+ MOVL R9, 15*4+off+64(dst); \ -+ MOVL R9, 9*4+off+128(dst); \ -+ MOVL R9, 1*4+off+192(dst); \ -+ MOVL R9, 11*4+off+256(dst); \ -+ MOVL R9, 7*4+off+320(dst); \ -+ MOVL R9, 13*4+off+384(dst); \ -+ MOVL R9, 3*4+off+448(dst); \ -+ MOVL R9, 6*4+off+512(dst); \ -+ MOVL R9, 10*4+off+576(dst); \ -+ \ -+ MOVL R10, 2*4+off+0(dst); \ -+ MOVL R10, 1*4+off+64(dst); \ -+ MOVL R10, 15*4+off+128(dst); \ -+ MOVL R10, 10*4+off+192(dst); \ -+ MOVL R10, 6*4+off+256(dst); \ -+ MOVL R10, 8*4+off+320(dst); \ -+ MOVL R10, 3*4+off+384(dst); \ -+ MOVL R10, 13*4+off+448(dst); \ -+ MOVL R10, 14*4+off+512(dst); \ -+ MOVL R10, 5*4+off+576(dst); \ -+ SHRQ $32, R10; \ -+ MOVL R10, 6*4+off+0(dst); \ -+ MOVL R10, 11*4+off+64(dst); \ -+ MOVL R10, 2*4+off+128(dst); \ -+ MOVL R10, 9*4+off+192(dst); \ -+ MOVL R10, 1*4+off+256(dst); \ -+ MOVL R10, 13*4+off+320(dst); \ -+ MOVL R10, 4*4+off+384(dst); \ -+ MOVL R10, 8*4+off+448(dst); \ -+ MOVL R10, 15*4+off+512(dst); \ -+ MOVL R10, 7*4+off+576(dst); \ -+ \ -+ MOVL R11, 3*4+off+0(dst); \ -+ MOVL R11, 7*4+off+64(dst); \ -+ MOVL R11, 13*4+off+128(dst); \ -+ MOVL R11, 12*4+off+192(dst); \ -+ MOVL R11, 10*4+off+256(dst); \ -+ MOVL R11, 1*4+off+320(dst); \ -+ MOVL R11, 9*4+off+384(dst); \ -+ MOVL R11, 14*4+off+448(dst); \ -+ MOVL R11, 0*4+off+512(dst); \ -+ MOVL R11, 6*4+off+576(dst); \ -+ SHRQ $32, R11; \ -+ MOVL R11, 7*4+off+0(dst); \ -+ MOVL R11, 14*4+off+64(dst); \ -+ MOVL R11, 10*4+off+128(dst); \ -+ MOVL R11, 0*4+off+192(dst); \ -+ MOVL R11, 5*4+off+256(dst); \ -+ MOVL R11, 9*4+off+320(dst); \ -+ MOVL R11, 12*4+off+384(dst); \ -+ MOVL R11, 1*4+off+448(dst); \ -+ MOVL R11, 13*4+off+512(dst); \ -+ MOVL R11, 2*4+off+576(dst); \ -+ \ -+ MOVL R12, 8*4+off+0(dst); \ -+ MOVL R12, 5*4+off+64(dst); \ -+ MOVL R12, 4*4+off+128(dst); \ -+ MOVL R12, 15*4+off+192(dst); \ -+ MOVL R12, 14*4+off+256(dst); \ -+ MOVL R12, 3*4+off+320(dst); \ -+ MOVL R12, 11*4+off+384(dst); \ -+ MOVL R12, 10*4+off+448(dst); \ -+ MOVL R12, 7*4+off+512(dst); \ -+ MOVL R12, 1*4+off+576(dst); \ -+ SHRQ $32, R12; \ -+ MOVL R12, 12*4+off+0(dst); \ -+ MOVL R12, 2*4+off+64(dst); \ -+ MOVL R12, 11*4+off+128(dst); \ -+ MOVL R12, 4*4+off+192(dst); \ -+ MOVL R12, 0*4+off+256(dst); \ -+ MOVL R12, 15*4+off+320(dst); \ -+ MOVL R12, 10*4+off+384(dst); \ -+ MOVL R12, 7*4+off+448(dst); \ -+ MOVL R12, 5*4+off+512(dst); \ -+ MOVL R12, 9*4+off+576(dst); \ -+ \ -+ MOVL R13, 9*4+off+0(dst); \ -+ MOVL R13, 4*4+off+64(dst); \ -+ MOVL R13, 8*4+off+128(dst); \ -+ MOVL R13, 13*4+off+192(dst); \ -+ MOVL R13, 3*4+off+256(dst); \ -+ MOVL R13, 5*4+off+320(dst); \ -+ MOVL R13, 7*4+off+384(dst); \ -+ MOVL R13, 15*4+off+448(dst); \ -+ MOVL R13, 11*4+off+512(dst); \ -+ MOVL R13, 0*4+off+576(dst); \ -+ SHRQ $32, R13; \ -+ MOVL R13, 13*4+off+0(dst); \ -+ MOVL R13, 10*4+off+64(dst); \ -+ MOVL R13, 0*4+off+128(dst); \ -+ MOVL R13, 3*4+off+192(dst); \ -+ MOVL R13, 9*4+off+256(dst); \ -+ MOVL R13, 6*4+off+320(dst); \ -+ MOVL R13, 15*4+off+384(dst); \ -+ MOVL R13, 4*4+off+448(dst); \ -+ MOVL R13, 2*4+off+512(dst); \ -+ MOVL R13, 12*4+off+576(dst); \ -+ \ -+ MOVL R14, 10*4+off+0(dst); \ -+ MOVL R14, 12*4+off+64(dst); \ -+ MOVL R14, 1*4+off+128(dst); \ -+ MOVL R14, 6*4+off+192(dst); \ -+ MOVL R14, 13*4+off+256(dst); \ -+ MOVL R14, 4*4+off+320(dst); \ -+ MOVL R14, 0*4+off+384(dst); \ -+ MOVL R14, 2*4+off+448(dst); \ -+ MOVL R14, 8*4+off+512(dst); \ -+ MOVL R14, 14*4+off+576(dst); \ -+ SHRQ $32, R14; \ -+ MOVL R14, 14*4+off+0(dst); \ -+ MOVL R14, 3*4+off+64(dst); \ -+ MOVL R14, 7*4+off+128(dst); \ -+ MOVL R14, 2*4+off+192(dst); \ -+ MOVL R14, 15*4+off+256(dst); \ -+ MOVL R14, 12*4+off+320(dst); \ -+ MOVL R14, 6*4+off+384(dst); \ -+ MOVL R14, 0*4+off+448(dst); \ -+ MOVL R14, 9*4+off+512(dst); \ -+ MOVL R14, 11*4+off+576(dst); \ -+ \ -+ MOVL R15, 11*4+off+0(dst); \ -+ MOVL R15, 0*4+off+64(dst); \ -+ MOVL R15, 12*4+off+128(dst); \ -+ MOVL R15, 7*4+off+192(dst); \ -+ MOVL R15, 8*4+off+256(dst); \ -+ MOVL R15, 14*4+off+320(dst); \ -+ MOVL R15, 2*4+off+384(dst); \ -+ MOVL R15, 5*4+off+448(dst); \ -+ MOVL R15, 1*4+off+512(dst); \ -+ MOVL R15, 13*4+off+576(dst); \ -+ SHRQ $32, R15; \ -+ MOVL R15, 15*4+off+0(dst); \ -+ MOVL R15, 6*4+off+64(dst); \ -+ MOVL R15, 3*4+off+128(dst); \ -+ MOVL R15, 11*4+off+192(dst); \ -+ MOVL R15, 7*4+off+256(dst); \ -+ MOVL R15, 10*4+off+320(dst); \ -+ MOVL R15, 5*4+off+384(dst); \ -+ MOVL R15, 9*4+off+448(dst); \ -+ MOVL R15, 4*4+off+512(dst); \ -+ MOVL R15, 8*4+off+576(dst) -+ -+#define BLAKE2s_SSE2() \ -+ PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8) -+ -+#define BLAKE2s_SSSE3() \ -+ PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8, X13, X14) -+ -+#define BLAKE2s_SSE4() \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) -+ -+#define HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_FUNC) \ -+ MOVQ h, AX; \ -+ MOVQ c, BX; \ -+ MOVL flag, CX; \ -+ MOVQ blocks_base, SI; \ -+ MOVQ blocks_len, DX; \ -+ \ -+ MOVQ SP, BP; \ -+ ADDQ $15, BP; \ -+ ANDQ $~15, BP; \ -+ \ -+ MOVQ 0(BX), R9; \ -+ MOVQ R9, 0(BP); \ -+ MOVQ CX, 8(BP); \ -+ \ -+ MOVOU 0(AX), X0; \ -+ MOVOU 16(AX), X1; \ -+ MOVOU iv0<>(SB), X2; \ -+ MOVOU iv1<>(SB), X3 \ -+ \ -+ MOVOU counter<>(SB), X12; \ -+ MOVOU rol16<>(SB), X13; \ -+ MOVOU rol8<>(SB), X14; \ -+ MOVO 0(BP), X15; \ -+ \ -+ loop: \ -+ MOVO X0, X4; \ -+ MOVO X1, X5; \ -+ MOVO X2, X6; \ -+ MOVO X3, X7; \ -+ \ -+ PADDQ X12, X15; \ -+ PXOR X15, X7; \ -+ \ -+ BLAKE2s_FUNC(); \ -+ \ -+ PXOR X4, X0; \ -+ PXOR X5, X1; \ -+ PXOR X6, X0; \ -+ PXOR X7, X1; \ -+ \ -+ LEAQ 64(SI), SI; \ -+ SUBQ $64, DX; \ -+ JNE loop; \ -+ \ -+ MOVO X15, 0(BP); \ -+ MOVQ 0(BP), R9; \ -+ MOVQ R9, 0(BX); \ -+ \ -+ MOVOU X0, 0(AX); \ -+ MOVOU X1, 16(AX) -+ -+// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT ·hashBlocksSSE2(SB), 0, $672-48 // frame = 656 + 16 byte alignment -+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE2) -+ RET -+ -+// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT ·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment -+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSSE3) -+ RET -+ -+// func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT ·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment -+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) -+ RET -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go b/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go -new file mode 100644 -index 000000000000..24a1ff22adcf ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go -@@ -0,0 +1,178 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2s -+ -+import ( -+ "math/bits" -+) -+ -+// the precomputed values for BLAKE2s -+// there are 10 16-byte arrays - one for each round -+// the entries are calculated from the sigma constants. -+var precomputed = [10][16]byte{ -+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, -+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, -+ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, -+ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, -+ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, -+ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, -+ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, -+ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, -+ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, -+ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, -+} -+ -+func hashBlocksGeneric(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ var m [16]uint32 -+ c0, c1 := c[0], c[1] -+ -+ for i := 0; i < len(blocks); { -+ c0 += BlockSize -+ if c0 < BlockSize { -+ c1++ -+ } -+ -+ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] -+ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] -+ v12 ^= c0 -+ v13 ^= c1 -+ v14 ^= flag -+ -+ for j := range m { -+ m[j] = uint32(blocks[i]) | uint32(blocks[i+1])<<8 | uint32(blocks[i+2])<<16 | uint32(blocks[i+3])<<24 -+ i += 4 -+ } -+ -+ for k := range precomputed { -+ s := &(precomputed[k]) -+ -+ v0 += m[s[0]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft32(v12, -16) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft32(v4, -12) -+ v1 += m[s[1]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft32(v13, -16) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft32(v5, -12) -+ v2 += m[s[2]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft32(v14, -16) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft32(v6, -12) -+ v3 += m[s[3]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft32(v15, -16) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft32(v7, -12) -+ -+ v0 += m[s[4]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft32(v12, -8) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft32(v4, -7) -+ v1 += m[s[5]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft32(v13, -8) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft32(v5, -7) -+ v2 += m[s[6]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft32(v14, -8) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft32(v6, -7) -+ v3 += m[s[7]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft32(v15, -8) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft32(v7, -7) -+ -+ v0 += m[s[8]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft32(v15, -16) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft32(v5, -12) -+ v1 += m[s[9]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft32(v12, -16) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft32(v6, -12) -+ v2 += m[s[10]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft32(v13, -16) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft32(v7, -12) -+ v3 += m[s[11]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft32(v14, -16) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft32(v4, -12) -+ -+ v0 += m[s[12]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft32(v15, -8) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft32(v5, -7) -+ v1 += m[s[13]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft32(v12, -8) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft32(v6, -7) -+ v2 += m[s[14]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft32(v13, -8) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft32(v7, -7) -+ v3 += m[s[15]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft32(v14, -8) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft32(v4, -7) -+ } -+ -+ h[0] ^= v0 ^ v8 -+ h[1] ^= v1 ^ v9 -+ h[2] ^= v2 ^ v10 -+ h[3] ^= v3 ^ v11 -+ h[4] ^= v4 ^ v12 -+ h[5] ^= v5 ^ v13 -+ h[6] ^= v6 ^ v14 -+ h[7] ^= v7 ^ v15 -+ } -+ c[0], c[1] = c0, c1 -+} -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go b/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go -new file mode 100644 -index 000000000000..799dba0c4158 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go -@@ -0,0 +1,18 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (!amd64 && !386) || !gc || purego -+// +build !amd64,!386 !gc purego -+ -+package blake2s -+ -+var ( -+ useSSE4 = false -+ useSSSE3 = false -+ useSSE2 = false -+) -+ -+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ hashBlocksGeneric(h, c, flag, blocks) -+} -diff --git a/vendor/golang.org/x/crypto/blake2s/blake2x.go b/vendor/golang.org/x/crypto/blake2s/blake2x.go -new file mode 100644 -index 000000000000..828749ff01d1 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/blake2x.go -@@ -0,0 +1,178 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2s -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "io" -+) -+ -+// XOF defines the interface to hash functions that -+// support arbitrary-length output. -+type XOF interface { -+ // Write absorbs more data into the hash's state. It panics if called -+ // after Read. -+ io.Writer -+ -+ // Read reads more output from the hash. It returns io.EOF if the limit -+ // has been reached. -+ io.Reader -+ -+ // Clone returns a copy of the XOF in its current state. -+ Clone() XOF -+ -+ // Reset resets the XOF to its initial state. -+ Reset() -+} -+ -+// OutputLengthUnknown can be used as the size argument to NewXOF to indicate -+// the length of the output is not known in advance. -+const OutputLengthUnknown = 0 -+ -+// magicUnknownOutputLength is a magic value for the output size that indicates -+// an unknown number of output bytes. -+const magicUnknownOutputLength = 65535 -+ -+// maxOutputLength is the absolute maximum number of bytes to produce when the -+// number of output bytes is unknown. -+const maxOutputLength = (1 << 32) * 32 -+ -+// NewXOF creates a new variable-output-length hash. The hash either produce a -+// known number of bytes (1 <= size < 65535), or an unknown number of bytes -+// (size == OutputLengthUnknown). In the latter case, an absolute limit of -+// 128GiB applies. -+// -+// A non-nil key turns the hash into a MAC. The key must between -+// zero and 32 bytes long. -+func NewXOF(size uint16, key []byte) (XOF, error) { -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ if size == magicUnknownOutputLength { -+ // 2^16-1 indicates an unknown number of bytes and thus isn't a -+ // valid length. -+ return nil, errors.New("blake2s: XOF length too large") -+ } -+ if size == OutputLengthUnknown { -+ size = magicUnknownOutputLength -+ } -+ x := &xof{ -+ d: digest{ -+ size: Size, -+ keyLen: len(key), -+ }, -+ length: size, -+ } -+ copy(x.d.key[:], key) -+ x.Reset() -+ return x, nil -+} -+ -+type xof struct { -+ d digest -+ length uint16 -+ remaining uint64 -+ cfg, root, block [Size]byte -+ offset int -+ nodeOffset uint32 -+ readMode bool -+} -+ -+func (x *xof) Write(p []byte) (n int, err error) { -+ if x.readMode { -+ panic("blake2s: write to XOF after read") -+ } -+ return x.d.Write(p) -+} -+ -+func (x *xof) Clone() XOF { -+ clone := *x -+ return &clone -+} -+ -+func (x *xof) Reset() { -+ x.cfg[0] = byte(Size) -+ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length -+ binary.LittleEndian.PutUint16(x.cfg[12:], x.length) // XOF length -+ x.cfg[15] = byte(Size) // inner hash size -+ -+ x.d.Reset() -+ x.d.h[3] ^= uint32(x.length) -+ -+ x.remaining = uint64(x.length) -+ if x.remaining == magicUnknownOutputLength { -+ x.remaining = maxOutputLength -+ } -+ x.offset, x.nodeOffset = 0, 0 -+ x.readMode = false -+} -+ -+func (x *xof) Read(p []byte) (n int, err error) { -+ if !x.readMode { -+ x.d.finalize(&x.root) -+ x.readMode = true -+ } -+ -+ if x.remaining == 0 { -+ return 0, io.EOF -+ } -+ -+ n = len(p) -+ if uint64(n) > x.remaining { -+ n = int(x.remaining) -+ p = p[:n] -+ } -+ -+ if x.offset > 0 { -+ blockRemaining := Size - x.offset -+ if n < blockRemaining { -+ x.offset += copy(p, x.block[x.offset:]) -+ x.remaining -= uint64(n) -+ return -+ } -+ copy(p, x.block[x.offset:]) -+ p = p[blockRemaining:] -+ x.offset = 0 -+ x.remaining -= uint64(blockRemaining) -+ } -+ -+ for len(p) >= Size { -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ copy(p, x.block[:]) -+ p = p[Size:] -+ x.remaining -= uint64(Size) -+ } -+ -+ if todo := len(p); todo > 0 { -+ if x.remaining < uint64(Size) { -+ x.cfg[0] = byte(x.remaining) -+ } -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ x.offset = copy(p, x.block[:todo]) -+ x.remaining -= uint64(todo) -+ } -+ -+ return -+} -+ -+func (d *digest) initConfig(cfg *[Size]byte) { -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ for i := range d.h { -+ d.h[i] = iv[i] ^ binary.LittleEndian.Uint32(cfg[i*4:]) -+ } -+} -diff --git a/vendor/golang.org/x/crypto/blake2s/register.go b/vendor/golang.org/x/crypto/blake2s/register.go -new file mode 100644 -index 000000000000..ef79ff3c67a1 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/blake2s/register.go -@@ -0,0 +1,22 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.9 -+// +build go1.9 -+ -+package blake2s -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ newHash256 := func() hash.Hash { -+ h, _ := New256(nil) -+ return h -+ } -+ -+ crypto.RegisterHash(crypto.BLAKE2s_256, newHash256) -+} -diff --git a/vendor/golang.org/x/crypto/bn256/bn256.go b/vendor/golang.org/x/crypto/bn256/bn256.go -new file mode 100644 -index 000000000000..9c99fcdb5de4 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/bn256.go -@@ -0,0 +1,429 @@ -+// Copyright 2012 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 bn256 implements a particular bilinear group. -+// -+// Bilinear groups are the basis of many of the new cryptographic protocols -+// that have been proposed over the past decade. They consist of a triplet of -+// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ -+// (where gₓ is a generator of the respective group). That function is called -+// a pairing function. -+// -+// This package specifically implements the Optimal Ate pairing over a 256-bit -+// Barreto-Naehrig curve as described in -+// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible -+// with the implementation described in that paper. -+// -+// This package previously claimed to operate at a 128-bit security level. -+// However, recent improvements in attacks mean that is no longer true. See -+// https://moderncrypto.org/mail-archive/curves/2016/000740.html. -+// -+// Deprecated: due to its weakened security, new systems should not rely on this -+// elliptic curve. This package is frozen, and not implemented in constant time. -+// There is a more complete implementation at github.com/cloudflare/bn256, but -+// note that it suffers from the same security issues of the underlying curve. -+package bn256 // import "golang.org/x/crypto/bn256" -+ -+import ( -+ "crypto/rand" -+ "io" -+ "math/big" -+) -+ -+// G1 is an abstract cyclic group. The zero value is suitable for use as the -+// output of an operation, but cannot be used as an input. -+type G1 struct { -+ p *curvePoint -+} -+ -+// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r. -+func RandomG1(r io.Reader) (*big.Int, *G1, error) { -+ var k *big.Int -+ var err error -+ -+ for { -+ k, err = rand.Int(r, Order) -+ if err != nil { -+ return nil, nil, err -+ } -+ if k.Sign() > 0 { -+ break -+ } -+ } -+ -+ return k, new(G1).ScalarBaseMult(k), nil -+} -+ -+func (e *G1) String() string { -+ if e.p == nil { -+ return "bn256.G1" + newCurvePoint(nil).String() -+ } -+ return "bn256.G1" + e.p.String() -+} -+ -+// ScalarBaseMult sets e to g*k where g is the generator of the group and -+// then returns e. -+func (e *G1) ScalarBaseMult(k *big.Int) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Mul(curveGen, k, new(bnPool)) -+ return e -+} -+ -+// ScalarMult sets e to a*k and then returns e. -+func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Mul(a.p, k, new(bnPool)) -+ return e -+} -+ -+// Add sets e to a+b and then returns e. -+// -+// Warning: this function is not complete, it fails for a equal to b. -+func (e *G1) Add(a, b *G1) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Add(a.p, b.p, new(bnPool)) -+ return e -+} -+ -+// Neg sets e to -a and then returns e. -+func (e *G1) Neg(a *G1) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Negative(a.p) -+ return e -+} -+ -+// Marshal converts n to a byte slice. -+func (e *G1) Marshal() []byte { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if e.p.IsInfinity() { -+ return make([]byte, numBytes*2) -+ } -+ -+ e.p.MakeAffine(nil) -+ -+ xBytes := new(big.Int).Mod(e.p.x, p).Bytes() -+ yBytes := new(big.Int).Mod(e.p.y, p).Bytes() -+ -+ ret := make([]byte, numBytes*2) -+ copy(ret[1*numBytes-len(xBytes):], xBytes) -+ copy(ret[2*numBytes-len(yBytes):], yBytes) -+ -+ return ret -+} -+ -+// Unmarshal sets e to the result of converting the output of Marshal back into -+// a group element and then returns e. -+func (e *G1) Unmarshal(m []byte) (*G1, bool) { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if len(m) != 2*numBytes { -+ return nil, false -+ } -+ -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ -+ e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) -+ e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) -+ -+ if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { -+ // This is the point at infinity. -+ e.p.y.SetInt64(1) -+ e.p.z.SetInt64(0) -+ e.p.t.SetInt64(0) -+ } else { -+ e.p.z.SetInt64(1) -+ e.p.t.SetInt64(1) -+ -+ if !e.p.IsOnCurve() { -+ return nil, false -+ } -+ } -+ -+ return e, true -+} -+ -+// G2 is an abstract cyclic group. The zero value is suitable for use as the -+// output of an operation, but cannot be used as an input. -+type G2 struct { -+ p *twistPoint -+} -+ -+// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r. -+func RandomG2(r io.Reader) (*big.Int, *G2, error) { -+ var k *big.Int -+ var err error -+ -+ for { -+ k, err = rand.Int(r, Order) -+ if err != nil { -+ return nil, nil, err -+ } -+ if k.Sign() > 0 { -+ break -+ } -+ } -+ -+ return k, new(G2).ScalarBaseMult(k), nil -+} -+ -+func (e *G2) String() string { -+ if e.p == nil { -+ return "bn256.G2" + newTwistPoint(nil).String() -+ } -+ return "bn256.G2" + e.p.String() -+} -+ -+// ScalarBaseMult sets e to g*k where g is the generator of the group and -+// then returns out. -+func (e *G2) ScalarBaseMult(k *big.Int) *G2 { -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ e.p.Mul(twistGen, k, new(bnPool)) -+ return e -+} -+ -+// ScalarMult sets e to a*k and then returns e. -+func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ e.p.Mul(a.p, k, new(bnPool)) -+ return e -+} -+ -+// Add sets e to a+b and then returns e. -+// -+// Warning: this function is not complete, it fails for a equal to b. -+func (e *G2) Add(a, b *G2) *G2 { -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ e.p.Add(a.p, b.p, new(bnPool)) -+ return e -+} -+ -+// Marshal converts n into a byte slice. -+func (n *G2) Marshal() []byte { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if n.p.IsInfinity() { -+ return make([]byte, numBytes*4) -+ } -+ -+ n.p.MakeAffine(nil) -+ -+ xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes() -+ xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes() -+ yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes() -+ yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes() -+ -+ ret := make([]byte, numBytes*4) -+ copy(ret[1*numBytes-len(xxBytes):], xxBytes) -+ copy(ret[2*numBytes-len(xyBytes):], xyBytes) -+ copy(ret[3*numBytes-len(yxBytes):], yxBytes) -+ copy(ret[4*numBytes-len(yyBytes):], yyBytes) -+ -+ return ret -+} -+ -+// Unmarshal sets e to the result of converting the output of Marshal back into -+// a group element and then returns e. -+func (e *G2) Unmarshal(m []byte) (*G2, bool) { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if len(m) != 4*numBytes { -+ return nil, false -+ } -+ -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ -+ e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) -+ e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) -+ e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) -+ e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) -+ -+ if e.p.x.x.Sign() == 0 && -+ e.p.x.y.Sign() == 0 && -+ e.p.y.x.Sign() == 0 && -+ e.p.y.y.Sign() == 0 { -+ // This is the point at infinity. -+ e.p.y.SetOne() -+ e.p.z.SetZero() -+ e.p.t.SetZero() -+ } else { -+ e.p.z.SetOne() -+ e.p.t.SetOne() -+ -+ if !e.p.IsOnCurve() { -+ return nil, false -+ } -+ } -+ -+ return e, true -+} -+ -+// GT is an abstract cyclic group. The zero value is suitable for use as the -+// output of an operation, but cannot be used as an input. -+type GT struct { -+ p *gfP12 -+} -+ -+func (e *GT) String() string { -+ if e.p == nil { -+ return "bn256.GT" + newGFp12(nil).String() -+ } -+ return "bn256.GT" + e.p.String() -+} -+ -+// ScalarMult sets e to a*k and then returns e. -+func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ e.p.Exp(a.p, k, new(bnPool)) -+ return e -+} -+ -+// Add sets e to a+b and then returns e. -+func (e *GT) Add(a, b *GT) *GT { -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ e.p.Mul(a.p, b.p, new(bnPool)) -+ return e -+} -+ -+// Neg sets e to -a and then returns e. -+func (e *GT) Neg(a *GT) *GT { -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ e.p.Invert(a.p, new(bnPool)) -+ return e -+} -+ -+// Marshal converts n into a byte slice. -+func (n *GT) Marshal() []byte { -+ n.p.Minimal() -+ -+ xxxBytes := n.p.x.x.x.Bytes() -+ xxyBytes := n.p.x.x.y.Bytes() -+ xyxBytes := n.p.x.y.x.Bytes() -+ xyyBytes := n.p.x.y.y.Bytes() -+ xzxBytes := n.p.x.z.x.Bytes() -+ xzyBytes := n.p.x.z.y.Bytes() -+ yxxBytes := n.p.y.x.x.Bytes() -+ yxyBytes := n.p.y.x.y.Bytes() -+ yyxBytes := n.p.y.y.x.Bytes() -+ yyyBytes := n.p.y.y.y.Bytes() -+ yzxBytes := n.p.y.z.x.Bytes() -+ yzyBytes := n.p.y.z.y.Bytes() -+ -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ ret := make([]byte, numBytes*12) -+ copy(ret[1*numBytes-len(xxxBytes):], xxxBytes) -+ copy(ret[2*numBytes-len(xxyBytes):], xxyBytes) -+ copy(ret[3*numBytes-len(xyxBytes):], xyxBytes) -+ copy(ret[4*numBytes-len(xyyBytes):], xyyBytes) -+ copy(ret[5*numBytes-len(xzxBytes):], xzxBytes) -+ copy(ret[6*numBytes-len(xzyBytes):], xzyBytes) -+ copy(ret[7*numBytes-len(yxxBytes):], yxxBytes) -+ copy(ret[8*numBytes-len(yxyBytes):], yxyBytes) -+ copy(ret[9*numBytes-len(yyxBytes):], yyxBytes) -+ copy(ret[10*numBytes-len(yyyBytes):], yyyBytes) -+ copy(ret[11*numBytes-len(yzxBytes):], yzxBytes) -+ copy(ret[12*numBytes-len(yzyBytes):], yzyBytes) -+ -+ return ret -+} -+ -+// Unmarshal sets e to the result of converting the output of Marshal back into -+// a group element and then returns e. -+func (e *GT) Unmarshal(m []byte) (*GT, bool) { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if len(m) != 12*numBytes { -+ return nil, false -+ } -+ -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ -+ e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) -+ e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) -+ e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) -+ e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) -+ e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) -+ e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) -+ e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) -+ e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) -+ e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) -+ e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) -+ e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) -+ e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) -+ -+ return e, true -+} -+ -+// Pair calculates an Optimal Ate pairing. -+func Pair(g1 *G1, g2 *G2) *GT { -+ return >{optimalAte(g2.p, g1.p, new(bnPool))} -+} -+ -+// bnPool implements a tiny cache of *big.Int objects that's used to reduce the -+// number of allocations made during processing. -+type bnPool struct { -+ bns []*big.Int -+ count int -+} -+ -+func (pool *bnPool) Get() *big.Int { -+ if pool == nil { -+ return new(big.Int) -+ } -+ -+ pool.count++ -+ l := len(pool.bns) -+ if l == 0 { -+ return new(big.Int) -+ } -+ -+ bn := pool.bns[l-1] -+ pool.bns = pool.bns[:l-1] -+ return bn -+} -+ -+func (pool *bnPool) Put(bn *big.Int) { -+ if pool == nil { -+ return -+ } -+ pool.bns = append(pool.bns, bn) -+ pool.count-- -+} -+ -+func (pool *bnPool) Count() int { -+ return pool.count -+} -diff --git a/vendor/golang.org/x/crypto/bn256/constants.go b/vendor/golang.org/x/crypto/bn256/constants.go -new file mode 100644 -index 000000000000..1ccefc4982aa ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/constants.go -@@ -0,0 +1,44 @@ -+// Copyright 2012 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 bn256 -+ -+import ( -+ "math/big" -+) -+ -+func bigFromBase10(s string) *big.Int { -+ n, _ := new(big.Int).SetString(s, 10) -+ return n -+} -+ -+// u is the BN parameter that determines the prime: 1868033³. -+var u = bigFromBase10("6518589491078791937") -+ -+// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1. -+var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783") -+ -+// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1. -+var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969") -+ -+// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+3. -+var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")} -+ -+// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+3. -+var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")} -+ -+// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+3. -+var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")} -+ -+// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+3. -+var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752") -+ -+// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+3 (a cubic root of unity, mod p). -+var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030") -+ -+// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+3 (a cubic root of -1, mod p). -+var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753") -+ -+// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+3. -+var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")} -diff --git a/vendor/golang.org/x/crypto/bn256/curve.go b/vendor/golang.org/x/crypto/bn256/curve.go -new file mode 100644 -index 000000000000..63c052bc22f2 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/curve.go -@@ -0,0 +1,287 @@ -+// Copyright 2012 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 bn256 -+ -+import ( -+ "math/big" -+) -+ -+// curvePoint implements the elliptic curve y²=x³+3. Points are kept in -+// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on -+// GF(p). -+type curvePoint struct { -+ x, y, z, t *big.Int -+} -+ -+var curveB = new(big.Int).SetInt64(3) -+ -+// curveGen is the generator of G₁. -+var curveGen = &curvePoint{ -+ new(big.Int).SetInt64(1), -+ new(big.Int).SetInt64(-2), -+ new(big.Int).SetInt64(1), -+ new(big.Int).SetInt64(1), -+} -+ -+func newCurvePoint(pool *bnPool) *curvePoint { -+ return &curvePoint{ -+ pool.Get(), -+ pool.Get(), -+ pool.Get(), -+ pool.Get(), -+ } -+} -+ -+func (c *curvePoint) String() string { -+ c.MakeAffine(new(bnPool)) -+ return "(" + c.x.String() + ", " + c.y.String() + ")" -+} -+ -+func (c *curvePoint) Put(pool *bnPool) { -+ pool.Put(c.x) -+ pool.Put(c.y) -+ pool.Put(c.z) -+ pool.Put(c.t) -+} -+ -+func (c *curvePoint) Set(a *curvePoint) { -+ c.x.Set(a.x) -+ c.y.Set(a.y) -+ c.z.Set(a.z) -+ c.t.Set(a.t) -+} -+ -+// IsOnCurve returns true iff c is on the curve where c must be in affine form. -+func (c *curvePoint) IsOnCurve() bool { -+ yy := new(big.Int).Mul(c.y, c.y) -+ xxx := new(big.Int).Mul(c.x, c.x) -+ xxx.Mul(xxx, c.x) -+ yy.Sub(yy, xxx) -+ yy.Sub(yy, curveB) -+ if yy.Sign() < 0 || yy.Cmp(p) >= 0 { -+ yy.Mod(yy, p) -+ } -+ return yy.Sign() == 0 -+} -+ -+func (c *curvePoint) SetInfinity() { -+ c.z.SetInt64(0) -+} -+ -+func (c *curvePoint) IsInfinity() bool { -+ return c.z.Sign() == 0 -+} -+ -+func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { -+ if a.IsInfinity() { -+ c.Set(b) -+ return -+ } -+ if b.IsInfinity() { -+ c.Set(a) -+ return -+ } -+ -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 -+ -+ // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] -+ // by [u1:s1:z1·z2] and [u2:s2:z1·z2] -+ // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ -+ z1z1 := pool.Get().Mul(a.z, a.z) -+ z1z1.Mod(z1z1, p) -+ z2z2 := pool.Get().Mul(b.z, b.z) -+ z2z2.Mod(z2z2, p) -+ u1 := pool.Get().Mul(a.x, z2z2) -+ u1.Mod(u1, p) -+ u2 := pool.Get().Mul(b.x, z1z1) -+ u2.Mod(u2, p) -+ -+ t := pool.Get().Mul(b.z, z2z2) -+ t.Mod(t, p) -+ s1 := pool.Get().Mul(a.y, t) -+ s1.Mod(s1, p) -+ -+ t.Mul(a.z, z1z1) -+ t.Mod(t, p) -+ s2 := pool.Get().Mul(b.y, t) -+ s2.Mod(s2, p) -+ -+ // Compute x = (2h)²(s²-u1-u2) -+ // where s = (s2-s1)/(u2-u1) is the slope of the line through -+ // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. -+ // This is also: -+ // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) -+ // = r² - j - 2v -+ // with the notations below. -+ h := pool.Get().Sub(u2, u1) -+ xEqual := h.Sign() == 0 -+ -+ t.Add(h, h) -+ // i = 4h² -+ i := pool.Get().Mul(t, t) -+ i.Mod(i, p) -+ // j = 4h³ -+ j := pool.Get().Mul(h, i) -+ j.Mod(j, p) -+ -+ t.Sub(s2, s1) -+ yEqual := t.Sign() == 0 -+ if xEqual && yEqual { -+ c.Double(a, pool) -+ return -+ } -+ r := pool.Get().Add(t, t) -+ -+ v := pool.Get().Mul(u1, i) -+ v.Mod(v, p) -+ -+ // t4 = 4(s2-s1)² -+ t4 := pool.Get().Mul(r, r) -+ t4.Mod(t4, p) -+ t.Add(v, v) -+ t6 := pool.Get().Sub(t4, j) -+ c.x.Sub(t6, t) -+ -+ // Set y = -(2h)³(s1 + s*(x/4h²-u1)) -+ // This is also -+ // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j -+ t.Sub(v, c.x) // t7 -+ t4.Mul(s1, j) // t8 -+ t4.Mod(t4, p) -+ t6.Add(t4, t4) // t9 -+ t4.Mul(r, t) // t10 -+ t4.Mod(t4, p) -+ c.y.Sub(t4, t6) -+ -+ // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 -+ t.Add(a.z, b.z) // t11 -+ t4.Mul(t, t) // t12 -+ t4.Mod(t4, p) -+ t.Sub(t4, z1z1) // t13 -+ t4.Sub(t, z2z2) // t14 -+ c.z.Mul(t4, h) -+ c.z.Mod(c.z, p) -+ -+ pool.Put(z1z1) -+ pool.Put(z2z2) -+ pool.Put(u1) -+ pool.Put(u2) -+ pool.Put(t) -+ pool.Put(s1) -+ pool.Put(s2) -+ pool.Put(h) -+ pool.Put(i) -+ pool.Put(j) -+ pool.Put(r) -+ pool.Put(v) -+ pool.Put(t4) -+ pool.Put(t6) -+} -+ -+func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 -+ A := pool.Get().Mul(a.x, a.x) -+ A.Mod(A, p) -+ B := pool.Get().Mul(a.y, a.y) -+ B.Mod(B, p) -+ C := pool.Get().Mul(B, B) -+ C.Mod(C, p) -+ -+ t := pool.Get().Add(a.x, B) -+ t2 := pool.Get().Mul(t, t) -+ t2.Mod(t2, p) -+ t.Sub(t2, A) -+ t2.Sub(t, C) -+ d := pool.Get().Add(t2, t2) -+ t.Add(A, A) -+ e := pool.Get().Add(t, A) -+ f := pool.Get().Mul(e, e) -+ f.Mod(f, p) -+ -+ t.Add(d, d) -+ c.x.Sub(f, t) -+ -+ t.Add(C, C) -+ t2.Add(t, t) -+ t.Add(t2, t2) -+ c.y.Sub(d, c.x) -+ t2.Mul(e, c.y) -+ t2.Mod(t2, p) -+ c.y.Sub(t2, t) -+ -+ t.Mul(a.y, a.z) -+ t.Mod(t, p) -+ c.z.Add(t, t) -+ -+ pool.Put(A) -+ pool.Put(B) -+ pool.Put(C) -+ pool.Put(t) -+ pool.Put(t2) -+ pool.Put(d) -+ pool.Put(e) -+ pool.Put(f) -+} -+ -+func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { -+ sum := newCurvePoint(pool) -+ sum.SetInfinity() -+ t := newCurvePoint(pool) -+ -+ for i := scalar.BitLen(); i >= 0; i-- { -+ t.Double(sum, pool) -+ if scalar.Bit(i) != 0 { -+ sum.Add(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ sum.Put(pool) -+ t.Put(pool) -+ return c -+} -+ -+// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets -+// c to 0 : 1 : 0. -+func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { -+ if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { -+ return c -+ } -+ if c.IsInfinity() { -+ c.x.SetInt64(0) -+ c.y.SetInt64(1) -+ c.z.SetInt64(0) -+ c.t.SetInt64(0) -+ return c -+ } -+ -+ zInv := pool.Get().ModInverse(c.z, p) -+ t := pool.Get().Mul(c.y, zInv) -+ t.Mod(t, p) -+ zInv2 := pool.Get().Mul(zInv, zInv) -+ zInv2.Mod(zInv2, p) -+ c.y.Mul(t, zInv2) -+ c.y.Mod(c.y, p) -+ t.Mul(c.x, zInv2) -+ t.Mod(t, p) -+ c.x.Set(t) -+ c.z.SetInt64(1) -+ c.t.SetInt64(1) -+ -+ pool.Put(zInv) -+ pool.Put(t) -+ pool.Put(zInv2) -+ -+ return c -+} -+ -+func (c *curvePoint) Negative(a *curvePoint) { -+ c.x.Set(a.x) -+ c.y.Neg(a.y) -+ c.z.Set(a.z) -+ c.t.SetInt64(0) -+} -diff --git a/vendor/golang.org/x/crypto/bn256/gfp12.go b/vendor/golang.org/x/crypto/bn256/gfp12.go -new file mode 100644 -index 000000000000..2b0151ebcc49 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/gfp12.go -@@ -0,0 +1,200 @@ -+// Copyright 2012 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 bn256 -+ -+// For details of the algorithms used, see "Multiplication and Squaring on -+// Pairing-Friendly Fields, Devegili et al. -+// http://eprint.iacr.org/2006/471.pdf. -+ -+import ( -+ "math/big" -+) -+ -+// gfP12 implements the field of size p¹² as a quadratic extension of gfP6 -+// where ω²=τ. -+type gfP12 struct { -+ x, y *gfP6 // value is xω + y -+} -+ -+func newGFp12(pool *bnPool) *gfP12 { -+ return &gfP12{newGFp6(pool), newGFp6(pool)} -+} -+ -+func (e *gfP12) String() string { -+ return "(" + e.x.String() + "," + e.y.String() + ")" -+} -+ -+func (e *gfP12) Put(pool *bnPool) { -+ e.x.Put(pool) -+ e.y.Put(pool) -+} -+ -+func (e *gfP12) Set(a *gfP12) *gfP12 { -+ e.x.Set(a.x) -+ e.y.Set(a.y) -+ return e -+} -+ -+func (e *gfP12) SetZero() *gfP12 { -+ e.x.SetZero() -+ e.y.SetZero() -+ return e -+} -+ -+func (e *gfP12) SetOne() *gfP12 { -+ e.x.SetZero() -+ e.y.SetOne() -+ return e -+} -+ -+func (e *gfP12) Minimal() { -+ e.x.Minimal() -+ e.y.Minimal() -+} -+ -+func (e *gfP12) IsZero() bool { -+ e.Minimal() -+ return e.x.IsZero() && e.y.IsZero() -+} -+ -+func (e *gfP12) IsOne() bool { -+ e.Minimal() -+ return e.x.IsZero() && e.y.IsOne() -+} -+ -+func (e *gfP12) Conjugate(a *gfP12) *gfP12 { -+ e.x.Negative(a.x) -+ e.y.Set(a.y) -+ return a -+} -+ -+func (e *gfP12) Negative(a *gfP12) *gfP12 { -+ e.x.Negative(a.x) -+ e.y.Negative(a.y) -+ return e -+} -+ -+// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p -+func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { -+ e.x.Frobenius(a.x, pool) -+ e.y.Frobenius(a.y, pool) -+ e.x.MulScalar(e.x, xiToPMinus1Over6, pool) -+ return e -+} -+ -+// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² -+func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { -+ e.x.FrobeniusP2(a.x) -+ e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) -+ e.y.FrobeniusP2(a.y) -+ return e -+} -+ -+func (e *gfP12) Add(a, b *gfP12) *gfP12 { -+ e.x.Add(a.x, b.x) -+ e.y.Add(a.y, b.y) -+ return e -+} -+ -+func (e *gfP12) Sub(a, b *gfP12) *gfP12 { -+ e.x.Sub(a.x, b.x) -+ e.y.Sub(a.y, b.y) -+ return e -+} -+ -+func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { -+ tx := newGFp6(pool) -+ tx.Mul(a.x, b.y, pool) -+ t := newGFp6(pool) -+ t.Mul(b.x, a.y, pool) -+ tx.Add(tx, t) -+ -+ ty := newGFp6(pool) -+ ty.Mul(a.y, b.y, pool) -+ t.Mul(a.x, b.x, pool) -+ t.MulTau(t, pool) -+ e.y.Add(ty, t) -+ e.x.Set(tx) -+ -+ tx.Put(pool) -+ ty.Put(pool) -+ t.Put(pool) -+ return e -+} -+ -+func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { -+ e.x.Mul(a.x, b, pool) -+ e.y.Mul(a.y, b, pool) -+ return e -+} -+ -+func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { -+ sum := newGFp12(pool) -+ sum.SetOne() -+ t := newGFp12(pool) -+ -+ for i := power.BitLen() - 1; i >= 0; i-- { -+ t.Square(sum, pool) -+ if power.Bit(i) != 0 { -+ sum.Mul(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ -+ sum.Put(pool) -+ t.Put(pool) -+ -+ return c -+} -+ -+func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { -+ // Complex squaring algorithm -+ v0 := newGFp6(pool) -+ v0.Mul(a.x, a.y, pool) -+ -+ t := newGFp6(pool) -+ t.MulTau(a.x, pool) -+ t.Add(a.y, t) -+ ty := newGFp6(pool) -+ ty.Add(a.x, a.y) -+ ty.Mul(ty, t, pool) -+ ty.Sub(ty, v0) -+ t.MulTau(v0, pool) -+ ty.Sub(ty, t) -+ -+ e.y.Set(ty) -+ e.x.Double(v0) -+ -+ v0.Put(pool) -+ t.Put(pool) -+ ty.Put(pool) -+ -+ return e -+} -+ -+func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { -+ // See "Implementing cryptographic pairings", M. Scott, section 3.2. -+ // ftp://136.206.11.249/pub/crypto/pairings.pdf -+ t1 := newGFp6(pool) -+ t2 := newGFp6(pool) -+ -+ t1.Square(a.x, pool) -+ t2.Square(a.y, pool) -+ t1.MulTau(t1, pool) -+ t1.Sub(t2, t1) -+ t2.Invert(t1, pool) -+ -+ e.x.Negative(a.x) -+ e.y.Set(a.y) -+ e.MulScalar(e, t2, pool) -+ -+ t1.Put(pool) -+ t2.Put(pool) -+ -+ return e -+} -diff --git a/vendor/golang.org/x/crypto/bn256/gfp2.go b/vendor/golang.org/x/crypto/bn256/gfp2.go -new file mode 100644 -index 000000000000..97f3f1f3fa1a ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/gfp2.go -@@ -0,0 +1,219 @@ -+// Copyright 2012 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 bn256 -+ -+// For details of the algorithms used, see "Multiplication and Squaring on -+// Pairing-Friendly Fields, Devegili et al. -+// http://eprint.iacr.org/2006/471.pdf. -+ -+import ( -+ "math/big" -+) -+ -+// gfP2 implements a field of size p² as a quadratic extension of the base -+// field where i²=-1. -+type gfP2 struct { -+ x, y *big.Int // value is xi+y. -+} -+ -+func newGFp2(pool *bnPool) *gfP2 { -+ return &gfP2{pool.Get(), pool.Get()} -+} -+ -+func (e *gfP2) String() string { -+ x := new(big.Int).Mod(e.x, p) -+ y := new(big.Int).Mod(e.y, p) -+ return "(" + x.String() + "," + y.String() + ")" -+} -+ -+func (e *gfP2) Put(pool *bnPool) { -+ pool.Put(e.x) -+ pool.Put(e.y) -+} -+ -+func (e *gfP2) Set(a *gfP2) *gfP2 { -+ e.x.Set(a.x) -+ e.y.Set(a.y) -+ return e -+} -+ -+func (e *gfP2) SetZero() *gfP2 { -+ e.x.SetInt64(0) -+ e.y.SetInt64(0) -+ return e -+} -+ -+func (e *gfP2) SetOne() *gfP2 { -+ e.x.SetInt64(0) -+ e.y.SetInt64(1) -+ return e -+} -+ -+func (e *gfP2) Minimal() { -+ if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 { -+ e.x.Mod(e.x, p) -+ } -+ if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 { -+ e.y.Mod(e.y, p) -+ } -+} -+ -+func (e *gfP2) IsZero() bool { -+ return e.x.Sign() == 0 && e.y.Sign() == 0 -+} -+ -+func (e *gfP2) IsOne() bool { -+ if e.x.Sign() != 0 { -+ return false -+ } -+ words := e.y.Bits() -+ return len(words) == 1 && words[0] == 1 -+} -+ -+func (e *gfP2) Conjugate(a *gfP2) *gfP2 { -+ e.y.Set(a.y) -+ e.x.Neg(a.x) -+ return e -+} -+ -+func (e *gfP2) Negative(a *gfP2) *gfP2 { -+ e.x.Neg(a.x) -+ e.y.Neg(a.y) -+ return e -+} -+ -+func (e *gfP2) Add(a, b *gfP2) *gfP2 { -+ e.x.Add(a.x, b.x) -+ e.y.Add(a.y, b.y) -+ return e -+} -+ -+func (e *gfP2) Sub(a, b *gfP2) *gfP2 { -+ e.x.Sub(a.x, b.x) -+ e.y.Sub(a.y, b.y) -+ return e -+} -+ -+func (e *gfP2) Double(a *gfP2) *gfP2 { -+ e.x.Lsh(a.x, 1) -+ e.y.Lsh(a.y, 1) -+ return e -+} -+ -+func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { -+ sum := newGFp2(pool) -+ sum.SetOne() -+ t := newGFp2(pool) -+ -+ for i := power.BitLen() - 1; i >= 0; i-- { -+ t.Square(sum, pool) -+ if power.Bit(i) != 0 { -+ sum.Mul(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ -+ sum.Put(pool) -+ t.Put(pool) -+ -+ return c -+} -+ -+// See "Multiplication and Squaring in Pairing-Friendly Fields", -+// http://eprint.iacr.org/2006/471.pdf -+func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { -+ tx := pool.Get().Mul(a.x, b.y) -+ t := pool.Get().Mul(b.x, a.y) -+ tx.Add(tx, t) -+ tx.Mod(tx, p) -+ -+ ty := pool.Get().Mul(a.y, b.y) -+ t.Mul(a.x, b.x) -+ ty.Sub(ty, t) -+ e.y.Mod(ty, p) -+ e.x.Set(tx) -+ -+ pool.Put(tx) -+ pool.Put(ty) -+ pool.Put(t) -+ -+ return e -+} -+ -+func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { -+ e.x.Mul(a.x, b) -+ e.y.Mul(a.y, b) -+ return e -+} -+ -+// MulXi sets e=ξa where ξ=i+3 and then returns e. -+func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { -+ // (xi+y)(i+3) = (3x+y)i+(3y-x) -+ tx := pool.Get().Lsh(a.x, 1) -+ tx.Add(tx, a.x) -+ tx.Add(tx, a.y) -+ -+ ty := pool.Get().Lsh(a.y, 1) -+ ty.Add(ty, a.y) -+ ty.Sub(ty, a.x) -+ -+ e.x.Set(tx) -+ e.y.Set(ty) -+ -+ pool.Put(tx) -+ pool.Put(ty) -+ -+ return e -+} -+ -+func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { -+ // Complex squaring algorithm: -+ // (xi+b)² = (x+y)(y-x) + 2*i*x*y -+ t1 := pool.Get().Sub(a.y, a.x) -+ t2 := pool.Get().Add(a.x, a.y) -+ ty := pool.Get().Mul(t1, t2) -+ ty.Mod(ty, p) -+ -+ t1.Mul(a.x, a.y) -+ t1.Lsh(t1, 1) -+ -+ e.x.Mod(t1, p) -+ e.y.Set(ty) -+ -+ pool.Put(t1) -+ pool.Put(t2) -+ pool.Put(ty) -+ -+ return e -+} -+ -+func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { -+ // See "Implementing cryptographic pairings", M. Scott, section 3.2. -+ // ftp://136.206.11.249/pub/crypto/pairings.pdf -+ t := pool.Get() -+ t.Mul(a.y, a.y) -+ t2 := pool.Get() -+ t2.Mul(a.x, a.x) -+ t.Add(t, t2) -+ -+ inv := pool.Get() -+ inv.ModInverse(t, p) -+ -+ e.x.Neg(a.x) -+ e.x.Mul(e.x, inv) -+ e.x.Mod(e.x, p) -+ -+ e.y.Mul(a.y, inv) -+ e.y.Mod(e.y, p) -+ -+ pool.Put(t) -+ pool.Put(t2) -+ pool.Put(inv) -+ -+ return e -+} -diff --git a/vendor/golang.org/x/crypto/bn256/gfp6.go b/vendor/golang.org/x/crypto/bn256/gfp6.go -new file mode 100644 -index 000000000000..f98ae782cc15 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/gfp6.go -@@ -0,0 +1,296 @@ -+// Copyright 2012 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 bn256 -+ -+// For details of the algorithms used, see "Multiplication and Squaring on -+// Pairing-Friendly Fields, Devegili et al. -+// http://eprint.iacr.org/2006/471.pdf. -+ -+import ( -+ "math/big" -+) -+ -+// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ -+// and ξ=i+3. -+type gfP6 struct { -+ x, y, z *gfP2 // value is xτ² + yτ + z -+} -+ -+func newGFp6(pool *bnPool) *gfP6 { -+ return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} -+} -+ -+func (e *gfP6) String() string { -+ return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" -+} -+ -+func (e *gfP6) Put(pool *bnPool) { -+ e.x.Put(pool) -+ e.y.Put(pool) -+ e.z.Put(pool) -+} -+ -+func (e *gfP6) Set(a *gfP6) *gfP6 { -+ e.x.Set(a.x) -+ e.y.Set(a.y) -+ e.z.Set(a.z) -+ return e -+} -+ -+func (e *gfP6) SetZero() *gfP6 { -+ e.x.SetZero() -+ e.y.SetZero() -+ e.z.SetZero() -+ return e -+} -+ -+func (e *gfP6) SetOne() *gfP6 { -+ e.x.SetZero() -+ e.y.SetZero() -+ e.z.SetOne() -+ return e -+} -+ -+func (e *gfP6) Minimal() { -+ e.x.Minimal() -+ e.y.Minimal() -+ e.z.Minimal() -+} -+ -+func (e *gfP6) IsZero() bool { -+ return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() -+} -+ -+func (e *gfP6) IsOne() bool { -+ return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() -+} -+ -+func (e *gfP6) Negative(a *gfP6) *gfP6 { -+ e.x.Negative(a.x) -+ e.y.Negative(a.y) -+ e.z.Negative(a.z) -+ return e -+} -+ -+func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { -+ e.x.Conjugate(a.x) -+ e.y.Conjugate(a.y) -+ e.z.Conjugate(a.z) -+ -+ e.x.Mul(e.x, xiTo2PMinus2Over3, pool) -+ e.y.Mul(e.y, xiToPMinus1Over3, pool) -+ return e -+} -+ -+// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z -+func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { -+ // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) -+ e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3) -+ // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3) -+ e.y.MulScalar(a.y, xiToPSquaredMinus1Over3) -+ e.z.Set(a.z) -+ return e -+} -+ -+func (e *gfP6) Add(a, b *gfP6) *gfP6 { -+ e.x.Add(a.x, b.x) -+ e.y.Add(a.y, b.y) -+ e.z.Add(a.z, b.z) -+ return e -+} -+ -+func (e *gfP6) Sub(a, b *gfP6) *gfP6 { -+ e.x.Sub(a.x, b.x) -+ e.y.Sub(a.y, b.y) -+ e.z.Sub(a.z, b.z) -+ return e -+} -+ -+func (e *gfP6) Double(a *gfP6) *gfP6 { -+ e.x.Double(a.x) -+ e.y.Double(a.y) -+ e.z.Double(a.z) -+ return e -+} -+ -+func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 { -+ // "Multiplication and Squaring on Pairing-Friendly Fields" -+ // Section 4, Karatsuba method. -+ // http://eprint.iacr.org/2006/471.pdf -+ -+ v0 := newGFp2(pool) -+ v0.Mul(a.z, b.z, pool) -+ v1 := newGFp2(pool) -+ v1.Mul(a.y, b.y, pool) -+ v2 := newGFp2(pool) -+ v2.Mul(a.x, b.x, pool) -+ -+ t0 := newGFp2(pool) -+ t0.Add(a.x, a.y) -+ t1 := newGFp2(pool) -+ t1.Add(b.x, b.y) -+ tz := newGFp2(pool) -+ tz.Mul(t0, t1, pool) -+ -+ tz.Sub(tz, v1) -+ tz.Sub(tz, v2) -+ tz.MulXi(tz, pool) -+ tz.Add(tz, v0) -+ -+ t0.Add(a.y, a.z) -+ t1.Add(b.y, b.z) -+ ty := newGFp2(pool) -+ ty.Mul(t0, t1, pool) -+ ty.Sub(ty, v0) -+ ty.Sub(ty, v1) -+ t0.MulXi(v2, pool) -+ ty.Add(ty, t0) -+ -+ t0.Add(a.x, a.z) -+ t1.Add(b.x, b.z) -+ tx := newGFp2(pool) -+ tx.Mul(t0, t1, pool) -+ tx.Sub(tx, v0) -+ tx.Add(tx, v1) -+ tx.Sub(tx, v2) -+ -+ e.x.Set(tx) -+ e.y.Set(ty) -+ e.z.Set(tz) -+ -+ t0.Put(pool) -+ t1.Put(pool) -+ tx.Put(pool) -+ ty.Put(pool) -+ tz.Put(pool) -+ v0.Put(pool) -+ v1.Put(pool) -+ v2.Put(pool) -+ return e -+} -+ -+func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 { -+ e.x.Mul(a.x, b, pool) -+ e.y.Mul(a.y, b, pool) -+ e.z.Mul(a.z, b, pool) -+ return e -+} -+ -+func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 { -+ e.x.MulScalar(a.x, b) -+ e.y.MulScalar(a.y, b) -+ e.z.MulScalar(a.z, b) -+ return e -+} -+ -+// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ -+func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { -+ tz := newGFp2(pool) -+ tz.MulXi(a.x, pool) -+ ty := newGFp2(pool) -+ ty.Set(a.y) -+ e.y.Set(a.z) -+ e.x.Set(ty) -+ e.z.Set(tz) -+ tz.Put(pool) -+ ty.Put(pool) -+} -+ -+func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 { -+ v0 := newGFp2(pool).Square(a.z, pool) -+ v1 := newGFp2(pool).Square(a.y, pool) -+ v2 := newGFp2(pool).Square(a.x, pool) -+ -+ c0 := newGFp2(pool).Add(a.x, a.y) -+ c0.Square(c0, pool) -+ c0.Sub(c0, v1) -+ c0.Sub(c0, v2) -+ c0.MulXi(c0, pool) -+ c0.Add(c0, v0) -+ -+ c1 := newGFp2(pool).Add(a.y, a.z) -+ c1.Square(c1, pool) -+ c1.Sub(c1, v0) -+ c1.Sub(c1, v1) -+ xiV2 := newGFp2(pool).MulXi(v2, pool) -+ c1.Add(c1, xiV2) -+ -+ c2 := newGFp2(pool).Add(a.x, a.z) -+ c2.Square(c2, pool) -+ c2.Sub(c2, v0) -+ c2.Add(c2, v1) -+ c2.Sub(c2, v2) -+ -+ e.x.Set(c2) -+ e.y.Set(c1) -+ e.z.Set(c0) -+ -+ v0.Put(pool) -+ v1.Put(pool) -+ v2.Put(pool) -+ c0.Put(pool) -+ c1.Put(pool) -+ c2.Put(pool) -+ xiV2.Put(pool) -+ -+ return e -+} -+ -+func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { -+ // See "Implementing cryptographic pairings", M. Scott, section 3.2. -+ // ftp://136.206.11.249/pub/crypto/pairings.pdf -+ -+ // Here we can give a short explanation of how it works: let j be a cubic root of -+ // unity in GF(p²) so that 1+j+j²=0. -+ // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z) -+ // = (xτ² + yτ + z)(Cτ²+Bτ+A) -+ // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). -+ // -+ // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) -+ // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) -+ // -+ // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) -+ t1 := newGFp2(pool) -+ -+ A := newGFp2(pool) -+ A.Square(a.z, pool) -+ t1.Mul(a.x, a.y, pool) -+ t1.MulXi(t1, pool) -+ A.Sub(A, t1) -+ -+ B := newGFp2(pool) -+ B.Square(a.x, pool) -+ B.MulXi(B, pool) -+ t1.Mul(a.y, a.z, pool) -+ B.Sub(B, t1) -+ -+ C := newGFp2(pool) -+ C.Square(a.y, pool) -+ t1.Mul(a.x, a.z, pool) -+ C.Sub(C, t1) -+ -+ F := newGFp2(pool) -+ F.Mul(C, a.y, pool) -+ F.MulXi(F, pool) -+ t1.Mul(A, a.z, pool) -+ F.Add(F, t1) -+ t1.Mul(B, a.x, pool) -+ t1.MulXi(t1, pool) -+ F.Add(F, t1) -+ -+ F.Invert(F, pool) -+ -+ e.x.Mul(C, F, pool) -+ e.y.Mul(B, F, pool) -+ e.z.Mul(A, F, pool) -+ -+ t1.Put(pool) -+ A.Put(pool) -+ B.Put(pool) -+ C.Put(pool) -+ F.Put(pool) -+ -+ return e -+} -diff --git a/vendor/golang.org/x/crypto/bn256/optate.go b/vendor/golang.org/x/crypto/bn256/optate.go -new file mode 100644 -index 000000000000..7ae0746eb10b ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/optate.go -@@ -0,0 +1,395 @@ -+// Copyright 2012 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 bn256 -+ -+func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { -+ // See the mixed addition algorithm from "Faster Computation of the -+ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf -+ -+ B := newGFp2(pool).Mul(p.x, r.t, pool) -+ -+ D := newGFp2(pool).Add(p.y, r.z) -+ D.Square(D, pool) -+ D.Sub(D, r2) -+ D.Sub(D, r.t) -+ D.Mul(D, r.t, pool) -+ -+ H := newGFp2(pool).Sub(B, r.x) -+ I := newGFp2(pool).Square(H, pool) -+ -+ E := newGFp2(pool).Add(I, I) -+ E.Add(E, E) -+ -+ J := newGFp2(pool).Mul(H, E, pool) -+ -+ L1 := newGFp2(pool).Sub(D, r.y) -+ L1.Sub(L1, r.y) -+ -+ V := newGFp2(pool).Mul(r.x, E, pool) -+ -+ rOut = newTwistPoint(pool) -+ rOut.x.Square(L1, pool) -+ rOut.x.Sub(rOut.x, J) -+ rOut.x.Sub(rOut.x, V) -+ rOut.x.Sub(rOut.x, V) -+ -+ rOut.z.Add(r.z, H) -+ rOut.z.Square(rOut.z, pool) -+ rOut.z.Sub(rOut.z, r.t) -+ rOut.z.Sub(rOut.z, I) -+ -+ t := newGFp2(pool).Sub(V, rOut.x) -+ t.Mul(t, L1, pool) -+ t2 := newGFp2(pool).Mul(r.y, J, pool) -+ t2.Add(t2, t2) -+ rOut.y.Sub(t, t2) -+ -+ rOut.t.Square(rOut.z, pool) -+ -+ t.Add(p.y, rOut.z) -+ t.Square(t, pool) -+ t.Sub(t, r2) -+ t.Sub(t, rOut.t) -+ -+ t2.Mul(L1, p.x, pool) -+ t2.Add(t2, t2) -+ a = newGFp2(pool) -+ a.Sub(t2, t) -+ -+ c = newGFp2(pool) -+ c.MulScalar(rOut.z, q.y) -+ c.Add(c, c) -+ -+ b = newGFp2(pool) -+ b.SetZero() -+ b.Sub(b, L1) -+ b.MulScalar(b, q.x) -+ b.Add(b, b) -+ -+ B.Put(pool) -+ D.Put(pool) -+ H.Put(pool) -+ I.Put(pool) -+ E.Put(pool) -+ J.Put(pool) -+ L1.Put(pool) -+ V.Put(pool) -+ t.Put(pool) -+ t2.Put(pool) -+ -+ return -+} -+ -+func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { -+ // See the doubling algorithm for a=0 from "Faster Computation of the -+ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf -+ -+ A := newGFp2(pool).Square(r.x, pool) -+ B := newGFp2(pool).Square(r.y, pool) -+ C := newGFp2(pool).Square(B, pool) -+ -+ D := newGFp2(pool).Add(r.x, B) -+ D.Square(D, pool) -+ D.Sub(D, A) -+ D.Sub(D, C) -+ D.Add(D, D) -+ -+ E := newGFp2(pool).Add(A, A) -+ E.Add(E, A) -+ -+ G := newGFp2(pool).Square(E, pool) -+ -+ rOut = newTwistPoint(pool) -+ rOut.x.Sub(G, D) -+ rOut.x.Sub(rOut.x, D) -+ -+ rOut.z.Add(r.y, r.z) -+ rOut.z.Square(rOut.z, pool) -+ rOut.z.Sub(rOut.z, B) -+ rOut.z.Sub(rOut.z, r.t) -+ -+ rOut.y.Sub(D, rOut.x) -+ rOut.y.Mul(rOut.y, E, pool) -+ t := newGFp2(pool).Add(C, C) -+ t.Add(t, t) -+ t.Add(t, t) -+ rOut.y.Sub(rOut.y, t) -+ -+ rOut.t.Square(rOut.z, pool) -+ -+ t.Mul(E, r.t, pool) -+ t.Add(t, t) -+ b = newGFp2(pool) -+ b.SetZero() -+ b.Sub(b, t) -+ b.MulScalar(b, q.x) -+ -+ a = newGFp2(pool) -+ a.Add(r.x, E) -+ a.Square(a, pool) -+ a.Sub(a, A) -+ a.Sub(a, G) -+ t.Add(B, B) -+ t.Add(t, t) -+ a.Sub(a, t) -+ -+ c = newGFp2(pool) -+ c.Mul(rOut.z, r.t, pool) -+ c.Add(c, c) -+ c.MulScalar(c, q.y) -+ -+ A.Put(pool) -+ B.Put(pool) -+ C.Put(pool) -+ D.Put(pool) -+ E.Put(pool) -+ G.Put(pool) -+ t.Put(pool) -+ -+ return -+} -+ -+func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) { -+ a2 := newGFp6(pool) -+ a2.x.SetZero() -+ a2.y.Set(a) -+ a2.z.Set(b) -+ a2.Mul(a2, ret.x, pool) -+ t3 := newGFp6(pool).MulScalar(ret.y, c, pool) -+ -+ t := newGFp2(pool) -+ t.Add(b, c) -+ t2 := newGFp6(pool) -+ t2.x.SetZero() -+ t2.y.Set(a) -+ t2.z.Set(t) -+ ret.x.Add(ret.x, ret.y) -+ -+ ret.y.Set(t3) -+ -+ ret.x.Mul(ret.x, t2, pool) -+ ret.x.Sub(ret.x, a2) -+ ret.x.Sub(ret.x, ret.y) -+ a2.MulTau(a2, pool) -+ ret.y.Add(ret.y, a2) -+ -+ a2.Put(pool) -+ t3.Put(pool) -+ t2.Put(pool) -+ t.Put(pool) -+} -+ -+// sixuPlus2NAF is 6u+2 in non-adjacent form. -+var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1} -+ -+// miller implements the Miller loop for calculating the Optimal Ate pairing. -+// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf -+func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 { -+ ret := newGFp12(pool) -+ ret.SetOne() -+ -+ aAffine := newTwistPoint(pool) -+ aAffine.Set(q) -+ aAffine.MakeAffine(pool) -+ -+ bAffine := newCurvePoint(pool) -+ bAffine.Set(p) -+ bAffine.MakeAffine(pool) -+ -+ minusA := newTwistPoint(pool) -+ minusA.Negative(aAffine, pool) -+ -+ r := newTwistPoint(pool) -+ r.Set(aAffine) -+ -+ r2 := newGFp2(pool) -+ r2.Square(aAffine.y, pool) -+ -+ for i := len(sixuPlus2NAF) - 1; i > 0; i-- { -+ a, b, c, newR := lineFunctionDouble(r, bAffine, pool) -+ if i != len(sixuPlus2NAF)-1 { -+ ret.Square(ret, pool) -+ } -+ -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ -+ switch sixuPlus2NAF[i-1] { -+ case 1: -+ a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool) -+ case -1: -+ a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool) -+ default: -+ continue -+ } -+ -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ } -+ -+ // In order to calculate Q1 we have to convert q from the sextic twist -+ // to the full GF(p^12) group, apply the Frobenius there, and convert -+ // back. -+ // -+ // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just -+ // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) -+ // where x̄ is the conjugate of x. If we are going to apply the inverse -+ // isomorphism we need a value with a single coefficient of ω² so we -+ // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of -+ // p, 2p-2 is a multiple of six. Therefore we can rewrite as -+ // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the -+ // ω². -+ // -+ // A similar argument can be made for the y value. -+ -+ q1 := newTwistPoint(pool) -+ q1.x.Conjugate(aAffine.x) -+ q1.x.Mul(q1.x, xiToPMinus1Over3, pool) -+ q1.y.Conjugate(aAffine.y) -+ q1.y.Mul(q1.y, xiToPMinus1Over2, pool) -+ q1.z.SetOne() -+ q1.t.SetOne() -+ -+ // For Q2 we are applying the p² Frobenius. The two conjugations cancel -+ // out and we are left only with the factors from the isomorphism. In -+ // the case of x, we end up with a pure number which is why -+ // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We -+ // ignore this to end up with -Q2. -+ -+ minusQ2 := newTwistPoint(pool) -+ minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3) -+ minusQ2.y.Set(aAffine.y) -+ minusQ2.z.SetOne() -+ minusQ2.t.SetOne() -+ -+ r2.Square(q1.y, pool) -+ a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool) -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ -+ r2.Square(minusQ2.y, pool) -+ a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool) -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ -+ aAffine.Put(pool) -+ bAffine.Put(pool) -+ minusA.Put(pool) -+ r.Put(pool) -+ r2.Put(pool) -+ -+ return ret -+} -+ -+// finalExponentiation computes the (p¹²-1)/Order-th power of an element of -+// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from -+// http://cryptojedi.org/papers/dclxvi-20100714.pdf) -+func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 { -+ t1 := newGFp12(pool) -+ -+ // This is the p^6-Frobenius -+ t1.x.Negative(in.x) -+ t1.y.Set(in.y) -+ -+ inv := newGFp12(pool) -+ inv.Invert(in, pool) -+ t1.Mul(t1, inv, pool) -+ -+ t2 := newGFp12(pool).FrobeniusP2(t1, pool) -+ t1.Mul(t1, t2, pool) -+ -+ fp := newGFp12(pool).Frobenius(t1, pool) -+ fp2 := newGFp12(pool).FrobeniusP2(t1, pool) -+ fp3 := newGFp12(pool).Frobenius(fp2, pool) -+ -+ fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool) -+ fu.Exp(t1, u, pool) -+ fu2.Exp(fu, u, pool) -+ fu3.Exp(fu2, u, pool) -+ -+ y3 := newGFp12(pool).Frobenius(fu, pool) -+ fu2p := newGFp12(pool).Frobenius(fu2, pool) -+ fu3p := newGFp12(pool).Frobenius(fu3, pool) -+ y2 := newGFp12(pool).FrobeniusP2(fu2, pool) -+ -+ y0 := newGFp12(pool) -+ y0.Mul(fp, fp2, pool) -+ y0.Mul(y0, fp3, pool) -+ -+ y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool) -+ y1.Conjugate(t1) -+ y5.Conjugate(fu2) -+ y3.Conjugate(y3) -+ y4.Mul(fu, fu2p, pool) -+ y4.Conjugate(y4) -+ -+ y6 := newGFp12(pool) -+ y6.Mul(fu3, fu3p, pool) -+ y6.Conjugate(y6) -+ -+ t0 := newGFp12(pool) -+ t0.Square(y6, pool) -+ t0.Mul(t0, y4, pool) -+ t0.Mul(t0, y5, pool) -+ t1.Mul(y3, y5, pool) -+ t1.Mul(t1, t0, pool) -+ t0.Mul(t0, y2, pool) -+ t1.Square(t1, pool) -+ t1.Mul(t1, t0, pool) -+ t1.Square(t1, pool) -+ t0.Mul(t1, y1, pool) -+ t1.Mul(t1, y0, pool) -+ t0.Square(t0, pool) -+ t0.Mul(t0, t1, pool) -+ -+ inv.Put(pool) -+ t1.Put(pool) -+ t2.Put(pool) -+ fp.Put(pool) -+ fp2.Put(pool) -+ fp3.Put(pool) -+ fu.Put(pool) -+ fu2.Put(pool) -+ fu3.Put(pool) -+ fu2p.Put(pool) -+ fu3p.Put(pool) -+ y0.Put(pool) -+ y1.Put(pool) -+ y2.Put(pool) -+ y3.Put(pool) -+ y4.Put(pool) -+ y5.Put(pool) -+ y6.Put(pool) -+ -+ return t0 -+} -+ -+func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 { -+ e := miller(a, b, pool) -+ ret := finalExponentiation(e, pool) -+ e.Put(pool) -+ -+ if a.IsInfinity() || b.IsInfinity() { -+ ret.SetOne() -+ } -+ -+ return ret -+} -diff --git a/vendor/golang.org/x/crypto/bn256/twist.go b/vendor/golang.org/x/crypto/bn256/twist.go -new file mode 100644 -index 000000000000..056d80f18f08 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/bn256/twist.go -@@ -0,0 +1,258 @@ -+// Copyright 2012 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 bn256 -+ -+import ( -+ "math/big" -+) -+ -+// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are -+// kept in Jacobian form and t=z² when valid. The group G₂ is the set of -+// n-torsion points of this curve over GF(p²) (where n = Order) -+type twistPoint struct { -+ x, y, z, t *gfP2 -+} -+ -+var twistB = &gfP2{ -+ bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"), -+ bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"), -+} -+ -+// twistGen is the generator of group G₂. -+var twistGen = &twistPoint{ -+ &gfP2{ -+ bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"), -+ bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"), -+ }, -+ &gfP2{ -+ bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"), -+ bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"), -+ }, -+ &gfP2{ -+ bigFromBase10("0"), -+ bigFromBase10("1"), -+ }, -+ &gfP2{ -+ bigFromBase10("0"), -+ bigFromBase10("1"), -+ }, -+} -+ -+func newTwistPoint(pool *bnPool) *twistPoint { -+ return &twistPoint{ -+ newGFp2(pool), -+ newGFp2(pool), -+ newGFp2(pool), -+ newGFp2(pool), -+ } -+} -+ -+func (c *twistPoint) String() string { -+ return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" -+} -+ -+func (c *twistPoint) Put(pool *bnPool) { -+ c.x.Put(pool) -+ c.y.Put(pool) -+ c.z.Put(pool) -+ c.t.Put(pool) -+} -+ -+func (c *twistPoint) Set(a *twistPoint) { -+ c.x.Set(a.x) -+ c.y.Set(a.y) -+ c.z.Set(a.z) -+ c.t.Set(a.t) -+} -+ -+// IsOnCurve returns true iff c is on the curve where c must be in affine form. -+func (c *twistPoint) IsOnCurve() bool { -+ pool := new(bnPool) -+ yy := newGFp2(pool).Square(c.y, pool) -+ xxx := newGFp2(pool).Square(c.x, pool) -+ xxx.Mul(xxx, c.x, pool) -+ yy.Sub(yy, xxx) -+ yy.Sub(yy, twistB) -+ yy.Minimal() -+ return yy.x.Sign() == 0 && yy.y.Sign() == 0 -+} -+ -+func (c *twistPoint) SetInfinity() { -+ c.z.SetZero() -+} -+ -+func (c *twistPoint) IsInfinity() bool { -+ return c.z.IsZero() -+} -+ -+func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { -+ // For additional comments, see the same function in curve.go. -+ -+ if a.IsInfinity() { -+ c.Set(b) -+ return -+ } -+ if b.IsInfinity() { -+ c.Set(a) -+ return -+ } -+ -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 -+ z1z1 := newGFp2(pool).Square(a.z, pool) -+ z2z2 := newGFp2(pool).Square(b.z, pool) -+ u1 := newGFp2(pool).Mul(a.x, z2z2, pool) -+ u2 := newGFp2(pool).Mul(b.x, z1z1, pool) -+ -+ t := newGFp2(pool).Mul(b.z, z2z2, pool) -+ s1 := newGFp2(pool).Mul(a.y, t, pool) -+ -+ t.Mul(a.z, z1z1, pool) -+ s2 := newGFp2(pool).Mul(b.y, t, pool) -+ -+ h := newGFp2(pool).Sub(u2, u1) -+ xEqual := h.IsZero() -+ -+ t.Add(h, h) -+ i := newGFp2(pool).Square(t, pool) -+ j := newGFp2(pool).Mul(h, i, pool) -+ -+ t.Sub(s2, s1) -+ yEqual := t.IsZero() -+ if xEqual && yEqual { -+ c.Double(a, pool) -+ return -+ } -+ r := newGFp2(pool).Add(t, t) -+ -+ v := newGFp2(pool).Mul(u1, i, pool) -+ -+ t4 := newGFp2(pool).Square(r, pool) -+ t.Add(v, v) -+ t6 := newGFp2(pool).Sub(t4, j) -+ c.x.Sub(t6, t) -+ -+ t.Sub(v, c.x) // t7 -+ t4.Mul(s1, j, pool) // t8 -+ t6.Add(t4, t4) // t9 -+ t4.Mul(r, t, pool) // t10 -+ c.y.Sub(t4, t6) -+ -+ t.Add(a.z, b.z) // t11 -+ t4.Square(t, pool) // t12 -+ t.Sub(t4, z1z1) // t13 -+ t4.Sub(t, z2z2) // t14 -+ c.z.Mul(t4, h, pool) -+ -+ z1z1.Put(pool) -+ z2z2.Put(pool) -+ u1.Put(pool) -+ u2.Put(pool) -+ t.Put(pool) -+ s1.Put(pool) -+ s2.Put(pool) -+ h.Put(pool) -+ i.Put(pool) -+ j.Put(pool) -+ r.Put(pool) -+ v.Put(pool) -+ t4.Put(pool) -+ t6.Put(pool) -+} -+ -+func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 -+ A := newGFp2(pool).Square(a.x, pool) -+ B := newGFp2(pool).Square(a.y, pool) -+ C := newGFp2(pool).Square(B, pool) -+ -+ t := newGFp2(pool).Add(a.x, B) -+ t2 := newGFp2(pool).Square(t, pool) -+ t.Sub(t2, A) -+ t2.Sub(t, C) -+ d := newGFp2(pool).Add(t2, t2) -+ t.Add(A, A) -+ e := newGFp2(pool).Add(t, A) -+ f := newGFp2(pool).Square(e, pool) -+ -+ t.Add(d, d) -+ c.x.Sub(f, t) -+ -+ t.Add(C, C) -+ t2.Add(t, t) -+ t.Add(t2, t2) -+ c.y.Sub(d, c.x) -+ t2.Mul(e, c.y, pool) -+ c.y.Sub(t2, t) -+ -+ t.Mul(a.y, a.z, pool) -+ c.z.Add(t, t) -+ -+ A.Put(pool) -+ B.Put(pool) -+ C.Put(pool) -+ t.Put(pool) -+ t2.Put(pool) -+ d.Put(pool) -+ e.Put(pool) -+ f.Put(pool) -+} -+ -+func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { -+ sum := newTwistPoint(pool) -+ sum.SetInfinity() -+ t := newTwistPoint(pool) -+ -+ for i := scalar.BitLen(); i >= 0; i-- { -+ t.Double(sum, pool) -+ if scalar.Bit(i) != 0 { -+ sum.Add(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ sum.Put(pool) -+ t.Put(pool) -+ return c -+} -+ -+// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets -+// c to 0 : 1 : 0. -+func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { -+ if c.z.IsOne() { -+ return c -+ } -+ if c.IsInfinity() { -+ c.x.SetZero() -+ c.y.SetOne() -+ c.z.SetZero() -+ c.t.SetZero() -+ return c -+ } -+ -+ zInv := newGFp2(pool).Invert(c.z, pool) -+ t := newGFp2(pool).Mul(c.y, zInv, pool) -+ zInv2 := newGFp2(pool).Square(zInv, pool) -+ c.y.Mul(t, zInv2, pool) -+ t.Mul(c.x, zInv2, pool) -+ c.x.Set(t) -+ c.z.SetOne() -+ c.t.SetOne() -+ -+ zInv.Put(pool) -+ t.Put(pool) -+ zInv2.Put(pool) -+ -+ return c -+} -+ -+func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { -+ c.x.Set(a.x) -+ c.y.SetZero() -+ c.y.Sub(c.y, a.y) -+ c.z.Set(a.z) -+ c.t.SetZero() -+} -diff --git a/vendor/golang.org/x/crypto/cast5/cast5.go b/vendor/golang.org/x/crypto/cast5/cast5.go -new file mode 100644 -index 000000000000..ddcbeb6f2ad1 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/cast5/cast5.go -@@ -0,0 +1,533 @@ -+// Copyright 2010 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 cast5 implements CAST5, as defined in RFC 2144. -+// -+// CAST5 is a legacy cipher and its short block size makes it vulnerable to -+// birthday bound attacks (see https://sweet32.info). It should only be used -+// where compatibility with legacy systems, not security, is the goal. -+// -+// Deprecated: any new system should use AES (from crypto/aes, if necessary in -+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package cast5 // import "golang.org/x/crypto/cast5" -+ -+import "errors" -+ -+const BlockSize = 8 -+const KeySize = 16 -+ -+type Cipher struct { -+ masking [16]uint32 -+ rotate [16]uint8 -+} -+ -+func NewCipher(key []byte) (c *Cipher, err error) { -+ if len(key) != KeySize { -+ return nil, errors.New("CAST5: keys must be 16 bytes") -+ } -+ -+ c = new(Cipher) -+ c.keySchedule(key) -+ return -+} -+ -+func (c *Cipher) BlockSize() int { -+ return BlockSize -+} -+ -+func (c *Cipher) Encrypt(dst, src []byte) { -+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ -+ l, r = r, l^f1(r, c.masking[0], c.rotate[0]) -+ l, r = r, l^f2(r, c.masking[1], c.rotate[1]) -+ l, r = r, l^f3(r, c.masking[2], c.rotate[2]) -+ l, r = r, l^f1(r, c.masking[3], c.rotate[3]) -+ -+ l, r = r, l^f2(r, c.masking[4], c.rotate[4]) -+ l, r = r, l^f3(r, c.masking[5], c.rotate[5]) -+ l, r = r, l^f1(r, c.masking[6], c.rotate[6]) -+ l, r = r, l^f2(r, c.masking[7], c.rotate[7]) -+ -+ l, r = r, l^f3(r, c.masking[8], c.rotate[8]) -+ l, r = r, l^f1(r, c.masking[9], c.rotate[9]) -+ l, r = r, l^f2(r, c.masking[10], c.rotate[10]) -+ l, r = r, l^f3(r, c.masking[11], c.rotate[11]) -+ -+ l, r = r, l^f1(r, c.masking[12], c.rotate[12]) -+ l, r = r, l^f2(r, c.masking[13], c.rotate[13]) -+ l, r = r, l^f3(r, c.masking[14], c.rotate[14]) -+ l, r = r, l^f1(r, c.masking[15], c.rotate[15]) -+ -+ dst[0] = uint8(r >> 24) -+ dst[1] = uint8(r >> 16) -+ dst[2] = uint8(r >> 8) -+ dst[3] = uint8(r) -+ dst[4] = uint8(l >> 24) -+ dst[5] = uint8(l >> 16) -+ dst[6] = uint8(l >> 8) -+ dst[7] = uint8(l) -+} -+ -+func (c *Cipher) Decrypt(dst, src []byte) { -+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ -+ l, r = r, l^f1(r, c.masking[15], c.rotate[15]) -+ l, r = r, l^f3(r, c.masking[14], c.rotate[14]) -+ l, r = r, l^f2(r, c.masking[13], c.rotate[13]) -+ l, r = r, l^f1(r, c.masking[12], c.rotate[12]) -+ -+ l, r = r, l^f3(r, c.masking[11], c.rotate[11]) -+ l, r = r, l^f2(r, c.masking[10], c.rotate[10]) -+ l, r = r, l^f1(r, c.masking[9], c.rotate[9]) -+ l, r = r, l^f3(r, c.masking[8], c.rotate[8]) -+ -+ l, r = r, l^f2(r, c.masking[7], c.rotate[7]) -+ l, r = r, l^f1(r, c.masking[6], c.rotate[6]) -+ l, r = r, l^f3(r, c.masking[5], c.rotate[5]) -+ l, r = r, l^f2(r, c.masking[4], c.rotate[4]) -+ -+ l, r = r, l^f1(r, c.masking[3], c.rotate[3]) -+ l, r = r, l^f3(r, c.masking[2], c.rotate[2]) -+ l, r = r, l^f2(r, c.masking[1], c.rotate[1]) -+ l, r = r, l^f1(r, c.masking[0], c.rotate[0]) -+ -+ dst[0] = uint8(r >> 24) -+ dst[1] = uint8(r >> 16) -+ dst[2] = uint8(r >> 8) -+ dst[3] = uint8(r) -+ dst[4] = uint8(l >> 24) -+ dst[5] = uint8(l >> 16) -+ dst[6] = uint8(l >> 8) -+ dst[7] = uint8(l) -+} -+ -+type keyScheduleA [4][7]uint8 -+type keyScheduleB [4][5]uint8 -+ -+// keyScheduleRound contains the magic values for a round of the key schedule. -+// The keyScheduleA deals with the lines like: -+// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] -+// Conceptually, both x and z are in the same array, x first. The first -+// element describes which word of this array gets written to and the -+// second, which word gets read. So, for the line above, it's "4, 0", because -+// it's writing to the first word of z, which, being after x, is word 4, and -+// reading from the first word of x: word 0. -+// -+// Next are the indexes into the S-boxes. Now the array is treated as bytes. So -+// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear -+// that it's z that we're indexing. -+// -+// keyScheduleB deals with lines like: -+// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] -+// "K1" is ignored because key words are always written in order. So the five -+// elements are the S-box indexes. They use the same form as in keyScheduleA, -+// above. -+ -+type keyScheduleRound struct{} -+type keySchedule []keyScheduleRound -+ -+var schedule = []struct { -+ a keyScheduleA -+ b keyScheduleB -+}{ -+ { -+ keyScheduleA{ -+ {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8}, -+ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, -+ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, -+ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, -+ }, -+ keyScheduleB{ -+ {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2}, -+ {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6}, -+ {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9}, -+ {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc}, -+ }, -+ }, -+ { -+ keyScheduleA{ -+ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, -+ {1, 4, 0, 2, 1, 3, 16 + 2}, -+ {2, 5, 7, 6, 5, 4, 16 + 1}, -+ {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, -+ }, -+ keyScheduleB{ -+ {3, 2, 0xc, 0xd, 8}, -+ {1, 0, 0xe, 0xf, 0xd}, -+ {7, 6, 8, 9, 3}, -+ {5, 4, 0xa, 0xb, 7}, -+ }, -+ }, -+ { -+ keyScheduleA{ -+ {4, 0, 0xd, 0xf, 0xc, 0xe, 8}, -+ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, -+ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, -+ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, -+ }, -+ keyScheduleB{ -+ {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9}, -+ {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc}, -+ {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2}, -+ {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6}, -+ }, -+ }, -+ { -+ keyScheduleA{ -+ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, -+ {1, 4, 0, 2, 1, 3, 16 + 2}, -+ {2, 5, 7, 6, 5, 4, 16 + 1}, -+ {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, -+ }, -+ keyScheduleB{ -+ {8, 9, 7, 6, 3}, -+ {0xa, 0xb, 5, 4, 7}, -+ {0xc, 0xd, 3, 2, 8}, -+ {0xe, 0xf, 1, 0, 0xd}, -+ }, -+ }, -+} -+ -+func (c *Cipher) keySchedule(in []byte) { -+ var t [8]uint32 -+ var k [32]uint32 -+ -+ for i := 0; i < 4; i++ { -+ j := i * 4 -+ t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3]) -+ } -+ -+ x := []byte{6, 7, 4, 5} -+ ki := 0 -+ -+ for half := 0; half < 2; half++ { -+ for _, round := range schedule { -+ for j := 0; j < 4; j++ { -+ var a [7]uint8 -+ copy(a[:], round.a[j][:]) -+ w := t[a[1]] -+ w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff] -+ w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff] -+ w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff] -+ w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff] -+ w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff] -+ t[a[0]] = w -+ } -+ -+ for j := 0; j < 4; j++ { -+ var b [5]uint8 -+ copy(b[:], round.b[j][:]) -+ w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff] -+ w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff] -+ w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff] -+ w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff] -+ w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff] -+ k[ki] = w -+ ki++ -+ } -+ } -+ } -+ -+ for i := 0; i < 16; i++ { -+ c.masking[i] = k[i] -+ c.rotate[i] = uint8(k[16+i] & 0x1f) -+ } -+} -+ -+// These are the three 'f' functions. See RFC 2144, section 2.2. -+func f1(d, m uint32, r uint8) uint32 { -+ t := m + d -+ I := (t << r) | (t >> (32 - r)) -+ return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff] -+} -+ -+func f2(d, m uint32, r uint8) uint32 { -+ t := m ^ d -+ I := (t << r) | (t >> (32 - r)) -+ return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff] -+} -+ -+func f3(d, m uint32, r uint8) uint32 { -+ t := m - d -+ I := (t << r) | (t >> (32 - r)) -+ return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff] -+} -+ -+var sBox = [8][256]uint32{ -+ { -+ 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, -+ 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, -+ 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, -+ 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, -+ 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, -+ 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, -+ 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, -+ 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, -+ 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, -+ 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, -+ 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, -+ 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, -+ 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, -+ 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, -+ 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, -+ 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, -+ 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, -+ 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, -+ 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, -+ 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, -+ 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, -+ 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, -+ 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, -+ 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, -+ 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, -+ 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, -+ 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, -+ 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, -+ 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, -+ 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, -+ 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, -+ 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, -+ }, -+ { -+ 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, -+ 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, -+ 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, -+ 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, -+ 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, -+ 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, -+ 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, -+ 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, -+ 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, -+ 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, -+ 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, -+ 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, -+ 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, -+ 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, -+ 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, -+ 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, -+ 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, -+ 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, -+ 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, -+ 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, -+ 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, -+ 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, -+ 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, -+ 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, -+ 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, -+ 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, -+ 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, -+ 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, -+ 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, -+ 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, -+ 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, -+ 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, -+ }, -+ { -+ 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, -+ 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, -+ 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, -+ 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, -+ 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, -+ 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, -+ 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, -+ 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, -+ 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, -+ 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, -+ 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, -+ 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, -+ 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, -+ 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, -+ 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, -+ 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, -+ 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, -+ 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, -+ 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, -+ 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, -+ 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, -+ 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, -+ 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, -+ 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, -+ 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, -+ 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, -+ 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, -+ 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, -+ 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, -+ 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, -+ 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, -+ 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, -+ }, -+ { -+ 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, -+ 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, -+ 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, -+ 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, -+ 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, -+ 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, -+ 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, -+ 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, -+ 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, -+ 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, -+ 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, -+ 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, -+ 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, -+ 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, -+ 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, -+ 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, -+ 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, -+ 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, -+ 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, -+ 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, -+ 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, -+ 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, -+ 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, -+ 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, -+ 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, -+ 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, -+ 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, -+ 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, -+ 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, -+ 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, -+ 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, -+ 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, -+ }, -+ { -+ 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, -+ 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, -+ 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, -+ 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, -+ 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, -+ 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, -+ 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, -+ 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, -+ 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, -+ 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, -+ 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, -+ 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, -+ 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, -+ 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, -+ 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, -+ 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, -+ 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, -+ 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, -+ 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, -+ 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, -+ 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, -+ 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, -+ 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, -+ 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, -+ 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, -+ 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, -+ 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, -+ 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, -+ 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, -+ 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, -+ 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, -+ 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, -+ }, -+ { -+ 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, -+ 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, -+ 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, -+ 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, -+ 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, -+ 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, -+ 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, -+ 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, -+ 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, -+ 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, -+ 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, -+ 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, -+ 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, -+ 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, -+ 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, -+ 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, -+ 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, -+ 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, -+ 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, -+ 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, -+ 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, -+ 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, -+ 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, -+ 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, -+ 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, -+ 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, -+ 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, -+ 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, -+ 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, -+ 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, -+ 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, -+ 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, -+ }, -+ { -+ 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, -+ 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, -+ 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, -+ 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, -+ 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, -+ 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, -+ 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, -+ 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, -+ 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, -+ 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, -+ 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, -+ 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, -+ 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, -+ 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, -+ 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, -+ 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, -+ 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, -+ 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, -+ 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, -+ 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, -+ 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, -+ 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, -+ 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, -+ 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, -+ 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, -+ 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, -+ 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, -+ 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, -+ 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, -+ 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, -+ 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, -+ 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, -+ }, -+ { -+ 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, -+ 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, -+ 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, -+ 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, -+ 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, -+ 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, -+ 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, -+ 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, -+ 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, -+ 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, -+ 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, -+ 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, -+ 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, -+ 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, -+ 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, -+ 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, -+ 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, -+ 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, -+ 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, -+ 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, -+ 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, -+ 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, -+ 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, -+ 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, -+ 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, -+ 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, -+ 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, -+ 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, -+ 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, -+ 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, -+ 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, -+ 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, -+ }, -+} -diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go -index b799e440b4a1..94c71ac1ac86 100644 ---- a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go -+++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build go1.11,!gccgo,!purego -+//go:build go1.11 && gc && !purego -+// +build go1.11,gc,!purego - - package chacha20 - -diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s -index 891481539a11..63cae9e6f0b1 100644 ---- a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s -+++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build go1.11,!gccgo,!purego -+//go:build go1.11 && gc && !purego -+// +build go1.11,gc,!purego - - #include "textflag.h" - -diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go -index 4635307b8f29..025b49897e32 100644 ---- a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go -+++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo purego -+//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego -+// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego - - package chacha20 - -diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go -index b79933034156..da420b2e97b0 100644 ---- a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go -+++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - package chacha20 - -diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s -index 23c602164301..5c0fed26f850 100644 ---- a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s -+++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s -@@ -19,7 +19,8 @@ - // The differences in this and the original implementation are - // due to the calling conventions and initialization of constants. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - #include "textflag.h" - -diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go -index a9244bdf4dbf..c5898db46584 100644 ---- a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go -+++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - package chacha20 - -diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s -index 89c658c410bf..f3ef5a019d95 100644 ---- a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s -+++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - #include "go_asm.h" - #include "textflag.h" -diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go -new file mode 100644 -index 000000000000..93da7322bc48 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go -@@ -0,0 +1,98 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its -+// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and -+// draft-irtf-cfrg-xchacha-01. -+package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305" -+ -+import ( -+ "crypto/cipher" -+ "errors" -+) -+ -+const ( -+ // KeySize is the size of the key used by this AEAD, in bytes. -+ KeySize = 32 -+ -+ // NonceSize is the size of the nonce used with the standard variant of this -+ // AEAD, in bytes. -+ // -+ // Note that this is too short to be safely generated at random if the same -+ // key is reused more than 2³² times. -+ NonceSize = 12 -+ -+ // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 -+ // variant of this AEAD, in bytes. -+ NonceSizeX = 24 -+ -+ // Overhead is the size of the Poly1305 authentication tag, and the -+ // difference between a ciphertext length and its plaintext. -+ Overhead = 16 -+) -+ -+type chacha20poly1305 struct { -+ key [KeySize]byte -+} -+ -+// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key. -+func New(key []byte) (cipher.AEAD, error) { -+ if len(key) != KeySize { -+ return nil, errors.New("chacha20poly1305: bad key length") -+ } -+ ret := new(chacha20poly1305) -+ copy(ret.key[:], key) -+ return ret, nil -+} -+ -+func (c *chacha20poly1305) NonceSize() int { -+ return NonceSize -+} -+ -+func (c *chacha20poly1305) Overhead() int { -+ return Overhead -+} -+ -+func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ if len(nonce) != NonceSize { -+ panic("chacha20poly1305: bad nonce length passed to Seal") -+ } -+ -+ if uint64(len(plaintext)) > (1<<38)-64 { -+ panic("chacha20poly1305: plaintext too large") -+ } -+ -+ return c.seal(dst, nonce, plaintext, additionalData) -+} -+ -+var errOpen = errors.New("chacha20poly1305: message authentication failed") -+ -+func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ if len(nonce) != NonceSize { -+ panic("chacha20poly1305: bad nonce length passed to Open") -+ } -+ if len(ciphertext) < 16 { -+ return nil, errOpen -+ } -+ if uint64(len(ciphertext)) > (1<<38)-48 { -+ panic("chacha20poly1305: ciphertext too large") -+ } -+ -+ return c.open(dst, nonce, ciphertext, additionalData) -+} -+ -+// sliceForAppend takes a slice and a requested number of bytes. It returns a -+// slice with the contents of the given slice followed by that many bytes and a -+// second slice that aliases into it and contains only the extra bytes. If the -+// original slice has sufficient capacity then no allocation is performed. -+func sliceForAppend(in []byte, n int) (head, tail []byte) { -+ if total := len(in) + n; cap(in) >= total { -+ head = in[:total] -+ } else { -+ head = make([]byte, total) -+ copy(head, in) -+ } -+ tail = head[len(in):] -+ return -+} -diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go -new file mode 100644 -index 000000000000..25959b9a6efa ---- /dev/null -+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go -@@ -0,0 +1,87 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package chacha20poly1305 -+ -+import ( -+ "encoding/binary" -+ -+ "golang.org/x/crypto/internal/subtle" -+ "golang.org/x/sys/cpu" -+) -+ -+//go:noescape -+func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool -+ -+//go:noescape -+func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) -+ -+var ( -+ useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 -+) -+ -+// setupState writes a ChaCha20 input matrix to state. See -+// https://tools.ietf.org/html/rfc7539#section-2.3. -+func setupState(state *[16]uint32, key *[32]byte, nonce []byte) { -+ state[0] = 0x61707865 -+ state[1] = 0x3320646e -+ state[2] = 0x79622d32 -+ state[3] = 0x6b206574 -+ -+ state[4] = binary.LittleEndian.Uint32(key[0:4]) -+ state[5] = binary.LittleEndian.Uint32(key[4:8]) -+ state[6] = binary.LittleEndian.Uint32(key[8:12]) -+ state[7] = binary.LittleEndian.Uint32(key[12:16]) -+ state[8] = binary.LittleEndian.Uint32(key[16:20]) -+ state[9] = binary.LittleEndian.Uint32(key[20:24]) -+ state[10] = binary.LittleEndian.Uint32(key[24:28]) -+ state[11] = binary.LittleEndian.Uint32(key[28:32]) -+ -+ state[12] = 0 -+ state[13] = binary.LittleEndian.Uint32(nonce[0:4]) -+ state[14] = binary.LittleEndian.Uint32(nonce[4:8]) -+ state[15] = binary.LittleEndian.Uint32(nonce[8:12]) -+} -+ -+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ if !cpu.X86.HasSSSE3 { -+ return c.sealGeneric(dst, nonce, plaintext, additionalData) -+ } -+ -+ var state [16]uint32 -+ setupState(&state, &c.key, nonce) -+ -+ ret, out := sliceForAppend(dst, len(plaintext)+16) -+ if subtle.InexactOverlap(out, plaintext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData) -+ return ret -+} -+ -+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ if !cpu.X86.HasSSSE3 { -+ return c.openGeneric(dst, nonce, ciphertext, additionalData) -+ } -+ -+ var state [16]uint32 -+ setupState(&state, &c.key, nonce) -+ -+ ciphertext = ciphertext[:len(ciphertext)-16] -+ ret, out := sliceForAppend(dst, len(ciphertext)) -+ if subtle.InexactOverlap(out, ciphertext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) { -+ for i := range out { -+ out[i] = 0 -+ } -+ return nil, errOpen -+ } -+ -+ return ret, nil -+} -diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s -new file mode 100644 -index 000000000000..867c181a14c0 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s -@@ -0,0 +1,2696 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+// General register allocation -+#define oup DI -+#define inp SI -+#define inl BX -+#define adp CX // free to reuse, after we hash the additional data -+#define keyp R8 // free to reuse, when we copy the key to stack -+#define itr2 R9 // general iterator -+#define itr1 CX // general iterator -+#define acc0 R10 -+#define acc1 R11 -+#define acc2 R12 -+#define t0 R13 -+#define t1 R14 -+#define t2 R15 -+#define t3 R8 -+// Register and stack allocation for the SSE code -+#define rStore (0*16)(BP) -+#define sStore (1*16)(BP) -+#define state1Store (2*16)(BP) -+#define state2Store (3*16)(BP) -+#define tmpStore (4*16)(BP) -+#define ctr0Store (5*16)(BP) -+#define ctr1Store (6*16)(BP) -+#define ctr2Store (7*16)(BP) -+#define ctr3Store (8*16)(BP) -+#define A0 X0 -+#define A1 X1 -+#define A2 X2 -+#define B0 X3 -+#define B1 X4 -+#define B2 X5 -+#define C0 X6 -+#define C1 X7 -+#define C2 X8 -+#define D0 X9 -+#define D1 X10 -+#define D2 X11 -+#define T0 X12 -+#define T1 X13 -+#define T2 X14 -+#define T3 X15 -+#define A3 T0 -+#define B3 T1 -+#define C3 T2 -+#define D3 T3 -+// Register and stack allocation for the AVX2 code -+#define rsStoreAVX2 (0*32)(BP) -+#define state1StoreAVX2 (1*32)(BP) -+#define state2StoreAVX2 (2*32)(BP) -+#define ctr0StoreAVX2 (3*32)(BP) -+#define ctr1StoreAVX2 (4*32)(BP) -+#define ctr2StoreAVX2 (5*32)(BP) -+#define ctr3StoreAVX2 (6*32)(BP) -+#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack -+#define AA0 Y0 -+#define AA1 Y5 -+#define AA2 Y6 -+#define AA3 Y7 -+#define BB0 Y14 -+#define BB1 Y9 -+#define BB2 Y10 -+#define BB3 Y11 -+#define CC0 Y12 -+#define CC1 Y13 -+#define CC2 Y8 -+#define CC3 Y15 -+#define DD0 Y4 -+#define DD1 Y1 -+#define DD2 Y2 -+#define DD3 Y3 -+#define TT0 DD3 -+#define TT1 AA3 -+#define TT2 BB3 -+#define TT3 CC3 -+// ChaCha20 constants -+DATA ·chacha20Constants<>+0x00(SB)/4, $0x61707865 -+DATA ·chacha20Constants<>+0x04(SB)/4, $0x3320646e -+DATA ·chacha20Constants<>+0x08(SB)/4, $0x79622d32 -+DATA ·chacha20Constants<>+0x0c(SB)/4, $0x6b206574 -+DATA ·chacha20Constants<>+0x10(SB)/4, $0x61707865 -+DATA ·chacha20Constants<>+0x14(SB)/4, $0x3320646e -+DATA ·chacha20Constants<>+0x18(SB)/4, $0x79622d32 -+DATA ·chacha20Constants<>+0x1c(SB)/4, $0x6b206574 -+// <<< 16 with PSHUFB -+DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302 -+DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -+DATA ·rol16<>+0x10(SB)/8, $0x0504070601000302 -+DATA ·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A -+// <<< 8 with PSHUFB -+DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003 -+DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B -+DATA ·rol8<>+0x10(SB)/8, $0x0605040702010003 -+DATA ·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B -+ -+DATA ·avx2InitMask<>+0x00(SB)/8, $0x0 -+DATA ·avx2InitMask<>+0x08(SB)/8, $0x0 -+DATA ·avx2InitMask<>+0x10(SB)/8, $0x1 -+DATA ·avx2InitMask<>+0x18(SB)/8, $0x0 -+ -+DATA ·avx2IncMask<>+0x00(SB)/8, $0x2 -+DATA ·avx2IncMask<>+0x08(SB)/8, $0x0 -+DATA ·avx2IncMask<>+0x10(SB)/8, $0x2 -+DATA ·avx2IncMask<>+0x18(SB)/8, $0x0 -+// Poly1305 key clamp -+DATA ·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -+DATA ·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -+DATA ·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF -+DATA ·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF -+ -+DATA ·sseIncMask<>+0x00(SB)/8, $0x1 -+DATA ·sseIncMask<>+0x08(SB)/8, $0x0 -+// To load/store the last < 16 bytes in a buffer -+DATA ·andMask<>+0x00(SB)/8, $0x00000000000000ff -+DATA ·andMask<>+0x08(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x10(SB)/8, $0x000000000000ffff -+DATA ·andMask<>+0x18(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x20(SB)/8, $0x0000000000ffffff -+DATA ·andMask<>+0x28(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x30(SB)/8, $0x00000000ffffffff -+DATA ·andMask<>+0x38(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x40(SB)/8, $0x000000ffffffffff -+DATA ·andMask<>+0x48(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x50(SB)/8, $0x0000ffffffffffff -+DATA ·andMask<>+0x58(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x60(SB)/8, $0x00ffffffffffffff -+DATA ·andMask<>+0x68(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x70(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0x78(SB)/8, $0x0000000000000000 -+DATA ·andMask<>+0x80(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0x88(SB)/8, $0x00000000000000ff -+DATA ·andMask<>+0x90(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0x98(SB)/8, $0x000000000000ffff -+DATA ·andMask<>+0xa0(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0xa8(SB)/8, $0x0000000000ffffff -+DATA ·andMask<>+0xb0(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0xb8(SB)/8, $0x00000000ffffffff -+DATA ·andMask<>+0xc0(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0xc8(SB)/8, $0x000000ffffffffff -+DATA ·andMask<>+0xd0(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff -+DATA ·andMask<>+0xe0(SB)/8, $0xffffffffffffffff -+DATA ·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff -+ -+GLOBL ·chacha20Constants<>(SB), (NOPTR+RODATA), $32 -+GLOBL ·rol16<>(SB), (NOPTR+RODATA), $32 -+GLOBL ·rol8<>(SB), (NOPTR+RODATA), $32 -+GLOBL ·sseIncMask<>(SB), (NOPTR+RODATA), $16 -+GLOBL ·avx2IncMask<>(SB), (NOPTR+RODATA), $32 -+GLOBL ·avx2InitMask<>(SB), (NOPTR+RODATA), $32 -+GLOBL ·polyClampMask<>(SB), (NOPTR+RODATA), $32 -+GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240 -+// No PALIGNR in Go ASM yet (but VPALIGNR is present). -+#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3 -+#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4 -+#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5 -+#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13 -+#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6 -+#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7 -+#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8 -+#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14 -+#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9 -+#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10 -+#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11 -+#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15 -+#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3 -+#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4 -+#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5 -+#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13 -+#define shiftC0Right shiftC0Left -+#define shiftC1Right shiftC1Left -+#define shiftC2Right shiftC2Left -+#define shiftC3Right shiftC3Left -+#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9 -+#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10 -+#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11 -+#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15 -+// Some macros -+#define chachaQR(A, B, C, D, T) \ -+ PADDD B, A; PXOR A, D; PSHUFB ·rol16<>(SB), D \ -+ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \ -+ PADDD B, A; PXOR A, D; PSHUFB ·rol8<>(SB), D \ -+ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B -+ -+#define chachaQR_AVX2(A, B, C, D, T) \ -+ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol16<>(SB), D, D \ -+ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \ -+ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol8<>(SB), D, D \ -+ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B -+ -+#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2 -+#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2 -+#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX -+#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3 -+#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t3, t2; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2 -+ -+#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2 -+#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3 -+#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3 -+ -+#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage -+#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage -+// ---------------------------------------------------------------------------- -+TEXT polyHashADInternal<>(SB), NOSPLIT, $0 -+ // adp points to beginning of additional data -+ // itr2 holds ad length -+ XORQ acc0, acc0 -+ XORQ acc1, acc1 -+ XORQ acc2, acc2 -+ CMPQ itr2, $13 -+ JNE hashADLoop -+ -+openFastTLSAD: -+ // Special treatment for the TLS case of 13 bytes -+ MOVQ (adp), acc0 -+ MOVQ 5(adp), acc1 -+ SHRQ $24, acc1 -+ MOVQ $1, acc2 -+ polyMul -+ RET -+ -+hashADLoop: -+ // Hash in 16 byte chunks -+ CMPQ itr2, $16 -+ JB hashADTail -+ polyAdd(0(adp)) -+ LEAQ (1*16)(adp), adp -+ SUBQ $16, itr2 -+ polyMul -+ JMP hashADLoop -+ -+hashADTail: -+ CMPQ itr2, $0 -+ JE hashADDone -+ -+ // Hash last < 16 byte tail -+ XORQ t0, t0 -+ XORQ t1, t1 -+ XORQ t2, t2 -+ ADDQ itr2, adp -+ -+hashADTailLoop: -+ SHLQ $8, t0, t1 -+ SHLQ $8, t0 -+ MOVB -1(adp), t2 -+ XORQ t2, t0 -+ DECQ adp -+ DECQ itr2 -+ JNE hashADTailLoop -+ -+hashADTailFinish: -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ -+ // Finished AD -+hashADDone: -+ RET -+ -+// ---------------------------------------------------------------------------- -+// func chacha20Poly1305Open(dst, key, src, ad []byte) bool -+TEXT ·chacha20Poly1305Open(SB), 0, $288-97 -+ // For aligned stack access -+ MOVQ SP, BP -+ ADDQ $32, BP -+ ANDQ $-32, BP -+ MOVQ dst+0(FP), oup -+ MOVQ key+24(FP), keyp -+ MOVQ src+48(FP), inp -+ MOVQ src_len+56(FP), inl -+ MOVQ ad+72(FP), adp -+ -+ // Check for AVX2 support -+ CMPB ·useAVX2(SB), $1 -+ JE chacha20Poly1305Open_AVX2 -+ -+ // Special optimization, for very short buffers -+ CMPQ inl, $128 -+ JBE openSSE128 // About 16% faster -+ -+ // For long buffers, prepare the poly key first -+ MOVOU ·chacha20Constants<>(SB), A0 -+ MOVOU (1*16)(keyp), B0 -+ MOVOU (2*16)(keyp), C0 -+ MOVOU (3*16)(keyp), D0 -+ MOVO D0, T1 -+ -+ // Store state on stack for future use -+ MOVO B0, state1Store -+ MOVO C0, state2Store -+ MOVO D0, ctr3Store -+ MOVQ $10, itr2 -+ -+openSSEPreparePolyKey: -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ DECQ itr2 -+ JNE openSSEPreparePolyKey -+ -+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded -+ PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0 -+ -+ // Clamp and store the key -+ PAND ·polyClampMask<>(SB), A0 -+ MOVO A0, rStore; MOVO B0, sStore -+ -+ // Hash AAD -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+openSSEMainLoop: -+ CMPQ inl, $256 -+ JB openSSEMainLoopDone -+ -+ // Load state, increment counter blocks -+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ -+ // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16 -+ MOVQ $4, itr1 -+ MOVQ inp, itr2 -+ -+openSSEInternalLoop: -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyAdd(0(itr2)) -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ polyMulStage1 -+ polyMulStage2 -+ LEAQ (2*8)(itr2), itr2 -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ polyMulStage3 -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyMulReduceStage -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ DECQ itr1 -+ JGE openSSEInternalLoop -+ -+ polyAdd(0(itr2)) -+ polyMul -+ LEAQ (2*8)(itr2), itr2 -+ -+ CMPQ itr1, $-6 -+ JG openSSEInternalLoop -+ -+ // Add in the state -+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ -+ // Load - xor - store -+ MOVO D3, tmpStore -+ MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup) -+ MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup) -+ MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup) -+ MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup) -+ MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup) -+ MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup) -+ MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup) -+ MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup) -+ MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup) -+ MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup) -+ MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup) -+ MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup) -+ MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup) -+ MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup) -+ MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup) -+ MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup) -+ LEAQ 256(inp), inp -+ LEAQ 256(oup), oup -+ SUBQ $256, inl -+ JMP openSSEMainLoop -+ -+openSSEMainLoopDone: -+ // Handle the various tail sizes efficiently -+ TESTQ inl, inl -+ JE openSSEFinalize -+ CMPQ inl, $64 -+ JBE openSSETail64 -+ CMPQ inl, $128 -+ JBE openSSETail128 -+ CMPQ inl, $192 -+ JBE openSSETail192 -+ JMP openSSETail256 -+ -+openSSEFinalize: -+ // Hash in the PT, AAD lengths -+ ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2 -+ polyMul -+ -+ // Final reduce -+ MOVQ acc0, t0 -+ MOVQ acc1, t1 -+ MOVQ acc2, t2 -+ SUBQ $-5, acc0 -+ SBBQ $-1, acc1 -+ SBBQ $3, acc2 -+ CMOVQCS t0, acc0 -+ CMOVQCS t1, acc1 -+ CMOVQCS t2, acc2 -+ -+ // Add in the "s" part of the key -+ ADDQ 0+sStore, acc0 -+ ADCQ 8+sStore, acc1 -+ -+ // Finally, constant time compare to the tag at the end of the message -+ XORQ AX, AX -+ MOVQ $1, DX -+ XORQ (0*8)(inp), acc0 -+ XORQ (1*8)(inp), acc1 -+ ORQ acc1, acc0 -+ CMOVQEQ DX, AX -+ -+ // Return true iff tags are equal -+ MOVB AX, ret+96(FP) -+ RET -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 129 bytes -+openSSE128: -+ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks -+ MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 -+ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 -+ MOVQ $10, itr2 -+ -+openSSE128InnerCipherLoop: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftB1Left; shiftB2Left -+ shiftC0Left; shiftC1Left; shiftC2Left -+ shiftD0Left; shiftD1Left; shiftD2Left -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftB1Right; shiftB2Right -+ shiftC0Right; shiftC1Right; shiftC2Right -+ shiftD0Right; shiftD1Right; shiftD2Right -+ DECQ itr2 -+ JNE openSSE128InnerCipherLoop -+ -+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded -+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 -+ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 -+ PADDL T2, C1; PADDL T2, C2 -+ PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 -+ -+ // Clamp and store the key -+ PAND ·polyClampMask<>(SB), A0 -+ MOVOU A0, rStore; MOVOU B0, sStore -+ -+ // Hash -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+openSSE128Open: -+ CMPQ inl, $16 -+ JB openSSETail16 -+ SUBQ $16, inl -+ -+ // Load for hashing -+ polyAdd(0(inp)) -+ -+ // Load for decryption -+ MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ polyMul -+ -+ // Shift the stream "left" -+ MOVO B1, A1 -+ MOVO C1, B1 -+ MOVO D1, C1 -+ MOVO A2, D1 -+ MOVO B2, A2 -+ MOVO C2, B2 -+ MOVO D2, C2 -+ JMP openSSE128Open -+ -+openSSETail16: -+ TESTQ inl, inl -+ JE openSSEFinalize -+ -+ // We can safely load the CT from the end, because it is padded with the MAC -+ MOVQ inl, itr2 -+ SHLQ $4, itr2 -+ LEAQ ·andMask<>(SB), t0 -+ MOVOU (inp), T0 -+ ADDQ inl, inp -+ PAND -16(t0)(itr2*1), T0 -+ MOVO T0, 0+tmpStore -+ MOVQ T0, t0 -+ MOVQ 8+tmpStore, t1 -+ PXOR A1, T0 -+ -+ // We can only store one byte at a time, since plaintext can be shorter than 16 bytes -+openSSETail16Store: -+ MOVQ T0, t3 -+ MOVB t3, (oup) -+ PSRLDQ $1, T0 -+ INCQ oup -+ DECQ inl -+ JNE openSSETail16Store -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ JMP openSSEFinalize -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 64 bytes of ciphertext -+openSSETail64: -+ // Need to decrypt up to 64 bytes - prepare single block -+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store -+ XORQ itr2, itr2 -+ MOVQ inl, itr1 -+ CMPQ itr1, $16 -+ JB openSSETail64LoopB -+ -+openSSETail64LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ SUBQ $16, itr1 -+ -+openSSETail64LoopB: -+ ADDQ $16, itr2 -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ -+ CMPQ itr1, $16 -+ JAE openSSETail64LoopA -+ -+ CMPQ itr2, $160 -+ JNE openSSETail64LoopB -+ -+ PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0 -+ -+openSSETail64DecLoop: -+ CMPQ inl, $16 -+ JB openSSETail64DecLoopDone -+ SUBQ $16, inl -+ MOVOU (inp), T0 -+ PXOR T0, A0 -+ MOVOU A0, (oup) -+ LEAQ 16(inp), inp -+ LEAQ 16(oup), oup -+ MOVO B0, A0 -+ MOVO C0, B0 -+ MOVO D0, C0 -+ JMP openSSETail64DecLoop -+ -+openSSETail64DecLoopDone: -+ MOVO A0, A1 -+ JMP openSSETail16 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of ciphertext -+openSSETail128: -+ // Need to decrypt up to 128 bytes - prepare two blocks -+ MOVO ·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr0Store -+ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr1Store -+ XORQ itr2, itr2 -+ MOVQ inl, itr1 -+ ANDQ $-16, itr1 -+ -+openSSETail128LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ -+openSSETail128LoopB: -+ ADDQ $16, itr2 -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ -+ CMPQ itr2, itr1 -+ JB openSSETail128LoopA -+ -+ CMPQ itr2, $160 -+ JNE openSSETail128LoopB -+ -+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 -+ PADDL state1Store, B0; PADDL state1Store, B1 -+ PADDL state2Store, C0; PADDL state2Store, C1 -+ PADDL ctr1Store, D0; PADDL ctr0Store, D1 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 -+ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) -+ -+ SUBQ $64, inl -+ LEAQ 64(inp), inp -+ LEAQ 64(oup), oup -+ JMP openSSETail64DecLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 192 bytes of ciphertext -+openSSETail192: -+ // Need to decrypt up to 192 bytes - prepare three blocks -+ MOVO ·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr0Store -+ MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store -+ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr2Store -+ -+ MOVQ inl, itr1 -+ MOVQ $160, itr2 -+ CMPQ itr1, $160 -+ CMOVQGT itr2, itr1 -+ ANDQ $-16, itr1 -+ XORQ itr2, itr2 -+ -+openSSLTail192LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ -+openSSLTail192LoopB: -+ ADDQ $16, itr2 -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ shiftB2Left; shiftC2Left; shiftD2Left -+ -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ shiftB2Right; shiftC2Right; shiftD2Right -+ -+ CMPQ itr2, itr1 -+ JB openSSLTail192LoopA -+ -+ CMPQ itr2, $160 -+ JNE openSSLTail192LoopB -+ -+ CMPQ inl, $176 -+ JB openSSLTail192Store -+ -+ polyAdd(160(inp)) -+ polyMul -+ -+ CMPQ inl, $192 -+ JB openSSLTail192Store -+ -+ polyAdd(176(inp)) -+ polyMul -+ -+openSSLTail192Store: -+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 -+ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 -+ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 -+ PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2 -+ MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup) -+ -+ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 -+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ -+ SUBQ $128, inl -+ LEAQ 128(inp), inp -+ LEAQ 128(oup), oup -+ JMP openSSETail64DecLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 256 bytes of ciphertext -+openSSETail256: -+ // Need to decrypt up to 256 bytes - prepare four blocks -+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ XORQ itr2, itr2 -+ -+openSSETail256Loop: -+ // This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication -+ polyAdd(0(inp)(itr2*1)) -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ polyMulStage1 -+ polyMulStage2 -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyMulStage3 -+ polyMulReduceStage -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ ADDQ $2*8, itr2 -+ CMPQ itr2, $160 -+ JB openSSETail256Loop -+ MOVQ inl, itr1 -+ ANDQ $-16, itr1 -+ -+openSSETail256HashLoop: -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ ADDQ $2*8, itr2 -+ CMPQ itr2, itr1 -+ JB openSSETail256HashLoop -+ -+ // Add in the state -+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ MOVO D3, tmpStore -+ -+ // Load - xor - store -+ MOVOU (0*16)(inp), D3; PXOR D3, A0 -+ MOVOU (1*16)(inp), D3; PXOR D3, B0 -+ MOVOU (2*16)(inp), D3; PXOR D3, C0 -+ MOVOU (3*16)(inp), D3; PXOR D3, D0 -+ MOVOU A0, (0*16)(oup) -+ MOVOU B0, (1*16)(oup) -+ MOVOU C0, (2*16)(oup) -+ MOVOU D0, (3*16)(oup) -+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 -+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 -+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 -+ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) -+ LEAQ 192(inp), inp -+ LEAQ 192(oup), oup -+ SUBQ $192, inl -+ MOVO A3, A0 -+ MOVO B3, B0 -+ MOVO C3, C0 -+ MOVO tmpStore, D0 -+ -+ JMP openSSETail64DecLoop -+ -+// ---------------------------------------------------------------------------- -+// ------------------------- AVX2 Code ---------------------------------------- -+chacha20Poly1305Open_AVX2: -+ VZEROUPPER -+ VMOVDQU ·chacha20Constants<>(SB), AA0 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 -+ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 -+ VPADDD ·avx2InitMask<>(SB), DD0, DD0 -+ -+ // Special optimization, for very short buffers -+ CMPQ inl, $192 -+ JBE openAVX2192 -+ CMPQ inl, $320 -+ JBE openAVX2320 -+ -+ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream -+ VMOVDQA BB0, state1StoreAVX2 -+ VMOVDQA CC0, state2StoreAVX2 -+ VMOVDQA DD0, ctr3StoreAVX2 -+ MOVQ $10, itr2 -+ -+openAVX2PreparePolyKey: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 -+ DECQ itr2 -+ JNE openAVX2PreparePolyKey -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0 -+ VPADDD state1StoreAVX2, BB0, BB0 -+ VPADDD state2StoreAVX2, CC0, CC0 -+ VPADDD ctr3StoreAVX2, DD0, DD0 -+ -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ -+ // Clamp and store poly key -+ VPAND ·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for the first 64 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ -+ // Hash AD + first 64 bytes -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ XORQ itr1, itr1 -+ -+openAVX2InitialHash64: -+ polyAdd(0(inp)(itr1*1)) -+ polyMulAVX2 -+ ADDQ $16, itr1 -+ CMPQ itr1, $64 -+ JNE openAVX2InitialHash64 -+ -+ // Decrypt the first 64 bytes -+ VPXOR (0*32)(inp), AA0, AA0 -+ VPXOR (1*32)(inp), BB0, BB0 -+ VMOVDQU AA0, (0*32)(oup) -+ VMOVDQU BB0, (1*32)(oup) -+ LEAQ (2*32)(inp), inp -+ LEAQ (2*32)(oup), oup -+ SUBQ $64, inl -+ -+openAVX2MainLoop: -+ CMPQ inl, $512 -+ JB openAVX2MainLoopDone -+ -+ // Load state, increment counter blocks, store the incremented counters -+ VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ XORQ itr1, itr1 -+ -+openAVX2InternalLoop: -+ // Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications -+ // Effectively per 512 bytes of stream we hash 480 bytes of ciphertext -+ polyAdd(0*8(inp)(itr1*1)) -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage1_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ polyMulStage2_AVX2 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyMulStage3_AVX2 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ polyAdd(2*8(inp)(itr1*1)) -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage1_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage2_AVX2 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage3_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ polyMulReduceStage -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(4*8(inp)(itr1*1)) -+ LEAQ (6*8)(itr1), itr1 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage1_AVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ polyMulStage2_AVX2 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage3_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ CMPQ itr1, $480 -+ JNE openAVX2InternalLoop -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ -+ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here -+ polyAdd(480(inp)) -+ polyMulAVX2 -+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 -+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 -+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ -+ // and here -+ polyAdd(496(inp)) -+ polyMulAVX2 -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) -+ LEAQ (32*16)(inp), inp -+ LEAQ (32*16)(oup), oup -+ SUBQ $(32*16), inl -+ JMP openAVX2MainLoop -+ -+openAVX2MainLoopDone: -+ // Handle the various tail sizes efficiently -+ TESTQ inl, inl -+ JE openSSEFinalize -+ CMPQ inl, $128 -+ JBE openAVX2Tail128 -+ CMPQ inl, $256 -+ JBE openAVX2Tail256 -+ CMPQ inl, $384 -+ JBE openAVX2Tail384 -+ JMP openAVX2Tail512 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 193 bytes -+openAVX2192: -+ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks -+ VMOVDQA AA0, AA1 -+ VMOVDQA BB0, BB1 -+ VMOVDQA CC0, CC1 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2 -+ VMOVDQA BB0, BB2 -+ VMOVDQA CC0, CC2 -+ VMOVDQA DD0, DD2 -+ VMOVDQA DD1, TT3 -+ MOVQ $10, itr2 -+ -+openAVX2192InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ DECQ itr2 -+ JNE openAVX2192InnerCipherLoop -+ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 -+ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 -+ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 -+ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ -+ // Clamp and store poly key -+ VPAND ·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 192 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ -+openAVX2ShortOpen: -+ // Hash -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+openAVX2ShortOpenLoop: -+ CMPQ inl, $32 -+ JB openAVX2ShortTail32 -+ SUBQ $32, inl -+ -+ // Load for hashing -+ polyAdd(0*8(inp)) -+ polyMulAVX2 -+ polyAdd(2*8(inp)) -+ polyMulAVX2 -+ -+ // Load for decryption -+ VPXOR (inp), AA0, AA0 -+ VMOVDQU AA0, (oup) -+ LEAQ (1*32)(inp), inp -+ LEAQ (1*32)(oup), oup -+ -+ // Shift stream left -+ VMOVDQA BB0, AA0 -+ VMOVDQA CC0, BB0 -+ VMOVDQA DD0, CC0 -+ VMOVDQA AA1, DD0 -+ VMOVDQA BB1, AA1 -+ VMOVDQA CC1, BB1 -+ VMOVDQA DD1, CC1 -+ VMOVDQA AA2, DD1 -+ VMOVDQA BB2, AA2 -+ JMP openAVX2ShortOpenLoop -+ -+openAVX2ShortTail32: -+ CMPQ inl, $16 -+ VMOVDQA A0, A1 -+ JB openAVX2ShortDone -+ -+ SUBQ $16, inl -+ -+ // Load for hashing -+ polyAdd(0*8(inp)) -+ polyMulAVX2 -+ -+ // Load for decryption -+ VPXOR (inp), A0, T0 -+ VMOVDQU T0, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ VPERM2I128 $0x11, AA0, AA0, AA0 -+ VMOVDQA A0, A1 -+ -+openAVX2ShortDone: -+ VZEROUPPER -+ JMP openSSETail16 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 321 bytes -+openAVX2320: -+ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks -+ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 -+ MOVQ $10, itr2 -+ -+openAVX2320InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ DECQ itr2 -+ JNE openAVX2320InnerCipherLoop -+ -+ VMOVDQA ·chacha20Constants<>(SB), TT0 -+ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 -+ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 -+ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 -+ VMOVDQA ·avx2IncMask<>(SB), TT0 -+ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD2, DD2 -+ -+ // Clamp and store poly key -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPAND ·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 320 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ VPERM2I128 $0x02, AA2, BB2, CC1 -+ VPERM2I128 $0x02, CC2, DD2, DD1 -+ VPERM2I128 $0x13, AA2, BB2, AA2 -+ VPERM2I128 $0x13, CC2, DD2, BB2 -+ JMP openAVX2ShortOpen -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of ciphertext -+openAVX2Tail128: -+ // Need to decrypt up to 128 bytes - prepare two blocks -+ VMOVDQA ·chacha20Constants<>(SB), AA1 -+ VMOVDQA state1StoreAVX2, BB1 -+ VMOVDQA state2StoreAVX2, CC1 -+ VMOVDQA ctr3StoreAVX2, DD1 -+ VPADDD ·avx2IncMask<>(SB), DD1, DD1 -+ VMOVDQA DD1, DD0 -+ -+ XORQ itr2, itr2 -+ MOVQ inl, itr1 -+ ANDQ $-16, itr1 -+ TESTQ itr1, itr1 -+ JE openAVX2Tail128LoopB -+ -+openAVX2Tail128LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMulAVX2 -+ -+openAVX2Tail128LoopB: -+ ADDQ $16, itr2 -+ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD1, DD1, DD1 -+ CMPQ itr2, itr1 -+ JB openAVX2Tail128LoopA -+ CMPQ itr2, $160 -+ JNE openAVX2Tail128LoopB -+ -+ VPADDD ·chacha20Constants<>(SB), AA1, AA1 -+ VPADDD state1StoreAVX2, BB1, BB1 -+ VPADDD state2StoreAVX2, CC1, CC1 -+ VPADDD DD0, DD1, DD1 -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ -+openAVX2TailLoop: -+ CMPQ inl, $32 -+ JB openAVX2Tail -+ SUBQ $32, inl -+ -+ // Load for decryption -+ VPXOR (inp), AA0, AA0 -+ VMOVDQU AA0, (oup) -+ LEAQ (1*32)(inp), inp -+ LEAQ (1*32)(oup), oup -+ VMOVDQA BB0, AA0 -+ VMOVDQA CC0, BB0 -+ VMOVDQA DD0, CC0 -+ JMP openAVX2TailLoop -+ -+openAVX2Tail: -+ CMPQ inl, $16 -+ VMOVDQA A0, A1 -+ JB openAVX2TailDone -+ SUBQ $16, inl -+ -+ // Load for decryption -+ VPXOR (inp), A0, T0 -+ VMOVDQU T0, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ VPERM2I128 $0x11, AA0, AA0, AA0 -+ VMOVDQA A0, A1 -+ -+openAVX2TailDone: -+ VZEROUPPER -+ JMP openSSETail16 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 256 bytes of ciphertext -+openAVX2Tail256: -+ // Need to decrypt up to 256 bytes - prepare four blocks -+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA DD0, TT1 -+ VMOVDQA DD1, TT2 -+ -+ // Compute the number of iterations that will hash data -+ MOVQ inl, tmpStoreAVX2 -+ MOVQ inl, itr1 -+ SUBQ $128, itr1 -+ SHRQ $4, itr1 -+ MOVQ $10, itr2 -+ CMPQ itr1, $10 -+ CMOVQGT itr2, itr1 -+ MOVQ inp, inl -+ XORQ itr2, itr2 -+ -+openAVX2Tail256LoopA: -+ polyAdd(0(inl)) -+ polyMulAVX2 -+ LEAQ 16(inl), inl -+ -+ // Perform ChaCha rounds, while hashing the remaining input -+openAVX2Tail256LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ INCQ itr2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ CMPQ itr2, itr1 -+ JB openAVX2Tail256LoopA -+ -+ CMPQ itr2, $10 -+ JNE openAVX2Tail256LoopB -+ -+ MOVQ inl, itr2 -+ SUBQ inp, inl -+ MOVQ inl, itr1 -+ MOVQ tmpStoreAVX2, inl -+ -+ // Hash the remainder of data (if any) -+openAVX2Tail256Hash: -+ ADDQ $16, itr1 -+ CMPQ itr1, inl -+ JGT openAVX2Tail256HashEnd -+ polyAdd (0(itr2)) -+ polyMulAVX2 -+ LEAQ 16(itr2), itr2 -+ JMP openAVX2Tail256Hash -+ -+// Store 128 bytes safely, then go to store loop -+openAVX2Tail256HashEnd: -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 -+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2 -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ -+ VPXOR (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2 -+ VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup) -+ LEAQ (4*32)(inp), inp -+ LEAQ (4*32)(oup), oup -+ SUBQ $4*32, inl -+ -+ JMP openAVX2TailLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 384 bytes of ciphertext -+openAVX2Tail384: -+ // Need to decrypt up to 384 bytes - prepare six blocks -+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD1 -+ VPADDD ·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA DD0, ctr0StoreAVX2 -+ VMOVDQA DD1, ctr1StoreAVX2 -+ VMOVDQA DD2, ctr2StoreAVX2 -+ -+ // Compute the number of iterations that will hash two blocks of data -+ MOVQ inl, tmpStoreAVX2 -+ MOVQ inl, itr1 -+ SUBQ $256, itr1 -+ SHRQ $4, itr1 -+ ADDQ $6, itr1 -+ MOVQ $10, itr2 -+ CMPQ itr1, $10 -+ CMOVQGT itr2, itr1 -+ MOVQ inp, inl -+ XORQ itr2, itr2 -+ -+ // Perform ChaCha rounds, while hashing the remaining input -+openAVX2Tail384LoopB: -+ polyAdd(0(inl)) -+ polyMulAVX2 -+ LEAQ 16(inl), inl -+ -+openAVX2Tail384LoopA: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ polyAdd(0(inl)) -+ polyMulAVX2 -+ LEAQ 16(inl), inl -+ INCQ itr2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ -+ CMPQ itr2, itr1 -+ JB openAVX2Tail384LoopB -+ -+ CMPQ itr2, $10 -+ JNE openAVX2Tail384LoopA -+ -+ MOVQ inl, itr2 -+ SUBQ inp, inl -+ MOVQ inl, itr1 -+ MOVQ tmpStoreAVX2, inl -+ -+openAVX2Tail384Hash: -+ ADDQ $16, itr1 -+ CMPQ itr1, inl -+ JGT openAVX2Tail384HashEnd -+ polyAdd(0(itr2)) -+ polyMulAVX2 -+ LEAQ 16(itr2), itr2 -+ JMP openAVX2Tail384Hash -+ -+// Store 256 bytes safely, then go to store loop -+openAVX2Tail384HashEnd: -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2 -+ VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3 -+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3 -+ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ LEAQ (8*32)(inp), inp -+ LEAQ (8*32)(oup), oup -+ SUBQ $8*32, inl -+ JMP openAVX2TailLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 512 bytes of ciphertext -+openAVX2Tail512: -+ VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ XORQ itr1, itr1 -+ MOVQ inp, itr2 -+ -+openAVX2Tail512LoopB: -+ polyAdd(0(itr2)) -+ polyMulAVX2 -+ LEAQ (2*8)(itr2), itr2 -+ -+openAVX2Tail512LoopA: -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyAdd(0*8(itr2)) -+ polyMulAVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(2*8(itr2)) -+ polyMulAVX2 -+ LEAQ (4*8)(itr2), itr2 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ INCQ itr1 -+ CMPQ itr1, $4 -+ JLT openAVX2Tail512LoopB -+ -+ CMPQ itr1, $10 -+ JNE openAVX2Tail512LoopA -+ -+ MOVQ inl, itr1 -+ SUBQ $384, itr1 -+ ANDQ $-16, itr1 -+ -+openAVX2Tail512HashLoop: -+ TESTQ itr1, itr1 -+ JE openAVX2Tail512HashEnd -+ polyAdd(0(itr2)) -+ polyMulAVX2 -+ LEAQ 16(itr2), itr2 -+ SUBQ $16, itr1 -+ JMP openAVX2Tail512HashLoop -+ -+openAVX2Tail512HashEnd: -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 -+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 -+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ -+ LEAQ (12*32)(inp), inp -+ LEAQ (12*32)(oup), oup -+ SUBQ $12*32, inl -+ -+ JMP openAVX2TailLoop -+ -+// ---------------------------------------------------------------------------- -+// ---------------------------------------------------------------------------- -+// func chacha20Poly1305Seal(dst, key, src, ad []byte) -+TEXT ·chacha20Poly1305Seal(SB), 0, $288-96 -+ // For aligned stack access -+ MOVQ SP, BP -+ ADDQ $32, BP -+ ANDQ $-32, BP -+ MOVQ dst+0(FP), oup -+ MOVQ key+24(FP), keyp -+ MOVQ src+48(FP), inp -+ MOVQ src_len+56(FP), inl -+ MOVQ ad+72(FP), adp -+ -+ CMPB ·useAVX2(SB), $1 -+ JE chacha20Poly1305Seal_AVX2 -+ -+ // Special optimization, for very short buffers -+ CMPQ inl, $128 -+ JBE sealSSE128 // About 15% faster -+ -+ // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration -+ MOVOU ·chacha20Constants<>(SB), A0 -+ MOVOU (1*16)(keyp), B0 -+ MOVOU (2*16)(keyp), C0 -+ MOVOU (3*16)(keyp), D0 -+ -+ // Store state on stack for future use -+ MOVO B0, state1Store -+ MOVO C0, state2Store -+ -+ // Load state, increment counter blocks -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ MOVQ $10, itr2 -+ -+sealSSEIntroLoop: -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ DECQ itr2 -+ JNE sealSSEIntroLoop -+ -+ // Add in the state -+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ -+ // Clamp and store the key -+ PAND ·polyClampMask<>(SB), A0 -+ MOVO A0, rStore -+ MOVO B0, sStore -+ -+ // Hash AAD -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 -+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 -+ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) -+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 -+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 -+ MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup) -+ -+ MOVQ $128, itr1 -+ SUBQ $128, inl -+ LEAQ 128(inp), inp -+ -+ MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1 -+ -+ CMPQ inl, $64 -+ JBE sealSSE128SealHash -+ -+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 -+ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 -+ MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup) -+ -+ ADDQ $64, itr1 -+ SUBQ $64, inl -+ LEAQ 64(inp), inp -+ -+ MOVQ $2, itr1 -+ MOVQ $8, itr2 -+ -+ CMPQ inl, $64 -+ JBE sealSSETail64 -+ CMPQ inl, $128 -+ JBE sealSSETail128 -+ CMPQ inl, $192 -+ JBE sealSSETail192 -+ -+sealSSEMainLoop: -+ // Load state, increment counter blocks -+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ -+sealSSEInnerLoop: -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyAdd(0(oup)) -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ polyMulStage1 -+ polyMulStage2 -+ LEAQ (2*8)(oup), oup -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ polyMulStage3 -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyMulReduceStage -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ DECQ itr2 -+ JGE sealSSEInnerLoop -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ (2*8)(oup), oup -+ DECQ itr1 -+ JG sealSSEInnerLoop -+ -+ // Add in the state -+ PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ MOVO D3, tmpStore -+ -+ // Load - xor - store -+ MOVOU (0*16)(inp), D3; PXOR D3, A0 -+ MOVOU (1*16)(inp), D3; PXOR D3, B0 -+ MOVOU (2*16)(inp), D3; PXOR D3, C0 -+ MOVOU (3*16)(inp), D3; PXOR D3, D0 -+ MOVOU A0, (0*16)(oup) -+ MOVOU B0, (1*16)(oup) -+ MOVOU C0, (2*16)(oup) -+ MOVOU D0, (3*16)(oup) -+ MOVO tmpStore, D3 -+ -+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 -+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 -+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 -+ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) -+ ADDQ $192, inp -+ MOVQ $192, itr1 -+ SUBQ $192, inl -+ MOVO A3, A1 -+ MOVO B3, B1 -+ MOVO C3, C1 -+ MOVO D3, D1 -+ CMPQ inl, $64 -+ JBE sealSSE128SealHash -+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 -+ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 -+ MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup) -+ LEAQ 64(inp), inp -+ SUBQ $64, inl -+ MOVQ $6, itr1 -+ MOVQ $4, itr2 -+ CMPQ inl, $192 -+ JG sealSSEMainLoop -+ -+ MOVQ inl, itr1 -+ TESTQ inl, inl -+ JE sealSSE128SealHash -+ MOVQ $6, itr1 -+ CMPQ inl, $64 -+ JBE sealSSETail64 -+ CMPQ inl, $128 -+ JBE sealSSETail128 -+ JMP sealSSETail192 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 64 bytes of plaintext -+sealSSETail64: -+ // Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes -+ MOVO ·chacha20Constants<>(SB), A1 -+ MOVO state1Store, B1 -+ MOVO state2Store, C1 -+ MOVO ctr3Store, D1 -+ PADDL ·sseIncMask<>(SB), D1 -+ MOVO D1, ctr0Store -+ -+sealSSETail64LoopA: -+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealSSETail64LoopB: -+ chachaQR(A1, B1, C1, D1, T1) -+ shiftB1Left; shiftC1Left; shiftD1Left -+ chachaQR(A1, B1, C1, D1, T1) -+ shiftB1Right; shiftC1Right; shiftD1Right -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+ DECQ itr1 -+ JG sealSSETail64LoopA -+ -+ DECQ itr2 -+ JGE sealSSETail64LoopB -+ PADDL ·chacha20Constants<>(SB), A1 -+ PADDL state1Store, B1 -+ PADDL state2Store, C1 -+ PADDL ctr0Store, D1 -+ -+ JMP sealSSE128Seal -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of plaintext -+sealSSETail128: -+ // Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes -+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store -+ -+sealSSETail128LoopA: -+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealSSETail128LoopB: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ -+ DECQ itr1 -+ JG sealSSETail128LoopA -+ -+ DECQ itr2 -+ JGE sealSSETail128LoopB -+ -+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 -+ PADDL state1Store, B0; PADDL state1Store, B1 -+ PADDL state2Store, C0; PADDL state2Store, C1 -+ PADDL ctr0Store, D0; PADDL ctr1Store, D1 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 -+ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) -+ -+ MOVQ $64, itr1 -+ LEAQ 64(inp), inp -+ SUBQ $64, inl -+ -+ JMP sealSSE128SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 192 bytes of plaintext -+sealSSETail192: -+ // Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes -+ MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr2Store -+ -+sealSSETail192LoopA: -+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealSSETail192LoopB: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ shiftB2Left; shiftC2Left; shiftD2Left -+ -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ shiftB2Right; shiftC2Right; shiftD2Right -+ -+ DECQ itr1 -+ JG sealSSETail192LoopA -+ -+ DECQ itr2 -+ JGE sealSSETail192LoopB -+ -+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 -+ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 -+ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 -+ PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 -+ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) -+ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 -+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ -+ MOVO A2, A1 -+ MOVO B2, B1 -+ MOVO C2, C1 -+ MOVO D2, D1 -+ MOVQ $128, itr1 -+ LEAQ 128(inp), inp -+ SUBQ $128, inl -+ -+ JMP sealSSE128SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special seal optimization for buffers smaller than 129 bytes -+sealSSE128: -+ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks -+ MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 -+ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 -+ MOVQ $10, itr2 -+ -+sealSSE128InnerCipherLoop: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftB1Left; shiftB2Left -+ shiftC0Left; shiftC1Left; shiftC2Left -+ shiftD0Left; shiftD1Left; shiftD2Left -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftB1Right; shiftB2Right -+ shiftC0Right; shiftC1Right; shiftC2Right -+ shiftD0Right; shiftD1Right; shiftD2Right -+ DECQ itr2 -+ JNE sealSSE128InnerCipherLoop -+ -+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded -+ PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 -+ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 -+ PADDL T2, C1; PADDL T2, C2 -+ PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 -+ PAND ·polyClampMask<>(SB), A0 -+ MOVOU A0, rStore -+ MOVOU B0, sStore -+ -+ // Hash -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ XORQ itr1, itr1 -+ -+sealSSE128SealHash: -+ // itr1 holds the number of bytes encrypted but not yet hashed -+ CMPQ itr1, $16 -+ JB sealSSE128Seal -+ polyAdd(0(oup)) -+ polyMul -+ -+ SUBQ $16, itr1 -+ ADDQ $16, oup -+ -+ JMP sealSSE128SealHash -+ -+sealSSE128Seal: -+ CMPQ inl, $16 -+ JB sealSSETail -+ SUBQ $16, inl -+ -+ // Load for decryption -+ MOVOU (inp), T0 -+ PXOR T0, A1 -+ MOVOU A1, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ -+ // Extract for hashing -+ MOVQ A1, t0 -+ PSRLDQ $8, A1 -+ MOVQ A1, t1 -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ -+ // Shift the stream "left" -+ MOVO B1, A1 -+ MOVO C1, B1 -+ MOVO D1, C1 -+ MOVO A2, D1 -+ MOVO B2, A2 -+ MOVO C2, B2 -+ MOVO D2, C2 -+ JMP sealSSE128Seal -+ -+sealSSETail: -+ TESTQ inl, inl -+ JE sealSSEFinalize -+ -+ // We can only load the PT one byte at a time to avoid read after end of buffer -+ MOVQ inl, itr2 -+ SHLQ $4, itr2 -+ LEAQ ·andMask<>(SB), t0 -+ MOVQ inl, itr1 -+ LEAQ -1(inp)(inl*1), inp -+ XORQ t2, t2 -+ XORQ t3, t3 -+ XORQ AX, AX -+ -+sealSSETailLoadLoop: -+ SHLQ $8, t2, t3 -+ SHLQ $8, t2 -+ MOVB (inp), AX -+ XORQ AX, t2 -+ LEAQ -1(inp), inp -+ DECQ itr1 -+ JNE sealSSETailLoadLoop -+ MOVQ t2, 0+tmpStore -+ MOVQ t3, 8+tmpStore -+ PXOR 0+tmpStore, A1 -+ MOVOU A1, (oup) -+ MOVOU -16(t0)(itr2*1), T0 -+ PAND T0, A1 -+ MOVQ A1, t0 -+ PSRLDQ $8, A1 -+ MOVQ A1, t1 -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ -+ ADDQ inl, oup -+ -+sealSSEFinalize: -+ // Hash in the buffer lengths -+ ADDQ ad_len+80(FP), acc0 -+ ADCQ src_len+56(FP), acc1 -+ ADCQ $1, acc2 -+ polyMul -+ -+ // Final reduce -+ MOVQ acc0, t0 -+ MOVQ acc1, t1 -+ MOVQ acc2, t2 -+ SUBQ $-5, acc0 -+ SBBQ $-1, acc1 -+ SBBQ $3, acc2 -+ CMOVQCS t0, acc0 -+ CMOVQCS t1, acc1 -+ CMOVQCS t2, acc2 -+ -+ // Add in the "s" part of the key -+ ADDQ 0+sStore, acc0 -+ ADCQ 8+sStore, acc1 -+ -+ // Finally store the tag at the end of the message -+ MOVQ acc0, (0*8)(oup) -+ MOVQ acc1, (1*8)(oup) -+ RET -+ -+// ---------------------------------------------------------------------------- -+// ------------------------- AVX2 Code ---------------------------------------- -+chacha20Poly1305Seal_AVX2: -+ VZEROUPPER -+ VMOVDQU ·chacha20Constants<>(SB), AA0 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 -+ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 -+ VPADDD ·avx2InitMask<>(SB), DD0, DD0 -+ -+ // Special optimizations, for very short buffers -+ CMPQ inl, $192 -+ JBE seal192AVX2 // 33% faster -+ CMPQ inl, $320 -+ JBE seal320AVX2 // 17% faster -+ -+ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream -+ VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2 -+ VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2 -+ VPADDD ·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2 -+ VPADDD ·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2 -+ VMOVDQA DD3, ctr3StoreAVX2 -+ MOVQ $10, itr2 -+ -+sealAVX2IntroLoop: -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 -+ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 -+ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 -+ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 -+ -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 -+ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 -+ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 -+ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 -+ DECQ itr2 -+ JNE sealAVX2IntroLoop -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ -+ VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127 -+ VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key -+ VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95 -+ -+ // Clamp and store poly key -+ VPAND ·polyClampMask<>(SB), DD0, DD0 -+ VMOVDQA DD0, rsStoreAVX2 -+ -+ // Hash AD -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+ // Can store at least 320 bytes -+ VPXOR (0*32)(inp), AA0, AA0 -+ VPXOR (1*32)(inp), CC0, CC0 -+ VMOVDQU AA0, (0*32)(oup) -+ VMOVDQU CC0, (1*32)(oup) -+ -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup) -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup) -+ -+ MOVQ $320, itr1 -+ SUBQ $320, inl -+ LEAQ 320(inp), inp -+ -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0 -+ CMPQ inl, $128 -+ JBE sealAVX2SealHash -+ -+ VPXOR (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup) -+ SUBQ $128, inl -+ LEAQ 128(inp), inp -+ -+ MOVQ $8, itr1 -+ MOVQ $2, itr2 -+ -+ CMPQ inl, $128 -+ JBE sealAVX2Tail128 -+ CMPQ inl, $256 -+ JBE sealAVX2Tail256 -+ CMPQ inl, $384 -+ JBE sealAVX2Tail384 -+ CMPQ inl, $512 -+ JBE sealAVX2Tail512 -+ -+ // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop -+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 -+ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 -+ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 -+ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 -+ -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 -+ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 -+ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 -+ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ -+ SUBQ $16, oup // Adjust the pointer -+ MOVQ $9, itr1 -+ JMP sealAVX2InternalLoopStart -+ -+sealAVX2MainLoop: -+ // Load state, increment counter blocks, store the incremented counters -+ VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ MOVQ $10, itr1 -+ -+sealAVX2InternalLoop: -+ polyAdd(0*8(oup)) -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage1_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ polyMulStage2_AVX2 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyMulStage3_AVX2 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ -+sealAVX2InternalLoopStart: -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ polyAdd(2*8(oup)) -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage1_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage2_AVX2 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage3_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ polyMulReduceStage -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(4*8(oup)) -+ LEAQ (6*8)(oup), oup -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage1_AVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ polyMulStage2_AVX2 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage3_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ DECQ itr1 -+ JNE sealAVX2InternalLoop -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ -+ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ LEAQ (4*8)(oup), oup -+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 -+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 -+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ -+ // and here -+ polyAdd(-2*8(oup)) -+ polyMulAVX2 -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) -+ LEAQ (32*16)(inp), inp -+ SUBQ $(32*16), inl -+ CMPQ inl, $512 -+ JG sealAVX2MainLoop -+ -+ // Tail can only hash 480 bytes -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ polyAdd(2*8(oup)) -+ polyMulAVX2 -+ LEAQ 32(oup), oup -+ -+ MOVQ $10, itr1 -+ MOVQ $0, itr2 -+ CMPQ inl, $128 -+ JBE sealAVX2Tail128 -+ CMPQ inl, $256 -+ JBE sealAVX2Tail256 -+ CMPQ inl, $384 -+ JBE sealAVX2Tail384 -+ JMP sealAVX2Tail512 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 193 bytes -+seal192AVX2: -+ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks -+ VMOVDQA AA0, AA1 -+ VMOVDQA BB0, BB1 -+ VMOVDQA CC0, CC1 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2 -+ VMOVDQA BB0, BB2 -+ VMOVDQA CC0, CC2 -+ VMOVDQA DD0, DD2 -+ VMOVDQA DD1, TT3 -+ MOVQ $10, itr2 -+ -+sealAVX2192InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ DECQ itr2 -+ JNE sealAVX2192InnerCipherLoop -+ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 -+ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 -+ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 -+ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ -+ // Clamp and store poly key -+ VPAND ·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 192 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ -+sealAVX2ShortSeal: -+ // Hash aad -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ XORQ itr1, itr1 -+ -+sealAVX2SealHash: -+ // itr1 holds the number of bytes encrypted but not yet hashed -+ CMPQ itr1, $16 -+ JB sealAVX2ShortSealLoop -+ polyAdd(0(oup)) -+ polyMul -+ SUBQ $16, itr1 -+ ADDQ $16, oup -+ JMP sealAVX2SealHash -+ -+sealAVX2ShortSealLoop: -+ CMPQ inl, $32 -+ JB sealAVX2ShortTail32 -+ SUBQ $32, inl -+ -+ // Load for encryption -+ VPXOR (inp), AA0, AA0 -+ VMOVDQU AA0, (oup) -+ LEAQ (1*32)(inp), inp -+ -+ // Now can hash -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ polyAdd(2*8(oup)) -+ polyMulAVX2 -+ LEAQ (1*32)(oup), oup -+ -+ // Shift stream left -+ VMOVDQA BB0, AA0 -+ VMOVDQA CC0, BB0 -+ VMOVDQA DD0, CC0 -+ VMOVDQA AA1, DD0 -+ VMOVDQA BB1, AA1 -+ VMOVDQA CC1, BB1 -+ VMOVDQA DD1, CC1 -+ VMOVDQA AA2, DD1 -+ VMOVDQA BB2, AA2 -+ JMP sealAVX2ShortSealLoop -+ -+sealAVX2ShortTail32: -+ CMPQ inl, $16 -+ VMOVDQA A0, A1 -+ JB sealAVX2ShortDone -+ -+ SUBQ $16, inl -+ -+ // Load for encryption -+ VPXOR (inp), A0, T0 -+ VMOVDQU T0, (oup) -+ LEAQ (1*16)(inp), inp -+ -+ // Hash -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ LEAQ (1*16)(oup), oup -+ VPERM2I128 $0x11, AA0, AA0, AA0 -+ VMOVDQA A0, A1 -+ -+sealAVX2ShortDone: -+ VZEROUPPER -+ JMP sealSSETail -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 321 bytes -+seal320AVX2: -+ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks -+ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 -+ MOVQ $10, itr2 -+ -+sealAVX2320InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ DECQ itr2 -+ JNE sealAVX2320InnerCipherLoop -+ -+ VMOVDQA ·chacha20Constants<>(SB), TT0 -+ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 -+ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 -+ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 -+ VMOVDQA ·avx2IncMask<>(SB), TT0 -+ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD2, DD2 -+ -+ // Clamp and store poly key -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPAND ·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 320 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ VPERM2I128 $0x02, AA2, BB2, CC1 -+ VPERM2I128 $0x02, CC2, DD2, DD1 -+ VPERM2I128 $0x13, AA2, BB2, AA2 -+ VPERM2I128 $0x13, CC2, DD2, BB2 -+ JMP sealAVX2ShortSeal -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of ciphertext -+sealAVX2Tail128: -+ // Need to decrypt up to 128 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA ·chacha20Constants<>(SB), AA0 -+ VMOVDQA state1StoreAVX2, BB0 -+ VMOVDQA state2StoreAVX2, CC0 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD0 -+ VMOVDQA DD0, DD1 -+ -+sealAVX2Tail128LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail128LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ polyAdd(0(oup)) -+ polyMul -+ VPALIGNR $4, BB0, BB0, BB0 -+ VPALIGNR $8, CC0, CC0, CC0 -+ VPALIGNR $12, DD0, DD0, DD0 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ polyAdd(16(oup)) -+ polyMul -+ LEAQ 32(oup), oup -+ VPALIGNR $12, BB0, BB0, BB0 -+ VPALIGNR $8, CC0, CC0, CC0 -+ VPALIGNR $4, DD0, DD0, DD0 -+ DECQ itr1 -+ JG sealAVX2Tail128LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail128LoopB -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA1 -+ VPADDD state1StoreAVX2, BB0, BB1 -+ VPADDD state2StoreAVX2, CC0, CC1 -+ VPADDD DD1, DD0, DD1 -+ -+ VPERM2I128 $0x02, AA1, BB1, AA0 -+ VPERM2I128 $0x02, CC1, DD1, BB0 -+ VPERM2I128 $0x13, AA1, BB1, CC0 -+ VPERM2I128 $0x13, CC1, DD1, DD0 -+ JMP sealAVX2ShortSealLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 256 bytes of ciphertext -+sealAVX2Tail256: -+ // Need to decrypt up to 256 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA ·chacha20Constants<>(SB), AA1 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA DD0, TT1 -+ VMOVDQA DD1, TT2 -+ -+sealAVX2Tail256LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail256LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ polyAdd(0(oup)) -+ polyMul -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ polyAdd(16(oup)) -+ polyMul -+ LEAQ 32(oup), oup -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ DECQ itr1 -+ JG sealAVX2Tail256LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail256LoopB -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 -+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPERM2I128 $0x02, CC0, DD0, TT1 -+ VPERM2I128 $0x13, AA0, BB0, TT2 -+ VPERM2I128 $0x13, CC0, DD0, TT3 -+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) -+ MOVQ $128, itr1 -+ LEAQ 128(inp), inp -+ SUBQ $128, inl -+ VPERM2I128 $0x02, AA1, BB1, AA0 -+ VPERM2I128 $0x02, CC1, DD1, BB0 -+ VPERM2I128 $0x13, AA1, BB1, CC0 -+ VPERM2I128 $0x13, CC1, DD1, DD0 -+ -+ JMP sealAVX2SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 384 bytes of ciphertext -+sealAVX2Tail384: -+ // Need to decrypt up to 384 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3 -+ -+sealAVX2Tail384LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail384LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ polyAdd(0(oup)) -+ polyMul -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ polyAdd(16(oup)) -+ polyMul -+ LEAQ 32(oup), oup -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ DECQ itr1 -+ JG sealAVX2Tail384LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail384LoopB -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 -+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPERM2I128 $0x02, CC0, DD0, TT1 -+ VPERM2I128 $0x13, AA0, BB0, TT2 -+ VPERM2I128 $0x13, CC0, DD0, TT3 -+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, TT0 -+ VPERM2I128 $0x02, CC1, DD1, TT1 -+ VPERM2I128 $0x13, AA1, BB1, TT2 -+ VPERM2I128 $0x13, CC1, DD1, TT3 -+ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) -+ MOVQ $256, itr1 -+ LEAQ 256(inp), inp -+ SUBQ $256, inl -+ VPERM2I128 $0x02, AA2, BB2, AA0 -+ VPERM2I128 $0x02, CC2, DD2, BB0 -+ VPERM2I128 $0x13, AA2, BB2, CC0 -+ VPERM2I128 $0x13, CC2, DD2, DD0 -+ -+ JMP sealAVX2SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 512 bytes of ciphertext -+sealAVX2Tail512: -+ // Need to decrypt up to 512 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ -+sealAVX2Tail512LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail512LoopB: -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(2*8(oup)) -+ polyMulAVX2 -+ LEAQ (4*8)(oup), oup -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ -+ DECQ itr1 -+ JG sealAVX2Tail512LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail512LoopB -+ -+ VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPERM2I128 $0x02, AA0, BB0, CC3 -+ VPXOR (0*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (0*32)(oup) -+ VPERM2I128 $0x02, CC0, DD0, CC3 -+ VPXOR (1*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (1*32)(oup) -+ VPERM2I128 $0x13, AA0, BB0, CC3 -+ VPXOR (2*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (2*32)(oup) -+ VPERM2I128 $0x13, CC0, DD0, CC3 -+ VPXOR (3*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (3*32)(oup) -+ -+ VPERM2I128 $0x02, AA1, BB1, AA0 -+ VPERM2I128 $0x02, CC1, DD1, BB0 -+ VPERM2I128 $0x13, AA1, BB1, CC0 -+ VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ -+ VPERM2I128 $0x02, AA2, BB2, AA0 -+ VPERM2I128 $0x02, CC2, DD2, BB0 -+ VPERM2I128 $0x13, AA2, BB2, CC0 -+ VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ -+ MOVQ $384, itr1 -+ LEAQ 384(inp), inp -+ SUBQ $384, inl -+ VPERM2I128 $0x02, AA3, BB3, AA0 -+ VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0 -+ VPERM2I128 $0x13, AA3, BB3, CC0 -+ VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ -+ JMP sealAVX2SealHash -diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go -new file mode 100644 -index 000000000000..96b2fd898bbc ---- /dev/null -+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go -@@ -0,0 +1,81 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20poly1305 -+ -+import ( -+ "encoding/binary" -+ -+ "golang.org/x/crypto/chacha20" -+ "golang.org/x/crypto/internal/poly1305" -+ "golang.org/x/crypto/internal/subtle" -+) -+ -+func writeWithPadding(p *poly1305.MAC, b []byte) { -+ p.Write(b) -+ if rem := len(b) % 16; rem != 0 { -+ var buf [16]byte -+ padLen := 16 - rem -+ p.Write(buf[:padLen]) -+ } -+} -+ -+func writeUint64(p *poly1305.MAC, n int) { -+ var buf [8]byte -+ binary.LittleEndian.PutUint64(buf[:], uint64(n)) -+ p.Write(buf[:]) -+} -+ -+func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte { -+ ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) -+ ciphertext, tag := out[:len(plaintext)], out[len(plaintext):] -+ if subtle.InexactOverlap(out, plaintext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ -+ var polyKey [32]byte -+ s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) -+ s.XORKeyStream(polyKey[:], polyKey[:]) -+ s.SetCounter(1) // set the counter to 1, skipping 32 bytes -+ s.XORKeyStream(ciphertext, plaintext) -+ -+ p := poly1305.New(&polyKey) -+ writeWithPadding(p, additionalData) -+ writeWithPadding(p, ciphertext) -+ writeUint64(p, len(additionalData)) -+ writeUint64(p, len(plaintext)) -+ p.Sum(tag[:0]) -+ -+ return ret -+} -+ -+func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ tag := ciphertext[len(ciphertext)-16:] -+ ciphertext = ciphertext[:len(ciphertext)-16] -+ -+ var polyKey [32]byte -+ s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) -+ s.XORKeyStream(polyKey[:], polyKey[:]) -+ s.SetCounter(1) // set the counter to 1, skipping 32 bytes -+ -+ p := poly1305.New(&polyKey) -+ writeWithPadding(p, additionalData) -+ writeWithPadding(p, ciphertext) -+ writeUint64(p, len(additionalData)) -+ writeUint64(p, len(ciphertext)) -+ -+ ret, out := sliceForAppend(dst, len(ciphertext)) -+ if subtle.InexactOverlap(out, ciphertext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ if !p.Verify(tag) { -+ for i := range out { -+ out[i] = 0 -+ } -+ return nil, errOpen -+ } -+ -+ s.XORKeyStream(out, ciphertext) -+ return ret, nil -+} -diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go -new file mode 100644 -index 000000000000..f832b33d45f2 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go -@@ -0,0 +1,16 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || !gc || purego -+// +build !amd64 !gc purego -+ -+package chacha20poly1305 -+ -+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ return c.sealGeneric(dst, nonce, plaintext, additionalData) -+} -+ -+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ return c.openGeneric(dst, nonce, ciphertext, additionalData) -+} -diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go -new file mode 100644 -index 000000000000..1cebfe946f44 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go -@@ -0,0 +1,86 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20poly1305 -+ -+import ( -+ "crypto/cipher" -+ "errors" -+ -+ "golang.org/x/crypto/chacha20" -+) -+ -+type xchacha20poly1305 struct { -+ key [KeySize]byte -+} -+ -+// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key. -+// -+// XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce, -+// suitable to be generated randomly without risk of collisions. It should be -+// preferred when nonce uniqueness cannot be trivially ensured, or whenever -+// nonces are randomly generated. -+func NewX(key []byte) (cipher.AEAD, error) { -+ if len(key) != KeySize { -+ return nil, errors.New("chacha20poly1305: bad key length") -+ } -+ ret := new(xchacha20poly1305) -+ copy(ret.key[:], key) -+ return ret, nil -+} -+ -+func (*xchacha20poly1305) NonceSize() int { -+ return NonceSizeX -+} -+ -+func (*xchacha20poly1305) Overhead() int { -+ return Overhead -+} -+ -+func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ if len(nonce) != NonceSizeX { -+ panic("chacha20poly1305: bad nonce length passed to Seal") -+ } -+ -+ // XChaCha20-Poly1305 technically supports a 64-bit counter, so there is no -+ // size limit. However, since we reuse the ChaCha20-Poly1305 implementation, -+ // the second half of the counter is not available. This is unlikely to be -+ // an issue because the cipher.AEAD API requires the entire message to be in -+ // memory, and the counter overflows at 256 GB. -+ if uint64(len(plaintext)) > (1<<38)-64 { -+ panic("chacha20poly1305: plaintext too large") -+ } -+ -+ c := new(chacha20poly1305) -+ hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) -+ copy(c.key[:], hKey) -+ -+ // The first 4 bytes of the final nonce are unused counter space. -+ cNonce := make([]byte, NonceSize) -+ copy(cNonce[4:12], nonce[16:24]) -+ -+ return c.seal(dst, cNonce[:], plaintext, additionalData) -+} -+ -+func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ if len(nonce) != NonceSizeX { -+ panic("chacha20poly1305: bad nonce length passed to Open") -+ } -+ if len(ciphertext) < 16 { -+ return nil, errOpen -+ } -+ if uint64(len(ciphertext)) > (1<<38)-48 { -+ panic("chacha20poly1305: ciphertext too large") -+ } -+ -+ c := new(chacha20poly1305) -+ hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) -+ copy(c.key[:], hKey) -+ -+ // The first 4 bytes of the final nonce are unused counter space. -+ cNonce := make([]byte, NonceSize) -+ copy(cNonce[4:12], nonce[16:24]) -+ -+ return c.open(dst, cNonce[:], ciphertext, additionalData) -+} -diff --git a/vendor/golang.org/x/crypto/codereview.cfg b/vendor/golang.org/x/crypto/codereview.cfg -new file mode 100644 -index 000000000000..3f8b14b64e83 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/codereview.cfg -@@ -0,0 +1 @@ -+issuerepo: golang/go -diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go -index d3596ee66fdb..3a1674a1e57c 100644 ---- a/vendor/golang.org/x/crypto/cryptobyte/asn1.go -+++ b/vendor/golang.org/x/crypto/cryptobyte/asn1.go -@@ -117,6 +117,19 @@ func (b *Builder) AddASN1GeneralizedTime(t time.Time) { - }) - } - -+// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime. -+func (b *Builder) AddASN1UTCTime(t time.Time) { -+ b.AddASN1(asn1.UTCTime, func(c *Builder) { -+ // As utilized by the X.509 profile, UTCTime can only -+ // represent the years 1950 through 2049. -+ if t.Year() < 1950 || t.Year() >= 2050 { -+ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t) -+ return -+ } -+ c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr))) -+ }) -+} -+ - // AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not - // support BIT STRINGs that are not a whole number of bytes. - func (b *Builder) AddASN1BitString(data []byte) { -@@ -394,7 +407,12 @@ func (s *String) ReadASN1Enum(out *int) bool { - func (s *String) readBase128Int(out *int) bool { - ret := 0 - for i := 0; len(*s) > 0; i++ { -- if i == 4 { -+ if i == 5 { -+ return false -+ } -+ // Avoid overflowing int on a 32-bit platform. -+ // We don't want different behavior based on the architecture. -+ if ret >= 1<<(31-7) { - return false - } - ret <<= 7 -@@ -466,6 +484,45 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { - return true - } - -+const defaultUTCTimeFormatStr = "060102150405Z0700" -+ -+// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances. -+// It reports whether the read was successful. -+func (s *String) ReadASN1UTCTime(out *time.Time) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.UTCTime) { -+ return false -+ } -+ t := string(bytes) -+ -+ formatStr := defaultUTCTimeFormatStr -+ var err error -+ res, err := time.Parse(formatStr, t) -+ if err != nil { -+ // Fallback to minute precision if we can't parse second -+ // precision. If we are following X.509 or X.690 we shouldn't -+ // support this, but we do. -+ formatStr = "0601021504Z0700" -+ res, err = time.Parse(formatStr, t) -+ } -+ if err != nil { -+ return false -+ } -+ -+ if serialized := res.Format(formatStr); serialized != t { -+ return false -+ } -+ -+ if res.Year() >= 2050 { -+ // UTCTime interprets the low order digits 50-99 as 1950-99. -+ // This only applies to its use in the X.509 profile. -+ // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 -+ res = res.AddDate(-100, 0, 0) -+ } -+ *out = res -+ return true -+} -+ - // ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. - // It reports whether the read was successful. - func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { -diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go -index 4b9a655d1b56..cda3fdd3540d 100644 ---- a/vendor/golang.org/x/crypto/curve25519/curve25519.go -+++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go -@@ -10,6 +10,8 @@ package curve25519 // import "golang.org/x/crypto/curve25519" - import ( - "crypto/subtle" - "fmt" -+ -+ "golang.org/x/crypto/curve25519/internal/field" - ) - - // ScalarMult sets dst to the product scalar * point. -@@ -18,7 +20,55 @@ import ( - // zeroes, irrespective of the scalar. Instead, use the X25519 function, which - // will return an error. - func ScalarMult(dst, scalar, point *[32]byte) { -- scalarMult(dst, scalar, point) -+ var e [32]byte -+ -+ copy(e[:], scalar[:]) -+ e[0] &= 248 -+ e[31] &= 127 -+ e[31] |= 64 -+ -+ var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element -+ x1.SetBytes(point[:]) -+ x2.One() -+ x3.Set(&x1) -+ z3.One() -+ -+ swap := 0 -+ for pos := 254; pos >= 0; pos-- { -+ b := e[pos/8] >> uint(pos&7) -+ b &= 1 -+ swap ^= int(b) -+ x2.Swap(&x3, swap) -+ z2.Swap(&z3, swap) -+ swap = int(b) -+ -+ tmp0.Subtract(&x3, &z3) -+ tmp1.Subtract(&x2, &z2) -+ x2.Add(&x2, &z2) -+ z2.Add(&x3, &z3) -+ z3.Multiply(&tmp0, &x2) -+ z2.Multiply(&z2, &tmp1) -+ tmp0.Square(&tmp1) -+ tmp1.Square(&x2) -+ x3.Add(&z3, &z2) -+ z2.Subtract(&z3, &z2) -+ x2.Multiply(&tmp1, &tmp0) -+ tmp1.Subtract(&tmp1, &tmp0) -+ z2.Square(&z2) -+ -+ z3.Mult32(&tmp1, 121666) -+ x3.Square(&x3) -+ tmp0.Add(&tmp0, &z3) -+ z3.Multiply(&x1, &z2) -+ z2.Multiply(&tmp1, &tmp0) -+ } -+ -+ x2.Swap(&x3, swap) -+ z2.Swap(&z3, swap) -+ -+ z2.Invert(&z2) -+ x2.Multiply(&x2, &z2) -+ copy(dst[:], x2.Bytes()) - } - - // ScalarBaseMult sets dst to the product scalar * base where base is the -diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go -deleted file mode 100644 -index 5120b779b9b4..000000000000 ---- a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go -+++ /dev/null -@@ -1,240 +0,0 @@ --// Copyright 2012 The Go Authors. All rights reserved. --// Use of this source code is governed by a BSD-style --// license that can be found in the LICENSE file. -- --// +build amd64,!gccgo,!appengine,!purego -- --package curve25519 -- --// These functions are implemented in the .s files. The names of the functions --// in the rest of the file are also taken from the SUPERCOP sources to help --// people following along. -- --//go:noescape -- --func cswap(inout *[5]uint64, v uint64) -- --//go:noescape -- --func ladderstep(inout *[5][5]uint64) -- --//go:noescape -- --func freeze(inout *[5]uint64) -- --//go:noescape -- --func mul(dest, a, b *[5]uint64) -- --//go:noescape -- --func square(out, in *[5]uint64) -- --// mladder uses a Montgomery ladder to calculate (xr/zr) *= s. --func mladder(xr, zr *[5]uint64, s *[32]byte) { -- var work [5][5]uint64 -- -- work[0] = *xr -- setint(&work[1], 1) -- setint(&work[2], 0) -- work[3] = *xr -- setint(&work[4], 1) -- -- j := uint(6) -- var prevbit byte -- -- for i := 31; i >= 0; i-- { -- for j < 8 { -- bit := ((*s)[i] >> j) & 1 -- swap := bit ^ prevbit -- prevbit = bit -- cswap(&work[1], uint64(swap)) -- ladderstep(&work) -- j-- -- } -- j = 7 -- } -- -- *xr = work[1] -- *zr = work[2] --} -- --func scalarMult(out, in, base *[32]byte) { -- var e [32]byte -- copy(e[:], (*in)[:]) -- e[0] &= 248 -- e[31] &= 127 -- e[31] |= 64 -- -- var t, z [5]uint64 -- unpack(&t, base) -- mladder(&t, &z, &e) -- invert(&z, &z) -- mul(&t, &t, &z) -- pack(out, &t) --} -- --func setint(r *[5]uint64, v uint64) { -- r[0] = v -- r[1] = 0 -- r[2] = 0 -- r[3] = 0 -- r[4] = 0 --} -- --// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian --// order. --func unpack(r *[5]uint64, x *[32]byte) { -- r[0] = uint64(x[0]) | -- uint64(x[1])<<8 | -- uint64(x[2])<<16 | -- uint64(x[3])<<24 | -- uint64(x[4])<<32 | -- uint64(x[5])<<40 | -- uint64(x[6]&7)<<48 -- -- r[1] = uint64(x[6])>>3 | -- uint64(x[7])<<5 | -- uint64(x[8])<<13 | -- uint64(x[9])<<21 | -- uint64(x[10])<<29 | -- uint64(x[11])<<37 | -- uint64(x[12]&63)<<45 -- -- r[2] = uint64(x[12])>>6 | -- uint64(x[13])<<2 | -- uint64(x[14])<<10 | -- uint64(x[15])<<18 | -- uint64(x[16])<<26 | -- uint64(x[17])<<34 | -- uint64(x[18])<<42 | -- uint64(x[19]&1)<<50 -- -- r[3] = uint64(x[19])>>1 | -- uint64(x[20])<<7 | -- uint64(x[21])<<15 | -- uint64(x[22])<<23 | -- uint64(x[23])<<31 | -- uint64(x[24])<<39 | -- uint64(x[25]&15)<<47 -- -- r[4] = uint64(x[25])>>4 | -- uint64(x[26])<<4 | -- uint64(x[27])<<12 | -- uint64(x[28])<<20 | -- uint64(x[29])<<28 | -- uint64(x[30])<<36 | -- uint64(x[31]&127)<<44 --} -- --// pack sets out = x where out is the usual, little-endian form of the 5, --// 51-bit limbs in x. --func pack(out *[32]byte, x *[5]uint64) { -- t := *x -- freeze(&t) -- -- out[0] = byte(t[0]) -- out[1] = byte(t[0] >> 8) -- out[2] = byte(t[0] >> 16) -- out[3] = byte(t[0] >> 24) -- out[4] = byte(t[0] >> 32) -- out[5] = byte(t[0] >> 40) -- out[6] = byte(t[0] >> 48) -- -- out[6] ^= byte(t[1]<<3) & 0xf8 -- out[7] = byte(t[1] >> 5) -- out[8] = byte(t[1] >> 13) -- out[9] = byte(t[1] >> 21) -- out[10] = byte(t[1] >> 29) -- out[11] = byte(t[1] >> 37) -- out[12] = byte(t[1] >> 45) -- -- out[12] ^= byte(t[2]<<6) & 0xc0 -- out[13] = byte(t[2] >> 2) -- out[14] = byte(t[2] >> 10) -- out[15] = byte(t[2] >> 18) -- out[16] = byte(t[2] >> 26) -- out[17] = byte(t[2] >> 34) -- out[18] = byte(t[2] >> 42) -- out[19] = byte(t[2] >> 50) -- -- out[19] ^= byte(t[3]<<1) & 0xfe -- out[20] = byte(t[3] >> 7) -- out[21] = byte(t[3] >> 15) -- out[22] = byte(t[3] >> 23) -- out[23] = byte(t[3] >> 31) -- out[24] = byte(t[3] >> 39) -- out[25] = byte(t[3] >> 47) -- -- out[25] ^= byte(t[4]<<4) & 0xf0 -- out[26] = byte(t[4] >> 4) -- out[27] = byte(t[4] >> 12) -- out[28] = byte(t[4] >> 20) -- out[29] = byte(t[4] >> 28) -- out[30] = byte(t[4] >> 36) -- out[31] = byte(t[4] >> 44) --} -- --// invert calculates r = x^-1 mod p using Fermat's little theorem. --func invert(r *[5]uint64, x *[5]uint64) { -- var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 -- -- square(&z2, x) /* 2 */ -- square(&t, &z2) /* 4 */ -- square(&t, &t) /* 8 */ -- mul(&z9, &t, x) /* 9 */ -- mul(&z11, &z9, &z2) /* 11 */ -- square(&t, &z11) /* 22 */ -- mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ -- -- square(&t, &z2_5_0) /* 2^6 - 2^1 */ -- for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ -- square(&t, &t) -- } -- mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ -- -- square(&t, &z2_10_0) /* 2^11 - 2^1 */ -- for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ -- square(&t, &t) -- } -- mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ -- -- square(&t, &z2_20_0) /* 2^21 - 2^1 */ -- for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ -- square(&t, &t) -- } -- mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ -- -- square(&t, &t) /* 2^41 - 2^1 */ -- for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ -- square(&t, &t) -- } -- mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ -- -- square(&t, &z2_50_0) /* 2^51 - 2^1 */ -- for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ -- square(&t, &t) -- } -- mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ -- -- square(&t, &z2_100_0) /* 2^101 - 2^1 */ -- for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ -- square(&t, &t) -- } -- mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ -- -- square(&t, &t) /* 2^201 - 2^1 */ -- for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ -- square(&t, &t) -- } -- mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ -- -- square(&t, &t) /* 2^251 - 2^1 */ -- square(&t, &t) /* 2^252 - 2^2 */ -- square(&t, &t) /* 2^253 - 2^3 */ -- -- square(&t, &t) /* 2^254 - 2^4 */ -- -- square(&t, &t) /* 2^255 - 2^5 */ -- mul(r, &t, &z11) /* 2^255 - 21 */ --} -diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s -deleted file mode 100644 -index 0250c8885929..000000000000 ---- a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s -+++ /dev/null -@@ -1,1793 +0,0 @@ --// Copyright 2012 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. -- --// This code was translated into a form compatible with 6a from the public --// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html -- --// +build amd64,!gccgo,!appengine,!purego -- --#define REDMASK51 0x0007FFFFFFFFFFFF -- --// These constants cannot be encoded in non-MOVQ immediates. --// We access them directly from memory instead. -- --DATA ·_121666_213(SB)/8, $996687872 --GLOBL ·_121666_213(SB), 8, $8 -- --DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA --GLOBL ·_2P0(SB), 8, $8 -- --DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE --GLOBL ·_2P1234(SB), 8, $8 -- --// func freeze(inout *[5]uint64) --TEXT ·freeze(SB),7,$0-8 -- MOVQ inout+0(FP), DI -- -- MOVQ 0(DI),SI -- MOVQ 8(DI),DX -- MOVQ 16(DI),CX -- MOVQ 24(DI),R8 -- MOVQ 32(DI),R9 -- MOVQ $REDMASK51,AX -- MOVQ AX,R10 -- SUBQ $18,R10 -- MOVQ $3,R11 --REDUCELOOP: -- MOVQ SI,R12 -- SHRQ $51,R12 -- ANDQ AX,SI -- ADDQ R12,DX -- MOVQ DX,R12 -- SHRQ $51,R12 -- ANDQ AX,DX -- ADDQ R12,CX -- MOVQ CX,R12 -- SHRQ $51,R12 -- ANDQ AX,CX -- ADDQ R12,R8 -- MOVQ R8,R12 -- SHRQ $51,R12 -- ANDQ AX,R8 -- ADDQ R12,R9 -- MOVQ R9,R12 -- SHRQ $51,R12 -- ANDQ AX,R9 -- IMUL3Q $19,R12,R12 -- ADDQ R12,SI -- SUBQ $1,R11 -- JA REDUCELOOP -- MOVQ $1,R12 -- CMPQ R10,SI -- CMOVQLT R11,R12 -- CMPQ AX,DX -- CMOVQNE R11,R12 -- CMPQ AX,CX -- CMOVQNE R11,R12 -- CMPQ AX,R8 -- CMOVQNE R11,R12 -- CMPQ AX,R9 -- CMOVQNE R11,R12 -- NEGQ R12 -- ANDQ R12,AX -- ANDQ R12,R10 -- SUBQ R10,SI -- SUBQ AX,DX -- SUBQ AX,CX -- SUBQ AX,R8 -- SUBQ AX,R9 -- MOVQ SI,0(DI) -- MOVQ DX,8(DI) -- MOVQ CX,16(DI) -- MOVQ R8,24(DI) -- MOVQ R9,32(DI) -- RET -- --// func ladderstep(inout *[5][5]uint64) --TEXT ·ladderstep(SB),0,$296-8 -- MOVQ inout+0(FP),DI -- -- MOVQ 40(DI),SI -- MOVQ 48(DI),DX -- MOVQ 56(DI),CX -- MOVQ 64(DI),R8 -- MOVQ 72(DI),R9 -- MOVQ SI,AX -- MOVQ DX,R10 -- MOVQ CX,R11 -- MOVQ R8,R12 -- MOVQ R9,R13 -- ADDQ ·_2P0(SB),AX -- ADDQ ·_2P1234(SB),R10 -- ADDQ ·_2P1234(SB),R11 -- ADDQ ·_2P1234(SB),R12 -- ADDQ ·_2P1234(SB),R13 -- ADDQ 80(DI),SI -- ADDQ 88(DI),DX -- ADDQ 96(DI),CX -- ADDQ 104(DI),R8 -- ADDQ 112(DI),R9 -- SUBQ 80(DI),AX -- SUBQ 88(DI),R10 -- SUBQ 96(DI),R11 -- SUBQ 104(DI),R12 -- SUBQ 112(DI),R13 -- MOVQ SI,0(SP) -- MOVQ DX,8(SP) -- MOVQ CX,16(SP) -- MOVQ R8,24(SP) -- MOVQ R9,32(SP) -- MOVQ AX,40(SP) -- MOVQ R10,48(SP) -- MOVQ R11,56(SP) -- MOVQ R12,64(SP) -- MOVQ R13,72(SP) -- MOVQ 40(SP),AX -- MULQ 40(SP) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 40(SP),AX -- SHLQ $1,AX -- MULQ 48(SP) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 40(SP),AX -- SHLQ $1,AX -- MULQ 56(SP) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 40(SP),AX -- SHLQ $1,AX -- MULQ 64(SP) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 40(SP),AX -- SHLQ $1,AX -- MULQ 72(SP) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 48(SP),AX -- MULQ 48(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 48(SP),AX -- SHLQ $1,AX -- MULQ 56(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 48(SP),AX -- SHLQ $1,AX -- MULQ 64(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 48(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 72(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 56(SP),AX -- MULQ 56(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 56(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 64(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 56(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 72(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 64(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 64(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 64(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 72(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 72(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 72(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- ANDQ DX,SI -- MOVQ CX,R8 -- SHRQ $51,CX -- ADDQ R10,CX -- ANDQ DX,R8 -- MOVQ CX,R9 -- SHRQ $51,CX -- ADDQ R12,CX -- ANDQ DX,R9 -- MOVQ CX,AX -- SHRQ $51,CX -- ADDQ R14,CX -- ANDQ DX,AX -- MOVQ CX,R10 -- SHRQ $51,CX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,80(SP) -- MOVQ R8,88(SP) -- MOVQ R9,96(SP) -- MOVQ AX,104(SP) -- MOVQ R10,112(SP) -- MOVQ 0(SP),AX -- MULQ 0(SP) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 0(SP),AX -- SHLQ $1,AX -- MULQ 8(SP) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 0(SP),AX -- SHLQ $1,AX -- MULQ 16(SP) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 0(SP),AX -- SHLQ $1,AX -- MULQ 24(SP) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 0(SP),AX -- SHLQ $1,AX -- MULQ 32(SP) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 8(SP),AX -- MULQ 8(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 8(SP),AX -- SHLQ $1,AX -- MULQ 16(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 8(SP),AX -- SHLQ $1,AX -- MULQ 24(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 8(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 32(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 16(SP),AX -- MULQ 16(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 16(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 24(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 16(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 32(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 24(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 24(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 24(SP),DX -- IMUL3Q $38,DX,AX -- MULQ 32(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 32(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 32(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- ANDQ DX,SI -- MOVQ CX,R8 -- SHRQ $51,CX -- ADDQ R10,CX -- ANDQ DX,R8 -- MOVQ CX,R9 -- SHRQ $51,CX -- ADDQ R12,CX -- ANDQ DX,R9 -- MOVQ CX,AX -- SHRQ $51,CX -- ADDQ R14,CX -- ANDQ DX,AX -- MOVQ CX,R10 -- SHRQ $51,CX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,120(SP) -- MOVQ R8,128(SP) -- MOVQ R9,136(SP) -- MOVQ AX,144(SP) -- MOVQ R10,152(SP) -- MOVQ SI,SI -- MOVQ R8,DX -- MOVQ R9,CX -- MOVQ AX,R8 -- MOVQ R10,R9 -- ADDQ ·_2P0(SB),SI -- ADDQ ·_2P1234(SB),DX -- ADDQ ·_2P1234(SB),CX -- ADDQ ·_2P1234(SB),R8 -- ADDQ ·_2P1234(SB),R9 -- SUBQ 80(SP),SI -- SUBQ 88(SP),DX -- SUBQ 96(SP),CX -- SUBQ 104(SP),R8 -- SUBQ 112(SP),R9 -- MOVQ SI,160(SP) -- MOVQ DX,168(SP) -- MOVQ CX,176(SP) -- MOVQ R8,184(SP) -- MOVQ R9,192(SP) -- MOVQ 120(DI),SI -- MOVQ 128(DI),DX -- MOVQ 136(DI),CX -- MOVQ 144(DI),R8 -- MOVQ 152(DI),R9 -- MOVQ SI,AX -- MOVQ DX,R10 -- MOVQ CX,R11 -- MOVQ R8,R12 -- MOVQ R9,R13 -- ADDQ ·_2P0(SB),AX -- ADDQ ·_2P1234(SB),R10 -- ADDQ ·_2P1234(SB),R11 -- ADDQ ·_2P1234(SB),R12 -- ADDQ ·_2P1234(SB),R13 -- ADDQ 160(DI),SI -- ADDQ 168(DI),DX -- ADDQ 176(DI),CX -- ADDQ 184(DI),R8 -- ADDQ 192(DI),R9 -- SUBQ 160(DI),AX -- SUBQ 168(DI),R10 -- SUBQ 176(DI),R11 -- SUBQ 184(DI),R12 -- SUBQ 192(DI),R13 -- MOVQ SI,200(SP) -- MOVQ DX,208(SP) -- MOVQ CX,216(SP) -- MOVQ R8,224(SP) -- MOVQ R9,232(SP) -- MOVQ AX,240(SP) -- MOVQ R10,248(SP) -- MOVQ R11,256(SP) -- MOVQ R12,264(SP) -- MOVQ R13,272(SP) -- MOVQ 224(SP),SI -- IMUL3Q $19,SI,AX -- MOVQ AX,280(SP) -- MULQ 56(SP) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 232(SP),DX -- IMUL3Q $19,DX,AX -- MOVQ AX,288(SP) -- MULQ 48(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 200(SP),AX -- MULQ 40(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 200(SP),AX -- MULQ 48(SP) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 200(SP),AX -- MULQ 56(SP) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 200(SP),AX -- MULQ 64(SP) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 200(SP),AX -- MULQ 72(SP) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 208(SP),AX -- MULQ 40(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 208(SP),AX -- MULQ 48(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 208(SP),AX -- MULQ 56(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 208(SP),AX -- MULQ 64(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 208(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 72(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 216(SP),AX -- MULQ 40(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 216(SP),AX -- MULQ 48(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 216(SP),AX -- MULQ 56(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 216(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 64(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 216(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 72(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 224(SP),AX -- MULQ 40(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 224(SP),AX -- MULQ 48(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 280(SP),AX -- MULQ 64(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 280(SP),AX -- MULQ 72(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 232(SP),AX -- MULQ 40(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 288(SP),AX -- MULQ 56(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 288(SP),AX -- MULQ 64(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 288(SP),AX -- MULQ 72(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- MOVQ CX,R8 -- SHRQ $51,CX -- ANDQ DX,SI -- ADDQ R10,CX -- MOVQ CX,R9 -- SHRQ $51,CX -- ANDQ DX,R8 -- ADDQ R12,CX -- MOVQ CX,AX -- SHRQ $51,CX -- ANDQ DX,R9 -- ADDQ R14,CX -- MOVQ CX,R10 -- SHRQ $51,CX -- ANDQ DX,AX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,40(SP) -- MOVQ R8,48(SP) -- MOVQ R9,56(SP) -- MOVQ AX,64(SP) -- MOVQ R10,72(SP) -- MOVQ 264(SP),SI -- IMUL3Q $19,SI,AX -- MOVQ AX,200(SP) -- MULQ 16(SP) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 272(SP),DX -- IMUL3Q $19,DX,AX -- MOVQ AX,208(SP) -- MULQ 8(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 240(SP),AX -- MULQ 0(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 240(SP),AX -- MULQ 8(SP) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 240(SP),AX -- MULQ 16(SP) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 240(SP),AX -- MULQ 24(SP) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 240(SP),AX -- MULQ 32(SP) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 248(SP),AX -- MULQ 0(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 248(SP),AX -- MULQ 8(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 248(SP),AX -- MULQ 16(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 248(SP),AX -- MULQ 24(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 248(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 32(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 256(SP),AX -- MULQ 0(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 256(SP),AX -- MULQ 8(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 256(SP),AX -- MULQ 16(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 256(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 24(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 256(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 32(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 264(SP),AX -- MULQ 0(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 264(SP),AX -- MULQ 8(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 200(SP),AX -- MULQ 24(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 200(SP),AX -- MULQ 32(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 272(SP),AX -- MULQ 0(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 208(SP),AX -- MULQ 16(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 208(SP),AX -- MULQ 24(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 208(SP),AX -- MULQ 32(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- MOVQ CX,R8 -- SHRQ $51,CX -- ANDQ DX,SI -- ADDQ R10,CX -- MOVQ CX,R9 -- SHRQ $51,CX -- ANDQ DX,R8 -- ADDQ R12,CX -- MOVQ CX,AX -- SHRQ $51,CX -- ANDQ DX,R9 -- ADDQ R14,CX -- MOVQ CX,R10 -- SHRQ $51,CX -- ANDQ DX,AX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,DX -- MOVQ R8,CX -- MOVQ R9,R11 -- MOVQ AX,R12 -- MOVQ R10,R13 -- ADDQ ·_2P0(SB),DX -- ADDQ ·_2P1234(SB),CX -- ADDQ ·_2P1234(SB),R11 -- ADDQ ·_2P1234(SB),R12 -- ADDQ ·_2P1234(SB),R13 -- ADDQ 40(SP),SI -- ADDQ 48(SP),R8 -- ADDQ 56(SP),R9 -- ADDQ 64(SP),AX -- ADDQ 72(SP),R10 -- SUBQ 40(SP),DX -- SUBQ 48(SP),CX -- SUBQ 56(SP),R11 -- SUBQ 64(SP),R12 -- SUBQ 72(SP),R13 -- MOVQ SI,120(DI) -- MOVQ R8,128(DI) -- MOVQ R9,136(DI) -- MOVQ AX,144(DI) -- MOVQ R10,152(DI) -- MOVQ DX,160(DI) -- MOVQ CX,168(DI) -- MOVQ R11,176(DI) -- MOVQ R12,184(DI) -- MOVQ R13,192(DI) -- MOVQ 120(DI),AX -- MULQ 120(DI) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 120(DI),AX -- SHLQ $1,AX -- MULQ 128(DI) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 120(DI),AX -- SHLQ $1,AX -- MULQ 136(DI) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 120(DI),AX -- SHLQ $1,AX -- MULQ 144(DI) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 120(DI),AX -- SHLQ $1,AX -- MULQ 152(DI) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 128(DI),AX -- MULQ 128(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 128(DI),AX -- SHLQ $1,AX -- MULQ 136(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 128(DI),AX -- SHLQ $1,AX -- MULQ 144(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 128(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 152(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 136(DI),AX -- MULQ 136(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 136(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 144(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 136(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 152(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 144(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 144(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 144(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 152(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 152(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 152(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- ANDQ DX,SI -- MOVQ CX,R8 -- SHRQ $51,CX -- ADDQ R10,CX -- ANDQ DX,R8 -- MOVQ CX,R9 -- SHRQ $51,CX -- ADDQ R12,CX -- ANDQ DX,R9 -- MOVQ CX,AX -- SHRQ $51,CX -- ADDQ R14,CX -- ANDQ DX,AX -- MOVQ CX,R10 -- SHRQ $51,CX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,120(DI) -- MOVQ R8,128(DI) -- MOVQ R9,136(DI) -- MOVQ AX,144(DI) -- MOVQ R10,152(DI) -- MOVQ 160(DI),AX -- MULQ 160(DI) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 160(DI),AX -- SHLQ $1,AX -- MULQ 168(DI) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 160(DI),AX -- SHLQ $1,AX -- MULQ 176(DI) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 160(DI),AX -- SHLQ $1,AX -- MULQ 184(DI) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 160(DI),AX -- SHLQ $1,AX -- MULQ 192(DI) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 168(DI),AX -- MULQ 168(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 168(DI),AX -- SHLQ $1,AX -- MULQ 176(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 168(DI),AX -- SHLQ $1,AX -- MULQ 184(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 168(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 192(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 176(DI),AX -- MULQ 176(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 176(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 184(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 176(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 192(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 184(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 184(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 184(DI),DX -- IMUL3Q $38,DX,AX -- MULQ 192(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 192(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 192(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- ANDQ DX,SI -- MOVQ CX,R8 -- SHRQ $51,CX -- ADDQ R10,CX -- ANDQ DX,R8 -- MOVQ CX,R9 -- SHRQ $51,CX -- ADDQ R12,CX -- ANDQ DX,R9 -- MOVQ CX,AX -- SHRQ $51,CX -- ADDQ R14,CX -- ANDQ DX,AX -- MOVQ CX,R10 -- SHRQ $51,CX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,160(DI) -- MOVQ R8,168(DI) -- MOVQ R9,176(DI) -- MOVQ AX,184(DI) -- MOVQ R10,192(DI) -- MOVQ 184(DI),SI -- IMUL3Q $19,SI,AX -- MOVQ AX,0(SP) -- MULQ 16(DI) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 192(DI),DX -- IMUL3Q $19,DX,AX -- MOVQ AX,8(SP) -- MULQ 8(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 160(DI),AX -- MULQ 0(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 160(DI),AX -- MULQ 8(DI) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 160(DI),AX -- MULQ 16(DI) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 160(DI),AX -- MULQ 24(DI) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 160(DI),AX -- MULQ 32(DI) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 168(DI),AX -- MULQ 0(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 168(DI),AX -- MULQ 8(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 168(DI),AX -- MULQ 16(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 168(DI),AX -- MULQ 24(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 168(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 32(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 176(DI),AX -- MULQ 0(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 176(DI),AX -- MULQ 8(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 176(DI),AX -- MULQ 16(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 176(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 24(DI) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 176(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 32(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 184(DI),AX -- MULQ 0(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 184(DI),AX -- MULQ 8(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 0(SP),AX -- MULQ 24(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 0(SP),AX -- MULQ 32(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 192(DI),AX -- MULQ 0(DI) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 8(SP),AX -- MULQ 16(DI) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 8(SP),AX -- MULQ 24(DI) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 8(SP),AX -- MULQ 32(DI) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- MOVQ CX,R8 -- SHRQ $51,CX -- ANDQ DX,SI -- ADDQ R10,CX -- MOVQ CX,R9 -- SHRQ $51,CX -- ANDQ DX,R8 -- ADDQ R12,CX -- MOVQ CX,AX -- SHRQ $51,CX -- ANDQ DX,R9 -- ADDQ R14,CX -- MOVQ CX,R10 -- SHRQ $51,CX -- ANDQ DX,AX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,160(DI) -- MOVQ R8,168(DI) -- MOVQ R9,176(DI) -- MOVQ AX,184(DI) -- MOVQ R10,192(DI) -- MOVQ 144(SP),SI -- IMUL3Q $19,SI,AX -- MOVQ AX,0(SP) -- MULQ 96(SP) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 152(SP),DX -- IMUL3Q $19,DX,AX -- MOVQ AX,8(SP) -- MULQ 88(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 120(SP),AX -- MULQ 80(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 120(SP),AX -- MULQ 88(SP) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 120(SP),AX -- MULQ 96(SP) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 120(SP),AX -- MULQ 104(SP) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 120(SP),AX -- MULQ 112(SP) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 128(SP),AX -- MULQ 80(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 128(SP),AX -- MULQ 88(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 128(SP),AX -- MULQ 96(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 128(SP),AX -- MULQ 104(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 128(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 112(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 136(SP),AX -- MULQ 80(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 136(SP),AX -- MULQ 88(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 136(SP),AX -- MULQ 96(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 136(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 104(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 136(SP),DX -- IMUL3Q $19,DX,AX -- MULQ 112(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 144(SP),AX -- MULQ 80(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 144(SP),AX -- MULQ 88(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 0(SP),AX -- MULQ 104(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 0(SP),AX -- MULQ 112(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 152(SP),AX -- MULQ 80(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 8(SP),AX -- MULQ 96(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 8(SP),AX -- MULQ 104(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 8(SP),AX -- MULQ 112(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- MOVQ CX,R8 -- SHRQ $51,CX -- ANDQ DX,SI -- ADDQ R10,CX -- MOVQ CX,R9 -- SHRQ $51,CX -- ANDQ DX,R8 -- ADDQ R12,CX -- MOVQ CX,AX -- SHRQ $51,CX -- ANDQ DX,R9 -- ADDQ R14,CX -- MOVQ CX,R10 -- SHRQ $51,CX -- ANDQ DX,AX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,40(DI) -- MOVQ R8,48(DI) -- MOVQ R9,56(DI) -- MOVQ AX,64(DI) -- MOVQ R10,72(DI) -- MOVQ 160(SP),AX -- MULQ ·_121666_213(SB) -- SHRQ $13,AX -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 168(SP),AX -- MULQ ·_121666_213(SB) -- SHRQ $13,AX -- ADDQ AX,CX -- MOVQ DX,R8 -- MOVQ 176(SP),AX -- MULQ ·_121666_213(SB) -- SHRQ $13,AX -- ADDQ AX,R8 -- MOVQ DX,R9 -- MOVQ 184(SP),AX -- MULQ ·_121666_213(SB) -- SHRQ $13,AX -- ADDQ AX,R9 -- MOVQ DX,R10 -- MOVQ 192(SP),AX -- MULQ ·_121666_213(SB) -- SHRQ $13,AX -- ADDQ AX,R10 -- IMUL3Q $19,DX,DX -- ADDQ DX,SI -- ADDQ 80(SP),SI -- ADDQ 88(SP),CX -- ADDQ 96(SP),R8 -- ADDQ 104(SP),R9 -- ADDQ 112(SP),R10 -- MOVQ SI,80(DI) -- MOVQ CX,88(DI) -- MOVQ R8,96(DI) -- MOVQ R9,104(DI) -- MOVQ R10,112(DI) -- MOVQ 104(DI),SI -- IMUL3Q $19,SI,AX -- MOVQ AX,0(SP) -- MULQ 176(SP) -- MOVQ AX,SI -- MOVQ DX,CX -- MOVQ 112(DI),DX -- IMUL3Q $19,DX,AX -- MOVQ AX,8(SP) -- MULQ 168(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 80(DI),AX -- MULQ 160(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 80(DI),AX -- MULQ 168(SP) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 80(DI),AX -- MULQ 176(SP) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 80(DI),AX -- MULQ 184(SP) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 80(DI),AX -- MULQ 192(SP) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 88(DI),AX -- MULQ 160(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 88(DI),AX -- MULQ 168(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 88(DI),AX -- MULQ 176(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 88(DI),AX -- MULQ 184(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 88(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 192(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 96(DI),AX -- MULQ 160(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 96(DI),AX -- MULQ 168(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 96(DI),AX -- MULQ 176(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 96(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 184(SP) -- ADDQ AX,SI -- ADCQ DX,CX -- MOVQ 96(DI),DX -- IMUL3Q $19,DX,AX -- MULQ 192(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 104(DI),AX -- MULQ 160(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 104(DI),AX -- MULQ 168(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 0(SP),AX -- MULQ 184(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 0(SP),AX -- MULQ 192(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 112(DI),AX -- MULQ 160(SP) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 8(SP),AX -- MULQ 176(SP) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 8(SP),AX -- MULQ 184(SP) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 8(SP),AX -- MULQ 192(SP) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ $REDMASK51,DX -- SHLQ $13,SI,CX -- ANDQ DX,SI -- SHLQ $13,R8,R9 -- ANDQ DX,R8 -- ADDQ CX,R8 -- SHLQ $13,R10,R11 -- ANDQ DX,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ DX,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ DX,R14 -- ADDQ R13,R14 -- IMUL3Q $19,R15,CX -- ADDQ CX,SI -- MOVQ SI,CX -- SHRQ $51,CX -- ADDQ R8,CX -- MOVQ CX,R8 -- SHRQ $51,CX -- ANDQ DX,SI -- ADDQ R10,CX -- MOVQ CX,R9 -- SHRQ $51,CX -- ANDQ DX,R8 -- ADDQ R12,CX -- MOVQ CX,AX -- SHRQ $51,CX -- ANDQ DX,R9 -- ADDQ R14,CX -- MOVQ CX,R10 -- SHRQ $51,CX -- ANDQ DX,AX -- IMUL3Q $19,CX,CX -- ADDQ CX,SI -- ANDQ DX,R10 -- MOVQ SI,80(DI) -- MOVQ R8,88(DI) -- MOVQ R9,96(DI) -- MOVQ AX,104(DI) -- MOVQ R10,112(DI) -- RET -- --// func cswap(inout *[4][5]uint64, v uint64) --TEXT ·cswap(SB),7,$0 -- MOVQ inout+0(FP),DI -- MOVQ v+8(FP),SI -- -- SUBQ $1, SI -- NOTQ SI -- MOVQ SI, X15 -- PSHUFD $0x44, X15, X15 -- -- MOVOU 0(DI), X0 -- MOVOU 16(DI), X2 -- MOVOU 32(DI), X4 -- MOVOU 48(DI), X6 -- MOVOU 64(DI), X8 -- MOVOU 80(DI), X1 -- MOVOU 96(DI), X3 -- MOVOU 112(DI), X5 -- MOVOU 128(DI), X7 -- MOVOU 144(DI), X9 -- -- MOVO X1, X10 -- MOVO X3, X11 -- MOVO X5, X12 -- MOVO X7, X13 -- MOVO X9, X14 -- -- PXOR X0, X10 -- PXOR X2, X11 -- PXOR X4, X12 -- PXOR X6, X13 -- PXOR X8, X14 -- PAND X15, X10 -- PAND X15, X11 -- PAND X15, X12 -- PAND X15, X13 -- PAND X15, X14 -- PXOR X10, X0 -- PXOR X10, X1 -- PXOR X11, X2 -- PXOR X11, X3 -- PXOR X12, X4 -- PXOR X12, X5 -- PXOR X13, X6 -- PXOR X13, X7 -- PXOR X14, X8 -- PXOR X14, X9 -- -- MOVOU X0, 0(DI) -- MOVOU X2, 16(DI) -- MOVOU X4, 32(DI) -- MOVOU X6, 48(DI) -- MOVOU X8, 64(DI) -- MOVOU X1, 80(DI) -- MOVOU X3, 96(DI) -- MOVOU X5, 112(DI) -- MOVOU X7, 128(DI) -- MOVOU X9, 144(DI) -- RET -- --// func mul(dest, a, b *[5]uint64) --TEXT ·mul(SB),0,$16-24 -- MOVQ dest+0(FP), DI -- MOVQ a+8(FP), SI -- MOVQ b+16(FP), DX -- -- MOVQ DX,CX -- MOVQ 24(SI),DX -- IMUL3Q $19,DX,AX -- MOVQ AX,0(SP) -- MULQ 16(CX) -- MOVQ AX,R8 -- MOVQ DX,R9 -- MOVQ 32(SI),DX -- IMUL3Q $19,DX,AX -- MOVQ AX,8(SP) -- MULQ 8(CX) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 0(SI),AX -- MULQ 0(CX) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 0(SI),AX -- MULQ 8(CX) -- MOVQ AX,R10 -- MOVQ DX,R11 -- MOVQ 0(SI),AX -- MULQ 16(CX) -- MOVQ AX,R12 -- MOVQ DX,R13 -- MOVQ 0(SI),AX -- MULQ 24(CX) -- MOVQ AX,R14 -- MOVQ DX,R15 -- MOVQ 0(SI),AX -- MULQ 32(CX) -- MOVQ AX,BX -- MOVQ DX,BP -- MOVQ 8(SI),AX -- MULQ 0(CX) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 8(SI),AX -- MULQ 8(CX) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 8(SI),AX -- MULQ 16(CX) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 8(SI),AX -- MULQ 24(CX) -- ADDQ AX,BX -- ADCQ DX,BP -- MOVQ 8(SI),DX -- IMUL3Q $19,DX,AX -- MULQ 32(CX) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 16(SI),AX -- MULQ 0(CX) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 16(SI),AX -- MULQ 8(CX) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 16(SI),AX -- MULQ 16(CX) -- ADDQ AX,BX -- ADCQ DX,BP -- MOVQ 16(SI),DX -- IMUL3Q $19,DX,AX -- MULQ 24(CX) -- ADDQ AX,R8 -- ADCQ DX,R9 -- MOVQ 16(SI),DX -- IMUL3Q $19,DX,AX -- MULQ 32(CX) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 24(SI),AX -- MULQ 0(CX) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ 24(SI),AX -- MULQ 8(CX) -- ADDQ AX,BX -- ADCQ DX,BP -- MOVQ 0(SP),AX -- MULQ 24(CX) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 0(SP),AX -- MULQ 32(CX) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 32(SI),AX -- MULQ 0(CX) -- ADDQ AX,BX -- ADCQ DX,BP -- MOVQ 8(SP),AX -- MULQ 16(CX) -- ADDQ AX,R10 -- ADCQ DX,R11 -- MOVQ 8(SP),AX -- MULQ 24(CX) -- ADDQ AX,R12 -- ADCQ DX,R13 -- MOVQ 8(SP),AX -- MULQ 32(CX) -- ADDQ AX,R14 -- ADCQ DX,R15 -- MOVQ $REDMASK51,SI -- SHLQ $13,R8,R9 -- ANDQ SI,R8 -- SHLQ $13,R10,R11 -- ANDQ SI,R10 -- ADDQ R9,R10 -- SHLQ $13,R12,R13 -- ANDQ SI,R12 -- ADDQ R11,R12 -- SHLQ $13,R14,R15 -- ANDQ SI,R14 -- ADDQ R13,R14 -- SHLQ $13,BX,BP -- ANDQ SI,BX -- ADDQ R15,BX -- IMUL3Q $19,BP,DX -- ADDQ DX,R8 -- MOVQ R8,DX -- SHRQ $51,DX -- ADDQ R10,DX -- MOVQ DX,CX -- SHRQ $51,DX -- ANDQ SI,R8 -- ADDQ R12,DX -- MOVQ DX,R9 -- SHRQ $51,DX -- ANDQ SI,CX -- ADDQ R14,DX -- MOVQ DX,AX -- SHRQ $51,DX -- ANDQ SI,R9 -- ADDQ BX,DX -- MOVQ DX,R10 -- SHRQ $51,DX -- ANDQ SI,AX -- IMUL3Q $19,DX,DX -- ADDQ DX,R8 -- ANDQ SI,R10 -- MOVQ R8,0(DI) -- MOVQ CX,8(DI) -- MOVQ R9,16(DI) -- MOVQ AX,24(DI) -- MOVQ R10,32(DI) -- RET -- --// func square(out, in *[5]uint64) --TEXT ·square(SB),7,$0-16 -- MOVQ out+0(FP), DI -- MOVQ in+8(FP), SI -- -- MOVQ 0(SI),AX -- MULQ 0(SI) -- MOVQ AX,CX -- MOVQ DX,R8 -- MOVQ 0(SI),AX -- SHLQ $1,AX -- MULQ 8(SI) -- MOVQ AX,R9 -- MOVQ DX,R10 -- MOVQ 0(SI),AX -- SHLQ $1,AX -- MULQ 16(SI) -- MOVQ AX,R11 -- MOVQ DX,R12 -- MOVQ 0(SI),AX -- SHLQ $1,AX -- MULQ 24(SI) -- MOVQ AX,R13 -- MOVQ DX,R14 -- MOVQ 0(SI),AX -- SHLQ $1,AX -- MULQ 32(SI) -- MOVQ AX,R15 -- MOVQ DX,BX -- MOVQ 8(SI),AX -- MULQ 8(SI) -- ADDQ AX,R11 -- ADCQ DX,R12 -- MOVQ 8(SI),AX -- SHLQ $1,AX -- MULQ 16(SI) -- ADDQ AX,R13 -- ADCQ DX,R14 -- MOVQ 8(SI),AX -- SHLQ $1,AX -- MULQ 24(SI) -- ADDQ AX,R15 -- ADCQ DX,BX -- MOVQ 8(SI),DX -- IMUL3Q $38,DX,AX -- MULQ 32(SI) -- ADDQ AX,CX -- ADCQ DX,R8 -- MOVQ 16(SI),AX -- MULQ 16(SI) -- ADDQ AX,R15 -- ADCQ DX,BX -- MOVQ 16(SI),DX -- IMUL3Q $38,DX,AX -- MULQ 24(SI) -- ADDQ AX,CX -- ADCQ DX,R8 -- MOVQ 16(SI),DX -- IMUL3Q $38,DX,AX -- MULQ 32(SI) -- ADDQ AX,R9 -- ADCQ DX,R10 -- MOVQ 24(SI),DX -- IMUL3Q $19,DX,AX -- MULQ 24(SI) -- ADDQ AX,R9 -- ADCQ DX,R10 -- MOVQ 24(SI),DX -- IMUL3Q $38,DX,AX -- MULQ 32(SI) -- ADDQ AX,R11 -- ADCQ DX,R12 -- MOVQ 32(SI),DX -- IMUL3Q $19,DX,AX -- MULQ 32(SI) -- ADDQ AX,R13 -- ADCQ DX,R14 -- MOVQ $REDMASK51,SI -- SHLQ $13,CX,R8 -- ANDQ SI,CX -- SHLQ $13,R9,R10 -- ANDQ SI,R9 -- ADDQ R8,R9 -- SHLQ $13,R11,R12 -- ANDQ SI,R11 -- ADDQ R10,R11 -- SHLQ $13,R13,R14 -- ANDQ SI,R13 -- ADDQ R12,R13 -- SHLQ $13,R15,BX -- ANDQ SI,R15 -- ADDQ R14,R15 -- IMUL3Q $19,BX,DX -- ADDQ DX,CX -- MOVQ CX,DX -- SHRQ $51,DX -- ADDQ R9,DX -- ANDQ SI,CX -- MOVQ DX,R8 -- SHRQ $51,DX -- ADDQ R11,DX -- ANDQ SI,R8 -- MOVQ DX,R9 -- SHRQ $51,DX -- ADDQ R13,DX -- ANDQ SI,R9 -- MOVQ DX,AX -- SHRQ $51,DX -- ADDQ R15,DX -- ANDQ SI,AX -- MOVQ DX,R10 -- SHRQ $51,DX -- IMUL3Q $19,DX,DX -- ADDQ DX,CX -- ANDQ SI,R10 -- MOVQ CX,0(DI) -- MOVQ R8,8(DI) -- MOVQ R9,16(DI) -- MOVQ AX,24(DI) -- MOVQ R10,32(DI) -- RET -diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go b/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go -deleted file mode 100644 -index c43b13fc83e7..000000000000 ---- a/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go -+++ /dev/null -@@ -1,828 +0,0 @@ --// Copyright 2013 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 curve25519 -- --import "encoding/binary" -- --// This code is a port of the public domain, "ref10" implementation of --// curve25519 from SUPERCOP 20130419 by D. J. Bernstein. -- --// fieldElement represents an element of the field GF(2^255 - 19). An element --// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 --// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on --// context. --type fieldElement [10]int32 -- --func feZero(fe *fieldElement) { -- for i := range fe { -- fe[i] = 0 -- } --} -- --func feOne(fe *fieldElement) { -- feZero(fe) -- fe[0] = 1 --} -- --func feAdd(dst, a, b *fieldElement) { -- for i := range dst { -- dst[i] = a[i] + b[i] -- } --} -- --func feSub(dst, a, b *fieldElement) { -- for i := range dst { -- dst[i] = a[i] - b[i] -- } --} -- --func feCopy(dst, src *fieldElement) { -- for i := range dst { -- dst[i] = src[i] -- } --} -- --// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0. --// --// Preconditions: b in {0,1}. --func feCSwap(f, g *fieldElement, b int32) { -- b = -b -- for i := range f { -- t := b & (f[i] ^ g[i]) -- f[i] ^= t -- g[i] ^= t -- } --} -- --// load3 reads a 24-bit, little-endian value from in. --func load3(in []byte) int64 { -- var r int64 -- r = int64(in[0]) -- r |= int64(in[1]) << 8 -- r |= int64(in[2]) << 16 -- return r --} -- --// load4 reads a 32-bit, little-endian value from in. --func load4(in []byte) int64 { -- return int64(binary.LittleEndian.Uint32(in)) --} -- --func feFromBytes(dst *fieldElement, src *[32]byte) { -- h0 := load4(src[:]) -- h1 := load3(src[4:]) << 6 -- h2 := load3(src[7:]) << 5 -- h3 := load3(src[10:]) << 3 -- h4 := load3(src[13:]) << 2 -- h5 := load4(src[16:]) -- h6 := load3(src[20:]) << 7 -- h7 := load3(src[23:]) << 5 -- h8 := load3(src[26:]) << 4 -- h9 := (load3(src[29:]) & 0x7fffff) << 2 -- -- var carry [10]int64 -- carry[9] = (h9 + 1<<24) >> 25 -- h0 += carry[9] * 19 -- h9 -= carry[9] << 25 -- carry[1] = (h1 + 1<<24) >> 25 -- h2 += carry[1] -- h1 -= carry[1] << 25 -- carry[3] = (h3 + 1<<24) >> 25 -- h4 += carry[3] -- h3 -= carry[3] << 25 -- carry[5] = (h5 + 1<<24) >> 25 -- h6 += carry[5] -- h5 -= carry[5] << 25 -- carry[7] = (h7 + 1<<24) >> 25 -- h8 += carry[7] -- h7 -= carry[7] << 25 -- -- carry[0] = (h0 + 1<<25) >> 26 -- h1 += carry[0] -- h0 -= carry[0] << 26 -- carry[2] = (h2 + 1<<25) >> 26 -- h3 += carry[2] -- h2 -= carry[2] << 26 -- carry[4] = (h4 + 1<<25) >> 26 -- h5 += carry[4] -- h4 -= carry[4] << 26 -- carry[6] = (h6 + 1<<25) >> 26 -- h7 += carry[6] -- h6 -= carry[6] << 26 -- carry[8] = (h8 + 1<<25) >> 26 -- h9 += carry[8] -- h8 -= carry[8] << 26 -- -- dst[0] = int32(h0) -- dst[1] = int32(h1) -- dst[2] = int32(h2) -- dst[3] = int32(h3) -- dst[4] = int32(h4) -- dst[5] = int32(h5) -- dst[6] = int32(h6) -- dst[7] = int32(h7) -- dst[8] = int32(h8) -- dst[9] = int32(h9) --} -- --// feToBytes marshals h to s. --// Preconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --// --// Write p=2^255-19; q=floor(h/p). --// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). --// --// Proof: --// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. --// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. --// --// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). --// Then 0> 25 -- q = (h[0] + q) >> 26 -- q = (h[1] + q) >> 25 -- q = (h[2] + q) >> 26 -- q = (h[3] + q) >> 25 -- q = (h[4] + q) >> 26 -- q = (h[5] + q) >> 25 -- q = (h[6] + q) >> 26 -- q = (h[7] + q) >> 25 -- q = (h[8] + q) >> 26 -- q = (h[9] + q) >> 25 -- -- // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. -- h[0] += 19 * q -- // Goal: Output h-2^255 q, which is between 0 and 2^255-20. -- -- carry[0] = h[0] >> 26 -- h[1] += carry[0] -- h[0] -= carry[0] << 26 -- carry[1] = h[1] >> 25 -- h[2] += carry[1] -- h[1] -= carry[1] << 25 -- carry[2] = h[2] >> 26 -- h[3] += carry[2] -- h[2] -= carry[2] << 26 -- carry[3] = h[3] >> 25 -- h[4] += carry[3] -- h[3] -= carry[3] << 25 -- carry[4] = h[4] >> 26 -- h[5] += carry[4] -- h[4] -= carry[4] << 26 -- carry[5] = h[5] >> 25 -- h[6] += carry[5] -- h[5] -= carry[5] << 25 -- carry[6] = h[6] >> 26 -- h[7] += carry[6] -- h[6] -= carry[6] << 26 -- carry[7] = h[7] >> 25 -- h[8] += carry[7] -- h[7] -= carry[7] << 25 -- carry[8] = h[8] >> 26 -- h[9] += carry[8] -- h[8] -= carry[8] << 26 -- carry[9] = h[9] >> 25 -- h[9] -= carry[9] << 25 -- // h10 = carry9 -- -- // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. -- // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; -- // evidently 2^255 h10-2^255 q = 0. -- // Goal: Output h[0]+...+2^230 h[9]. -- -- s[0] = byte(h[0] >> 0) -- s[1] = byte(h[0] >> 8) -- s[2] = byte(h[0] >> 16) -- s[3] = byte((h[0] >> 24) | (h[1] << 2)) -- s[4] = byte(h[1] >> 6) -- s[5] = byte(h[1] >> 14) -- s[6] = byte((h[1] >> 22) | (h[2] << 3)) -- s[7] = byte(h[2] >> 5) -- s[8] = byte(h[2] >> 13) -- s[9] = byte((h[2] >> 21) | (h[3] << 5)) -- s[10] = byte(h[3] >> 3) -- s[11] = byte(h[3] >> 11) -- s[12] = byte((h[3] >> 19) | (h[4] << 6)) -- s[13] = byte(h[4] >> 2) -- s[14] = byte(h[4] >> 10) -- s[15] = byte(h[4] >> 18) -- s[16] = byte(h[5] >> 0) -- s[17] = byte(h[5] >> 8) -- s[18] = byte(h[5] >> 16) -- s[19] = byte((h[5] >> 24) | (h[6] << 1)) -- s[20] = byte(h[6] >> 7) -- s[21] = byte(h[6] >> 15) -- s[22] = byte((h[6] >> 23) | (h[7] << 3)) -- s[23] = byte(h[7] >> 5) -- s[24] = byte(h[7] >> 13) -- s[25] = byte((h[7] >> 21) | (h[8] << 4)) -- s[26] = byte(h[8] >> 4) -- s[27] = byte(h[8] >> 12) -- s[28] = byte((h[8] >> 20) | (h[9] << 6)) -- s[29] = byte(h[9] >> 2) -- s[30] = byte(h[9] >> 10) -- s[31] = byte(h[9] >> 18) --} -- --// feMul calculates h = f * g --// Can overlap h with f or g. --// --// Preconditions: --// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. --// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. --// --// Postconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --// --// Notes on implementation strategy: --// --// Using schoolbook multiplication. --// Karatsuba would save a little in some cost models. --// --// Most multiplications by 2 and 19 are 32-bit precomputations; --// cheaper than 64-bit postcomputations. --// --// There is one remaining multiplication by 19 in the carry chain; --// one *19 precomputation can be merged into this, --// but the resulting data flow is considerably less clean. --// --// There are 12 carries below. --// 10 of them are 2-way parallelizable and vectorizable. --// Can get away with 11 carries, but then data flow is much deeper. --// --// With tighter constraints on inputs can squeeze carries into int32. --func feMul(h, f, g *fieldElement) { -- f0 := f[0] -- f1 := f[1] -- f2 := f[2] -- f3 := f[3] -- f4 := f[4] -- f5 := f[5] -- f6 := f[6] -- f7 := f[7] -- f8 := f[8] -- f9 := f[9] -- g0 := g[0] -- g1 := g[1] -- g2 := g[2] -- g3 := g[3] -- g4 := g[4] -- g5 := g[5] -- g6 := g[6] -- g7 := g[7] -- g8 := g[8] -- g9 := g[9] -- g1_19 := 19 * g1 // 1.4*2^29 -- g2_19 := 19 * g2 // 1.4*2^30; still ok -- g3_19 := 19 * g3 -- g4_19 := 19 * g4 -- g5_19 := 19 * g5 -- g6_19 := 19 * g6 -- g7_19 := 19 * g7 -- g8_19 := 19 * g8 -- g9_19 := 19 * g9 -- f1_2 := 2 * f1 -- f3_2 := 2 * f3 -- f5_2 := 2 * f5 -- f7_2 := 2 * f7 -- f9_2 := 2 * f9 -- f0g0 := int64(f0) * int64(g0) -- f0g1 := int64(f0) * int64(g1) -- f0g2 := int64(f0) * int64(g2) -- f0g3 := int64(f0) * int64(g3) -- f0g4 := int64(f0) * int64(g4) -- f0g5 := int64(f0) * int64(g5) -- f0g6 := int64(f0) * int64(g6) -- f0g7 := int64(f0) * int64(g7) -- f0g8 := int64(f0) * int64(g8) -- f0g9 := int64(f0) * int64(g9) -- f1g0 := int64(f1) * int64(g0) -- f1g1_2 := int64(f1_2) * int64(g1) -- f1g2 := int64(f1) * int64(g2) -- f1g3_2 := int64(f1_2) * int64(g3) -- f1g4 := int64(f1) * int64(g4) -- f1g5_2 := int64(f1_2) * int64(g5) -- f1g6 := int64(f1) * int64(g6) -- f1g7_2 := int64(f1_2) * int64(g7) -- f1g8 := int64(f1) * int64(g8) -- f1g9_38 := int64(f1_2) * int64(g9_19) -- f2g0 := int64(f2) * int64(g0) -- f2g1 := int64(f2) * int64(g1) -- f2g2 := int64(f2) * int64(g2) -- f2g3 := int64(f2) * int64(g3) -- f2g4 := int64(f2) * int64(g4) -- f2g5 := int64(f2) * int64(g5) -- f2g6 := int64(f2) * int64(g6) -- f2g7 := int64(f2) * int64(g7) -- f2g8_19 := int64(f2) * int64(g8_19) -- f2g9_19 := int64(f2) * int64(g9_19) -- f3g0 := int64(f3) * int64(g0) -- f3g1_2 := int64(f3_2) * int64(g1) -- f3g2 := int64(f3) * int64(g2) -- f3g3_2 := int64(f3_2) * int64(g3) -- f3g4 := int64(f3) * int64(g4) -- f3g5_2 := int64(f3_2) * int64(g5) -- f3g6 := int64(f3) * int64(g6) -- f3g7_38 := int64(f3_2) * int64(g7_19) -- f3g8_19 := int64(f3) * int64(g8_19) -- f3g9_38 := int64(f3_2) * int64(g9_19) -- f4g0 := int64(f4) * int64(g0) -- f4g1 := int64(f4) * int64(g1) -- f4g2 := int64(f4) * int64(g2) -- f4g3 := int64(f4) * int64(g3) -- f4g4 := int64(f4) * int64(g4) -- f4g5 := int64(f4) * int64(g5) -- f4g6_19 := int64(f4) * int64(g6_19) -- f4g7_19 := int64(f4) * int64(g7_19) -- f4g8_19 := int64(f4) * int64(g8_19) -- f4g9_19 := int64(f4) * int64(g9_19) -- f5g0 := int64(f5) * int64(g0) -- f5g1_2 := int64(f5_2) * int64(g1) -- f5g2 := int64(f5) * int64(g2) -- f5g3_2 := int64(f5_2) * int64(g3) -- f5g4 := int64(f5) * int64(g4) -- f5g5_38 := int64(f5_2) * int64(g5_19) -- f5g6_19 := int64(f5) * int64(g6_19) -- f5g7_38 := int64(f5_2) * int64(g7_19) -- f5g8_19 := int64(f5) * int64(g8_19) -- f5g9_38 := int64(f5_2) * int64(g9_19) -- f6g0 := int64(f6) * int64(g0) -- f6g1 := int64(f6) * int64(g1) -- f6g2 := int64(f6) * int64(g2) -- f6g3 := int64(f6) * int64(g3) -- f6g4_19 := int64(f6) * int64(g4_19) -- f6g5_19 := int64(f6) * int64(g5_19) -- f6g6_19 := int64(f6) * int64(g6_19) -- f6g7_19 := int64(f6) * int64(g7_19) -- f6g8_19 := int64(f6) * int64(g8_19) -- f6g9_19 := int64(f6) * int64(g9_19) -- f7g0 := int64(f7) * int64(g0) -- f7g1_2 := int64(f7_2) * int64(g1) -- f7g2 := int64(f7) * int64(g2) -- f7g3_38 := int64(f7_2) * int64(g3_19) -- f7g4_19 := int64(f7) * int64(g4_19) -- f7g5_38 := int64(f7_2) * int64(g5_19) -- f7g6_19 := int64(f7) * int64(g6_19) -- f7g7_38 := int64(f7_2) * int64(g7_19) -- f7g8_19 := int64(f7) * int64(g8_19) -- f7g9_38 := int64(f7_2) * int64(g9_19) -- f8g0 := int64(f8) * int64(g0) -- f8g1 := int64(f8) * int64(g1) -- f8g2_19 := int64(f8) * int64(g2_19) -- f8g3_19 := int64(f8) * int64(g3_19) -- f8g4_19 := int64(f8) * int64(g4_19) -- f8g5_19 := int64(f8) * int64(g5_19) -- f8g6_19 := int64(f8) * int64(g6_19) -- f8g7_19 := int64(f8) * int64(g7_19) -- f8g8_19 := int64(f8) * int64(g8_19) -- f8g9_19 := int64(f8) * int64(g9_19) -- f9g0 := int64(f9) * int64(g0) -- f9g1_38 := int64(f9_2) * int64(g1_19) -- f9g2_19 := int64(f9) * int64(g2_19) -- f9g3_38 := int64(f9_2) * int64(g3_19) -- f9g4_19 := int64(f9) * int64(g4_19) -- f9g5_38 := int64(f9_2) * int64(g5_19) -- f9g6_19 := int64(f9) * int64(g6_19) -- f9g7_38 := int64(f9_2) * int64(g7_19) -- f9g8_19 := int64(f9) * int64(g8_19) -- f9g9_38 := int64(f9_2) * int64(g9_19) -- h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38 -- h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19 -- h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38 -- h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19 -- h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38 -- h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19 -- h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38 -- h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19 -- h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38 -- h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 -- var carry [10]int64 -- -- // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) -- // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 -- // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) -- // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 -- -- carry[0] = (h0 + (1 << 25)) >> 26 -- h1 += carry[0] -- h0 -= carry[0] << 26 -- carry[4] = (h4 + (1 << 25)) >> 26 -- h5 += carry[4] -- h4 -= carry[4] << 26 -- // |h0| <= 2^25 -- // |h4| <= 2^25 -- // |h1| <= 1.51*2^58 -- // |h5| <= 1.51*2^58 -- -- carry[1] = (h1 + (1 << 24)) >> 25 -- h2 += carry[1] -- h1 -= carry[1] << 25 -- carry[5] = (h5 + (1 << 24)) >> 25 -- h6 += carry[5] -- h5 -= carry[5] << 25 -- // |h1| <= 2^24; from now on fits into int32 -- // |h5| <= 2^24; from now on fits into int32 -- // |h2| <= 1.21*2^59 -- // |h6| <= 1.21*2^59 -- -- carry[2] = (h2 + (1 << 25)) >> 26 -- h3 += carry[2] -- h2 -= carry[2] << 26 -- carry[6] = (h6 + (1 << 25)) >> 26 -- h7 += carry[6] -- h6 -= carry[6] << 26 -- // |h2| <= 2^25; from now on fits into int32 unchanged -- // |h6| <= 2^25; from now on fits into int32 unchanged -- // |h3| <= 1.51*2^58 -- // |h7| <= 1.51*2^58 -- -- carry[3] = (h3 + (1 << 24)) >> 25 -- h4 += carry[3] -- h3 -= carry[3] << 25 -- carry[7] = (h7 + (1 << 24)) >> 25 -- h8 += carry[7] -- h7 -= carry[7] << 25 -- // |h3| <= 2^24; from now on fits into int32 unchanged -- // |h7| <= 2^24; from now on fits into int32 unchanged -- // |h4| <= 1.52*2^33 -- // |h8| <= 1.52*2^33 -- -- carry[4] = (h4 + (1 << 25)) >> 26 -- h5 += carry[4] -- h4 -= carry[4] << 26 -- carry[8] = (h8 + (1 << 25)) >> 26 -- h9 += carry[8] -- h8 -= carry[8] << 26 -- // |h4| <= 2^25; from now on fits into int32 unchanged -- // |h8| <= 2^25; from now on fits into int32 unchanged -- // |h5| <= 1.01*2^24 -- // |h9| <= 1.51*2^58 -- -- carry[9] = (h9 + (1 << 24)) >> 25 -- h0 += carry[9] * 19 -- h9 -= carry[9] << 25 -- // |h9| <= 2^24; from now on fits into int32 unchanged -- // |h0| <= 1.8*2^37 -- -- carry[0] = (h0 + (1 << 25)) >> 26 -- h1 += carry[0] -- h0 -= carry[0] << 26 -- // |h0| <= 2^25; from now on fits into int32 unchanged -- // |h1| <= 1.01*2^24 -- -- h[0] = int32(h0) -- h[1] = int32(h1) -- h[2] = int32(h2) -- h[3] = int32(h3) -- h[4] = int32(h4) -- h[5] = int32(h5) -- h[6] = int32(h6) -- h[7] = int32(h7) -- h[8] = int32(h8) -- h[9] = int32(h9) --} -- --// feSquare calculates h = f*f. Can overlap h with f. --// --// Preconditions: --// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. --// --// Postconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --func feSquare(h, f *fieldElement) { -- f0 := f[0] -- f1 := f[1] -- f2 := f[2] -- f3 := f[3] -- f4 := f[4] -- f5 := f[5] -- f6 := f[6] -- f7 := f[7] -- f8 := f[8] -- f9 := f[9] -- f0_2 := 2 * f0 -- f1_2 := 2 * f1 -- f2_2 := 2 * f2 -- f3_2 := 2 * f3 -- f4_2 := 2 * f4 -- f5_2 := 2 * f5 -- f6_2 := 2 * f6 -- f7_2 := 2 * f7 -- f5_38 := 38 * f5 // 1.31*2^30 -- f6_19 := 19 * f6 // 1.31*2^30 -- f7_38 := 38 * f7 // 1.31*2^30 -- f8_19 := 19 * f8 // 1.31*2^30 -- f9_38 := 38 * f9 // 1.31*2^30 -- f0f0 := int64(f0) * int64(f0) -- f0f1_2 := int64(f0_2) * int64(f1) -- f0f2_2 := int64(f0_2) * int64(f2) -- f0f3_2 := int64(f0_2) * int64(f3) -- f0f4_2 := int64(f0_2) * int64(f4) -- f0f5_2 := int64(f0_2) * int64(f5) -- f0f6_2 := int64(f0_2) * int64(f6) -- f0f7_2 := int64(f0_2) * int64(f7) -- f0f8_2 := int64(f0_2) * int64(f8) -- f0f9_2 := int64(f0_2) * int64(f9) -- f1f1_2 := int64(f1_2) * int64(f1) -- f1f2_2 := int64(f1_2) * int64(f2) -- f1f3_4 := int64(f1_2) * int64(f3_2) -- f1f4_2 := int64(f1_2) * int64(f4) -- f1f5_4 := int64(f1_2) * int64(f5_2) -- f1f6_2 := int64(f1_2) * int64(f6) -- f1f7_4 := int64(f1_2) * int64(f7_2) -- f1f8_2 := int64(f1_2) * int64(f8) -- f1f9_76 := int64(f1_2) * int64(f9_38) -- f2f2 := int64(f2) * int64(f2) -- f2f3_2 := int64(f2_2) * int64(f3) -- f2f4_2 := int64(f2_2) * int64(f4) -- f2f5_2 := int64(f2_2) * int64(f5) -- f2f6_2 := int64(f2_2) * int64(f6) -- f2f7_2 := int64(f2_2) * int64(f7) -- f2f8_38 := int64(f2_2) * int64(f8_19) -- f2f9_38 := int64(f2) * int64(f9_38) -- f3f3_2 := int64(f3_2) * int64(f3) -- f3f4_2 := int64(f3_2) * int64(f4) -- f3f5_4 := int64(f3_2) * int64(f5_2) -- f3f6_2 := int64(f3_2) * int64(f6) -- f3f7_76 := int64(f3_2) * int64(f7_38) -- f3f8_38 := int64(f3_2) * int64(f8_19) -- f3f9_76 := int64(f3_2) * int64(f9_38) -- f4f4 := int64(f4) * int64(f4) -- f4f5_2 := int64(f4_2) * int64(f5) -- f4f6_38 := int64(f4_2) * int64(f6_19) -- f4f7_38 := int64(f4) * int64(f7_38) -- f4f8_38 := int64(f4_2) * int64(f8_19) -- f4f9_38 := int64(f4) * int64(f9_38) -- f5f5_38 := int64(f5) * int64(f5_38) -- f5f6_38 := int64(f5_2) * int64(f6_19) -- f5f7_76 := int64(f5_2) * int64(f7_38) -- f5f8_38 := int64(f5_2) * int64(f8_19) -- f5f9_76 := int64(f5_2) * int64(f9_38) -- f6f6_19 := int64(f6) * int64(f6_19) -- f6f7_38 := int64(f6) * int64(f7_38) -- f6f8_38 := int64(f6_2) * int64(f8_19) -- f6f9_38 := int64(f6) * int64(f9_38) -- f7f7_38 := int64(f7) * int64(f7_38) -- f7f8_38 := int64(f7_2) * int64(f8_19) -- f7f9_76 := int64(f7_2) * int64(f9_38) -- f8f8_19 := int64(f8) * int64(f8_19) -- f8f9_38 := int64(f8) * int64(f9_38) -- f9f9_38 := int64(f9) * int64(f9_38) -- h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38 -- h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38 -- h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19 -- h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38 -- h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38 -- h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38 -- h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19 -- h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38 -- h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38 -- h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2 -- var carry [10]int64 -- -- carry[0] = (h0 + (1 << 25)) >> 26 -- h1 += carry[0] -- h0 -= carry[0] << 26 -- carry[4] = (h4 + (1 << 25)) >> 26 -- h5 += carry[4] -- h4 -= carry[4] << 26 -- -- carry[1] = (h1 + (1 << 24)) >> 25 -- h2 += carry[1] -- h1 -= carry[1] << 25 -- carry[5] = (h5 + (1 << 24)) >> 25 -- h6 += carry[5] -- h5 -= carry[5] << 25 -- -- carry[2] = (h2 + (1 << 25)) >> 26 -- h3 += carry[2] -- h2 -= carry[2] << 26 -- carry[6] = (h6 + (1 << 25)) >> 26 -- h7 += carry[6] -- h6 -= carry[6] << 26 -- -- carry[3] = (h3 + (1 << 24)) >> 25 -- h4 += carry[3] -- h3 -= carry[3] << 25 -- carry[7] = (h7 + (1 << 24)) >> 25 -- h8 += carry[7] -- h7 -= carry[7] << 25 -- -- carry[4] = (h4 + (1 << 25)) >> 26 -- h5 += carry[4] -- h4 -= carry[4] << 26 -- carry[8] = (h8 + (1 << 25)) >> 26 -- h9 += carry[8] -- h8 -= carry[8] << 26 -- -- carry[9] = (h9 + (1 << 24)) >> 25 -- h0 += carry[9] * 19 -- h9 -= carry[9] << 25 -- -- carry[0] = (h0 + (1 << 25)) >> 26 -- h1 += carry[0] -- h0 -= carry[0] << 26 -- -- h[0] = int32(h0) -- h[1] = int32(h1) -- h[2] = int32(h2) -- h[3] = int32(h3) -- h[4] = int32(h4) -- h[5] = int32(h5) -- h[6] = int32(h6) -- h[7] = int32(h7) -- h[8] = int32(h8) -- h[9] = int32(h9) --} -- --// feMul121666 calculates h = f * 121666. Can overlap h with f. --// --// Preconditions: --// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. --// --// Postconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --func feMul121666(h, f *fieldElement) { -- h0 := int64(f[0]) * 121666 -- h1 := int64(f[1]) * 121666 -- h2 := int64(f[2]) * 121666 -- h3 := int64(f[3]) * 121666 -- h4 := int64(f[4]) * 121666 -- h5 := int64(f[5]) * 121666 -- h6 := int64(f[6]) * 121666 -- h7 := int64(f[7]) * 121666 -- h8 := int64(f[8]) * 121666 -- h9 := int64(f[9]) * 121666 -- var carry [10]int64 -- -- carry[9] = (h9 + (1 << 24)) >> 25 -- h0 += carry[9] * 19 -- h9 -= carry[9] << 25 -- carry[1] = (h1 + (1 << 24)) >> 25 -- h2 += carry[1] -- h1 -= carry[1] << 25 -- carry[3] = (h3 + (1 << 24)) >> 25 -- h4 += carry[3] -- h3 -= carry[3] << 25 -- carry[5] = (h5 + (1 << 24)) >> 25 -- h6 += carry[5] -- h5 -= carry[5] << 25 -- carry[7] = (h7 + (1 << 24)) >> 25 -- h8 += carry[7] -- h7 -= carry[7] << 25 -- -- carry[0] = (h0 + (1 << 25)) >> 26 -- h1 += carry[0] -- h0 -= carry[0] << 26 -- carry[2] = (h2 + (1 << 25)) >> 26 -- h3 += carry[2] -- h2 -= carry[2] << 26 -- carry[4] = (h4 + (1 << 25)) >> 26 -- h5 += carry[4] -- h4 -= carry[4] << 26 -- carry[6] = (h6 + (1 << 25)) >> 26 -- h7 += carry[6] -- h6 -= carry[6] << 26 -- carry[8] = (h8 + (1 << 25)) >> 26 -- h9 += carry[8] -- h8 -= carry[8] << 26 -- -- h[0] = int32(h0) -- h[1] = int32(h1) -- h[2] = int32(h2) -- h[3] = int32(h3) -- h[4] = int32(h4) -- h[5] = int32(h5) -- h[6] = int32(h6) -- h[7] = int32(h7) -- h[8] = int32(h8) -- h[9] = int32(h9) --} -- --// feInvert sets out = z^-1. --func feInvert(out, z *fieldElement) { -- var t0, t1, t2, t3 fieldElement -- var i int -- -- feSquare(&t0, z) -- for i = 1; i < 1; i++ { -- feSquare(&t0, &t0) -- } -- feSquare(&t1, &t0) -- for i = 1; i < 2; i++ { -- feSquare(&t1, &t1) -- } -- feMul(&t1, z, &t1) -- feMul(&t0, &t0, &t1) -- feSquare(&t2, &t0) -- for i = 1; i < 1; i++ { -- feSquare(&t2, &t2) -- } -- feMul(&t1, &t1, &t2) -- feSquare(&t2, &t1) -- for i = 1; i < 5; i++ { -- feSquare(&t2, &t2) -- } -- feMul(&t1, &t2, &t1) -- feSquare(&t2, &t1) -- for i = 1; i < 10; i++ { -- feSquare(&t2, &t2) -- } -- feMul(&t2, &t2, &t1) -- feSquare(&t3, &t2) -- for i = 1; i < 20; i++ { -- feSquare(&t3, &t3) -- } -- feMul(&t2, &t3, &t2) -- feSquare(&t2, &t2) -- for i = 1; i < 10; i++ { -- feSquare(&t2, &t2) -- } -- feMul(&t1, &t2, &t1) -- feSquare(&t2, &t1) -- for i = 1; i < 50; i++ { -- feSquare(&t2, &t2) -- } -- feMul(&t2, &t2, &t1) -- feSquare(&t3, &t2) -- for i = 1; i < 100; i++ { -- feSquare(&t3, &t3) -- } -- feMul(&t2, &t3, &t2) -- feSquare(&t2, &t2) -- for i = 1; i < 50; i++ { -- feSquare(&t2, &t2) -- } -- feMul(&t1, &t2, &t1) -- feSquare(&t1, &t1) -- for i = 1; i < 5; i++ { -- feSquare(&t1, &t1) -- } -- feMul(out, &t1, &t0) --} -- --func scalarMultGeneric(out, in, base *[32]byte) { -- var e [32]byte -- -- copy(e[:], in[:]) -- e[0] &= 248 -- e[31] &= 127 -- e[31] |= 64 -- -- var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement -- feFromBytes(&x1, base) -- feOne(&x2) -- feCopy(&x3, &x1) -- feOne(&z3) -- -- swap := int32(0) -- for pos := 254; pos >= 0; pos-- { -- b := e[pos/8] >> uint(pos&7) -- b &= 1 -- swap ^= int32(b) -- feCSwap(&x2, &x3, swap) -- feCSwap(&z2, &z3, swap) -- swap = int32(b) -- -- feSub(&tmp0, &x3, &z3) -- feSub(&tmp1, &x2, &z2) -- feAdd(&x2, &x2, &z2) -- feAdd(&z2, &x3, &z3) -- feMul(&z3, &tmp0, &x2) -- feMul(&z2, &z2, &tmp1) -- feSquare(&tmp0, &tmp1) -- feSquare(&tmp1, &x2) -- feAdd(&x3, &z3, &z2) -- feSub(&z2, &z3, &z2) -- feMul(&x2, &tmp1, &tmp0) -- feSub(&tmp1, &tmp1, &tmp0) -- feSquare(&z2, &z2) -- feMul121666(&z3, &tmp1) -- feSquare(&x3, &x3) -- feAdd(&tmp0, &tmp0, &z3) -- feMul(&z3, &x1, &z2) -- feMul(&z2, &tmp1, &tmp0) -- } -- -- feCSwap(&x2, &x3, swap) -- feCSwap(&z2, &z3, swap) -- -- feInvert(&z2, &z2) -- feMul(&x2, &x2, &z2) -- feToBytes(out, &x2) --} -diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go b/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go -deleted file mode 100644 -index 047d49afc27e..000000000000 ---- a/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go -+++ /dev/null -@@ -1,11 +0,0 @@ --// Copyright 2019 The Go Authors. All rights reserved. --// Use of this source code is governed by a BSD-style --// license that can be found in the LICENSE file. -- --// +build !amd64 gccgo appengine purego -- --package curve25519 -- --func scalarMult(out, in, base *[32]byte) { -- scalarMultGeneric(out, in, base) --} -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/README b/vendor/golang.org/x/crypto/curve25519/internal/field/README -new file mode 100644 -index 000000000000..e25bca7dc806 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/README -@@ -0,0 +1,7 @@ -+This package is kept in sync with crypto/ed25519/internal/edwards25519/field in -+the standard library. -+ -+If there are any changes in the standard library that need to be synced to this -+package, run sync.sh. It will not overwrite any local changes made since the -+previous sync, so it's ok to land changes in this package first, and then sync -+to the standard library later. -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go b/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go -new file mode 100644 -index 000000000000..1f3652987e84 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go -@@ -0,0 +1,298 @@ -+// Copyright (c) 2021 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 main -+ -+import ( -+ "fmt" -+ -+ . "github.com/mmcloughlin/avo/build" -+ . "github.com/mmcloughlin/avo/gotypes" -+ . "github.com/mmcloughlin/avo/operand" -+ . "github.com/mmcloughlin/avo/reg" -+ -+ // Ensure "go mod tidy" doesn't remove the golang.org/x/crypto module -+ // dependency, which is necessary to access the field.Element type. -+ _ "golang.org/x/crypto/curve25519" -+) -+ -+//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field -+ -+func main() { -+ Package("golang.org/x/crypto/curve25519/internal/field") -+ ConstraintExpr("amd64,gc,!purego") -+ feMul() -+ feSquare() -+ Generate() -+} -+ -+type namedComponent struct { -+ Component -+ name string -+} -+ -+func (c namedComponent) String() string { return c.name } -+ -+type uint128 struct { -+ name string -+ hi, lo GPVirtual -+} -+ -+func (c uint128) String() string { return c.name } -+ -+func feSquare() { -+ TEXT("feSquare", NOSPLIT, "func(out, a *Element)") -+ Doc("feSquare sets out = a * a. It works like feSquareGeneric.") -+ Pragma("noescape") -+ -+ a := Dereference(Param("a")) -+ l0 := namedComponent{a.Field("l0"), "l0"} -+ l1 := namedComponent{a.Field("l1"), "l1"} -+ l2 := namedComponent{a.Field("l2"), "l2"} -+ l3 := namedComponent{a.Field("l3"), "l3"} -+ l4 := namedComponent{a.Field("l4"), "l4"} -+ -+ // r0 = l0×l0 + 19×2×(l1×l4 + l2×l3) -+ r0 := uint128{"r0", GP64(), GP64()} -+ mul64(r0, 1, l0, l0) -+ addMul64(r0, 38, l1, l4) -+ addMul64(r0, 38, l2, l3) -+ -+ // r1 = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 -+ r1 := uint128{"r1", GP64(), GP64()} -+ mul64(r1, 2, l0, l1) -+ addMul64(r1, 38, l2, l4) -+ addMul64(r1, 19, l3, l3) -+ -+ // r2 = = 2×l0×l2 + l1×l1 + 19×2×l3×l4 -+ r2 := uint128{"r2", GP64(), GP64()} -+ mul64(r2, 2, l0, l2) -+ addMul64(r2, 1, l1, l1) -+ addMul64(r2, 38, l3, l4) -+ -+ // r3 = = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 -+ r3 := uint128{"r3", GP64(), GP64()} -+ mul64(r3, 2, l0, l3) -+ addMul64(r3, 2, l1, l2) -+ addMul64(r3, 19, l4, l4) -+ -+ // r4 = = 2×l0×l4 + 2×l1×l3 + l2×l2 -+ r4 := uint128{"r4", GP64(), GP64()} -+ mul64(r4, 2, l0, l4) -+ addMul64(r4, 2, l1, l3) -+ addMul64(r4, 1, l2, l2) -+ -+ Comment("First reduction chain") -+ maskLow51Bits := GP64() -+ MOVQ(Imm((1<<51)-1), maskLow51Bits) -+ c0, r0lo := shiftRightBy51(&r0) -+ c1, r1lo := shiftRightBy51(&r1) -+ c2, r2lo := shiftRightBy51(&r2) -+ c3, r3lo := shiftRightBy51(&r3) -+ c4, r4lo := shiftRightBy51(&r4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Second reduction chain (carryPropagate)") -+ // c0 = r0 >> 51 -+ MOVQ(r0lo, c0) -+ SHRQ(Imm(51), c0) -+ // c1 = r1 >> 51 -+ MOVQ(r1lo, c1) -+ SHRQ(Imm(51), c1) -+ // c2 = r2 >> 51 -+ MOVQ(r2lo, c2) -+ SHRQ(Imm(51), c2) -+ // c3 = r3 >> 51 -+ MOVQ(r3lo, c3) -+ SHRQ(Imm(51), c3) -+ // c4 = r4 >> 51 -+ MOVQ(r4lo, c4) -+ SHRQ(Imm(51), c4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Store output") -+ out := Dereference(Param("out")) -+ Store(r0lo, out.Field("l0")) -+ Store(r1lo, out.Field("l1")) -+ Store(r2lo, out.Field("l2")) -+ Store(r3lo, out.Field("l3")) -+ Store(r4lo, out.Field("l4")) -+ -+ RET() -+} -+ -+func feMul() { -+ TEXT("feMul", NOSPLIT, "func(out, a, b *Element)") -+ Doc("feMul sets out = a * b. It works like feMulGeneric.") -+ Pragma("noescape") -+ -+ a := Dereference(Param("a")) -+ a0 := namedComponent{a.Field("l0"), "a0"} -+ a1 := namedComponent{a.Field("l1"), "a1"} -+ a2 := namedComponent{a.Field("l2"), "a2"} -+ a3 := namedComponent{a.Field("l3"), "a3"} -+ a4 := namedComponent{a.Field("l4"), "a4"} -+ -+ b := Dereference(Param("b")) -+ b0 := namedComponent{b.Field("l0"), "b0"} -+ b1 := namedComponent{b.Field("l1"), "b1"} -+ b2 := namedComponent{b.Field("l2"), "b2"} -+ b3 := namedComponent{b.Field("l3"), "b3"} -+ b4 := namedComponent{b.Field("l4"), "b4"} -+ -+ // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) -+ r0 := uint128{"r0", GP64(), GP64()} -+ mul64(r0, 1, a0, b0) -+ addMul64(r0, 19, a1, b4) -+ addMul64(r0, 19, a2, b3) -+ addMul64(r0, 19, a3, b2) -+ addMul64(r0, 19, a4, b1) -+ -+ // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) -+ r1 := uint128{"r1", GP64(), GP64()} -+ mul64(r1, 1, a0, b1) -+ addMul64(r1, 1, a1, b0) -+ addMul64(r1, 19, a2, b4) -+ addMul64(r1, 19, a3, b3) -+ addMul64(r1, 19, a4, b2) -+ -+ // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) -+ r2 := uint128{"r2", GP64(), GP64()} -+ mul64(r2, 1, a0, b2) -+ addMul64(r2, 1, a1, b1) -+ addMul64(r2, 1, a2, b0) -+ addMul64(r2, 19, a3, b4) -+ addMul64(r2, 19, a4, b3) -+ -+ // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 -+ r3 := uint128{"r3", GP64(), GP64()} -+ mul64(r3, 1, a0, b3) -+ addMul64(r3, 1, a1, b2) -+ addMul64(r3, 1, a2, b1) -+ addMul64(r3, 1, a3, b0) -+ addMul64(r3, 19, a4, b4) -+ -+ // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 -+ r4 := uint128{"r4", GP64(), GP64()} -+ mul64(r4, 1, a0, b4) -+ addMul64(r4, 1, a1, b3) -+ addMul64(r4, 1, a2, b2) -+ addMul64(r4, 1, a3, b1) -+ addMul64(r4, 1, a4, b0) -+ -+ Comment("First reduction chain") -+ maskLow51Bits := GP64() -+ MOVQ(Imm((1<<51)-1), maskLow51Bits) -+ c0, r0lo := shiftRightBy51(&r0) -+ c1, r1lo := shiftRightBy51(&r1) -+ c2, r2lo := shiftRightBy51(&r2) -+ c3, r3lo := shiftRightBy51(&r3) -+ c4, r4lo := shiftRightBy51(&r4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Second reduction chain (carryPropagate)") -+ // c0 = r0 >> 51 -+ MOVQ(r0lo, c0) -+ SHRQ(Imm(51), c0) -+ // c1 = r1 >> 51 -+ MOVQ(r1lo, c1) -+ SHRQ(Imm(51), c1) -+ // c2 = r2 >> 51 -+ MOVQ(r2lo, c2) -+ SHRQ(Imm(51), c2) -+ // c3 = r3 >> 51 -+ MOVQ(r3lo, c3) -+ SHRQ(Imm(51), c3) -+ // c4 = r4 >> 51 -+ MOVQ(r4lo, c4) -+ SHRQ(Imm(51), c4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Store output") -+ out := Dereference(Param("out")) -+ Store(r0lo, out.Field("l0")) -+ Store(r1lo, out.Field("l1")) -+ Store(r2lo, out.Field("l2")) -+ Store(r3lo, out.Field("l3")) -+ Store(r4lo, out.Field("l4")) -+ -+ RET() -+} -+ -+// mul64 sets r to i * aX * bX. -+func mul64(r uint128, i int, aX, bX namedComponent) { -+ switch i { -+ case 1: -+ Comment(fmt.Sprintf("%s = %s×%s", r, aX, bX)) -+ Load(aX, RAX) -+ case 2: -+ Comment(fmt.Sprintf("%s = 2×%s×%s", r, aX, bX)) -+ Load(aX, RAX) -+ SHLQ(Imm(1), RAX) -+ default: -+ panic("unsupported i value") -+ } -+ MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX -+ MOVQ(RAX, r.lo) -+ MOVQ(RDX, r.hi) -+} -+ -+// addMul64 sets r to r + i * aX * bX. -+func addMul64(r uint128, i uint64, aX, bX namedComponent) { -+ switch i { -+ case 1: -+ Comment(fmt.Sprintf("%s += %s×%s", r, aX, bX)) -+ Load(aX, RAX) -+ default: -+ Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) -+ IMUL3Q(Imm(i), Load(aX, GP64()), RAX) -+ } -+ MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX -+ ADDQ(RAX, r.lo) -+ ADCQ(RDX, r.hi) -+} -+ -+// shiftRightBy51 returns r >> 51 and r.lo. -+// -+// After this function is called, the uint128 may not be used anymore. -+func shiftRightBy51(r *uint128) (out, lo GPVirtual) { -+ out = r.hi -+ lo = r.lo -+ SHLQ(Imm(64-51), r.lo, r.hi) -+ r.lo, r.hi = nil, nil // make sure the uint128 is unusable -+ return -+} -+ -+// maskAndAdd sets r = r&mask + c*i. -+func maskAndAdd(r, mask, c GPVirtual, i uint64) { -+ ANDQ(mask, r) -+ if i != 1 { -+ IMUL3Q(Imm(i), c, c) -+ } -+ ADDQ(c, r) -+} -+ -+func mustAddr(c Component) Op { -+ b, err := c.Resolve() -+ if err != nil { -+ panic(err) -+ } -+ return b.Addr -+} -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod b/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod -new file mode 100644 -index 000000000000..fbc78be881cd ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod -@@ -0,0 +1,10 @@ -+module asm -+ -+go 1.16 -+ -+require ( -+ github.com/mmcloughlin/avo v0.2.0 -+ golang.org/x/crypto v0.0.0 -+) -+ -+replace golang.org/x/crypto v0.0.0 => ../../../.. -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum b/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum -new file mode 100644 -index 000000000000..e2361f6ab4fe ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum -@@ -0,0 +1,34 @@ -+github.com/mmcloughlin/avo v0.2.0 h1:6vhoSaKtxb6f4RiH+LK2qL6GSMpFzhEwJYTTSZNy09w= -+github.com/mmcloughlin/avo v0.2.0/go.mod h1:5tidO2Z9Z7N6X7UMcGg+1KTj51O8OxYDCMHxCZTVpEA= -+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -+golang.org/x/arch v0.0.0-20210405154355-08b684f594a5/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= -+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= -+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A= -+golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -+golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= -+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go -new file mode 100644 -index 000000000000..ca841ad99e3a ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go -@@ -0,0 +1,416 @@ -+// Copyright (c) 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 field implements fast arithmetic modulo 2^255-19. -+package field -+ -+import ( -+ "crypto/subtle" -+ "encoding/binary" -+ "math/bits" -+) -+ -+// Element represents an element of the field GF(2^255-19). Note that this -+// is not a cryptographically secure group, and should only be used to interact -+// with edwards25519.Point coordinates. -+// -+// This type works similarly to math/big.Int, and all arguments and receivers -+// are allowed to alias. -+// -+// The zero value is a valid zero element. -+type Element struct { -+ // An element t represents the integer -+ // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 -+ // -+ // Between operations, all limbs are expected to be lower than 2^52. -+ l0 uint64 -+ l1 uint64 -+ l2 uint64 -+ l3 uint64 -+ l4 uint64 -+} -+ -+const maskLow51Bits uint64 = (1 << 51) - 1 -+ -+var feZero = &Element{0, 0, 0, 0, 0} -+ -+// Zero sets v = 0, and returns v. -+func (v *Element) Zero() *Element { -+ *v = *feZero -+ return v -+} -+ -+var feOne = &Element{1, 0, 0, 0, 0} -+ -+// One sets v = 1, and returns v. -+func (v *Element) One() *Element { -+ *v = *feOne -+ return v -+} -+ -+// reduce reduces v modulo 2^255 - 19 and returns it. -+func (v *Element) reduce() *Element { -+ v.carryPropagate() -+ -+ // After the light reduction we now have a field element representation -+ // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. -+ -+ // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, -+ // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. -+ c := (v.l0 + 19) >> 51 -+ c = (v.l1 + c) >> 51 -+ c = (v.l2 + c) >> 51 -+ c = (v.l3 + c) >> 51 -+ c = (v.l4 + c) >> 51 -+ -+ // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's -+ // effectively applying the reduction identity to the carry. -+ v.l0 += 19 * c -+ -+ v.l1 += v.l0 >> 51 -+ v.l0 = v.l0 & maskLow51Bits -+ v.l2 += v.l1 >> 51 -+ v.l1 = v.l1 & maskLow51Bits -+ v.l3 += v.l2 >> 51 -+ v.l2 = v.l2 & maskLow51Bits -+ v.l4 += v.l3 >> 51 -+ v.l3 = v.l3 & maskLow51Bits -+ // no additional carry -+ v.l4 = v.l4 & maskLow51Bits -+ -+ return v -+} -+ -+// Add sets v = a + b, and returns v. -+func (v *Element) Add(a, b *Element) *Element { -+ v.l0 = a.l0 + b.l0 -+ v.l1 = a.l1 + b.l1 -+ v.l2 = a.l2 + b.l2 -+ v.l3 = a.l3 + b.l3 -+ v.l4 = a.l4 + b.l4 -+ // Using the generic implementation here is actually faster than the -+ // assembly. Probably because the body of this function is so simple that -+ // the compiler can figure out better optimizations by inlining the carry -+ // propagation. TODO -+ return v.carryPropagateGeneric() -+} -+ -+// Subtract sets v = a - b, and returns v. -+func (v *Element) Subtract(a, b *Element) *Element { -+ // We first add 2 * p, to guarantee the subtraction won't underflow, and -+ // then subtract b (which can be up to 2^255 + 2^13 * 19). -+ v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 -+ v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 -+ v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 -+ v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 -+ v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 -+ return v.carryPropagate() -+} -+ -+// Negate sets v = -a, and returns v. -+func (v *Element) Negate(a *Element) *Element { -+ return v.Subtract(feZero, a) -+} -+ -+// Invert sets v = 1/z mod p, and returns v. -+// -+// If z == 0, Invert returns v = 0. -+func (v *Element) Invert(z *Element) *Element { -+ // Inversion is implemented as exponentiation with exponent p − 2. It uses the -+ // same sequence of 255 squarings and 11 multiplications as [Curve25519]. -+ var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element -+ -+ z2.Square(z) // 2 -+ t.Square(&z2) // 4 -+ t.Square(&t) // 8 -+ z9.Multiply(&t, z) // 9 -+ z11.Multiply(&z9, &z2) // 11 -+ t.Square(&z11) // 22 -+ z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 -+ -+ t.Square(&z2_5_0) // 2^6 - 2^1 -+ for i := 0; i < 4; i++ { -+ t.Square(&t) // 2^10 - 2^5 -+ } -+ z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 -+ -+ t.Square(&z2_10_0) // 2^11 - 2^1 -+ for i := 0; i < 9; i++ { -+ t.Square(&t) // 2^20 - 2^10 -+ } -+ z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 -+ -+ t.Square(&z2_20_0) // 2^21 - 2^1 -+ for i := 0; i < 19; i++ { -+ t.Square(&t) // 2^40 - 2^20 -+ } -+ t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 -+ -+ t.Square(&t) // 2^41 - 2^1 -+ for i := 0; i < 9; i++ { -+ t.Square(&t) // 2^50 - 2^10 -+ } -+ z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 -+ -+ t.Square(&z2_50_0) // 2^51 - 2^1 -+ for i := 0; i < 49; i++ { -+ t.Square(&t) // 2^100 - 2^50 -+ } -+ z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 -+ -+ t.Square(&z2_100_0) // 2^101 - 2^1 -+ for i := 0; i < 99; i++ { -+ t.Square(&t) // 2^200 - 2^100 -+ } -+ t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 -+ -+ t.Square(&t) // 2^201 - 2^1 -+ for i := 0; i < 49; i++ { -+ t.Square(&t) // 2^250 - 2^50 -+ } -+ t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 -+ -+ t.Square(&t) // 2^251 - 2^1 -+ t.Square(&t) // 2^252 - 2^2 -+ t.Square(&t) // 2^253 - 2^3 -+ t.Square(&t) // 2^254 - 2^4 -+ t.Square(&t) // 2^255 - 2^5 -+ -+ return v.Multiply(&t, &z11) // 2^255 - 21 -+} -+ -+// Set sets v = a, and returns v. -+func (v *Element) Set(a *Element) *Element { -+ *v = *a -+ return v -+} -+ -+// SetBytes sets v to x, which must be a 32-byte little-endian encoding. -+// -+// Consistent with RFC 7748, the most significant bit (the high bit of the -+// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) -+// are accepted. Note that this is laxer than specified by RFC 8032. -+func (v *Element) SetBytes(x []byte) *Element { -+ if len(x) != 32 { -+ panic("edwards25519: invalid field element input size") -+ } -+ -+ // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). -+ v.l0 = binary.LittleEndian.Uint64(x[0:8]) -+ v.l0 &= maskLow51Bits -+ // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). -+ v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 -+ v.l1 &= maskLow51Bits -+ // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). -+ v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 -+ v.l2 &= maskLow51Bits -+ // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). -+ v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 -+ v.l3 &= maskLow51Bits -+ // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). -+ // Note: not bytes 25:33, shift 4, to avoid overread. -+ v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 -+ v.l4 &= maskLow51Bits -+ -+ return v -+} -+ -+// Bytes returns the canonical 32-byte little-endian encoding of v. -+func (v *Element) Bytes() []byte { -+ // This function is outlined to make the allocations inline in the caller -+ // rather than happen on the heap. -+ var out [32]byte -+ return v.bytes(&out) -+} -+ -+func (v *Element) bytes(out *[32]byte) []byte { -+ t := *v -+ t.reduce() -+ -+ var buf [8]byte -+ for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { -+ bitsOffset := i * 51 -+ binary.LittleEndian.PutUint64(buf[:], l<= len(out) { -+ break -+ } -+ out[off] |= bb -+ } -+ } -+ -+ return out[:] -+} -+ -+// Equal returns 1 if v and u are equal, and 0 otherwise. -+func (v *Element) Equal(u *Element) int { -+ sa, sv := u.Bytes(), v.Bytes() -+ return subtle.ConstantTimeCompare(sa, sv) -+} -+ -+// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. -+func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } -+ -+// Select sets v to a if cond == 1, and to b if cond == 0. -+func (v *Element) Select(a, b *Element, cond int) *Element { -+ m := mask64Bits(cond) -+ v.l0 = (m & a.l0) | (^m & b.l0) -+ v.l1 = (m & a.l1) | (^m & b.l1) -+ v.l2 = (m & a.l2) | (^m & b.l2) -+ v.l3 = (m & a.l3) | (^m & b.l3) -+ v.l4 = (m & a.l4) | (^m & b.l4) -+ return v -+} -+ -+// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. -+func (v *Element) Swap(u *Element, cond int) { -+ m := mask64Bits(cond) -+ t := m & (v.l0 ^ u.l0) -+ v.l0 ^= t -+ u.l0 ^= t -+ t = m & (v.l1 ^ u.l1) -+ v.l1 ^= t -+ u.l1 ^= t -+ t = m & (v.l2 ^ u.l2) -+ v.l2 ^= t -+ u.l2 ^= t -+ t = m & (v.l3 ^ u.l3) -+ v.l3 ^= t -+ u.l3 ^= t -+ t = m & (v.l4 ^ u.l4) -+ v.l4 ^= t -+ u.l4 ^= t -+} -+ -+// IsNegative returns 1 if v is negative, and 0 otherwise. -+func (v *Element) IsNegative() int { -+ return int(v.Bytes()[0] & 1) -+} -+ -+// Absolute sets v to |u|, and returns v. -+func (v *Element) Absolute(u *Element) *Element { -+ return v.Select(new(Element).Negate(u), u, u.IsNegative()) -+} -+ -+// Multiply sets v = x * y, and returns v. -+func (v *Element) Multiply(x, y *Element) *Element { -+ feMul(v, x, y) -+ return v -+} -+ -+// Square sets v = x * x, and returns v. -+func (v *Element) Square(x *Element) *Element { -+ feSquare(v, x) -+ return v -+} -+ -+// Mult32 sets v = x * y, and returns v. -+func (v *Element) Mult32(x *Element, y uint32) *Element { -+ x0lo, x0hi := mul51(x.l0, y) -+ x1lo, x1hi := mul51(x.l1, y) -+ x2lo, x2hi := mul51(x.l2, y) -+ x3lo, x3hi := mul51(x.l3, y) -+ x4lo, x4hi := mul51(x.l4, y) -+ v.l0 = x0lo + 19*x4hi // carried over per the reduction identity -+ v.l1 = x1lo + x0hi -+ v.l2 = x2lo + x1hi -+ v.l3 = x3lo + x2hi -+ v.l4 = x4lo + x3hi -+ // The hi portions are going to be only 32 bits, plus any previous excess, -+ // so we can skip the carry propagation. -+ return v -+} -+ -+// mul51 returns lo + hi * 2⁵¹ = a * b. -+func mul51(a uint64, b uint32) (lo uint64, hi uint64) { -+ mh, ml := bits.Mul64(a, uint64(b)) -+ lo = ml & maskLow51Bits -+ hi = (mh << 13) | (ml >> 51) -+ return -+} -+ -+// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. -+func (v *Element) Pow22523(x *Element) *Element { -+ var t0, t1, t2 Element -+ -+ t0.Square(x) // x^2 -+ t1.Square(&t0) // x^4 -+ t1.Square(&t1) // x^8 -+ t1.Multiply(x, &t1) // x^9 -+ t0.Multiply(&t0, &t1) // x^11 -+ t0.Square(&t0) // x^22 -+ t0.Multiply(&t1, &t0) // x^31 -+ t1.Square(&t0) // x^62 -+ for i := 1; i < 5; i++ { // x^992 -+ t1.Square(&t1) -+ } -+ t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 -+ t1.Square(&t0) // 2^11 - 2 -+ for i := 1; i < 10; i++ { // 2^20 - 2^10 -+ t1.Square(&t1) -+ } -+ t1.Multiply(&t1, &t0) // 2^20 - 1 -+ t2.Square(&t1) // 2^21 - 2 -+ for i := 1; i < 20; i++ { // 2^40 - 2^20 -+ t2.Square(&t2) -+ } -+ t1.Multiply(&t2, &t1) // 2^40 - 1 -+ t1.Square(&t1) // 2^41 - 2 -+ for i := 1; i < 10; i++ { // 2^50 - 2^10 -+ t1.Square(&t1) -+ } -+ t0.Multiply(&t1, &t0) // 2^50 - 1 -+ t1.Square(&t0) // 2^51 - 2 -+ for i := 1; i < 50; i++ { // 2^100 - 2^50 -+ t1.Square(&t1) -+ } -+ t1.Multiply(&t1, &t0) // 2^100 - 1 -+ t2.Square(&t1) // 2^101 - 2 -+ for i := 1; i < 100; i++ { // 2^200 - 2^100 -+ t2.Square(&t2) -+ } -+ t1.Multiply(&t2, &t1) // 2^200 - 1 -+ t1.Square(&t1) // 2^201 - 2 -+ for i := 1; i < 50; i++ { // 2^250 - 2^50 -+ t1.Square(&t1) -+ } -+ t0.Multiply(&t1, &t0) // 2^250 - 1 -+ t0.Square(&t0) // 2^251 - 2 -+ t0.Square(&t0) // 2^252 - 4 -+ return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) -+} -+ -+// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. -+var sqrtM1 = &Element{1718705420411056, 234908883556509, -+ 2233514472574048, 2117202627021982, 765476049583133} -+ -+// SqrtRatio sets r to the non-negative square root of the ratio of u and v. -+// -+// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio -+// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, -+// and returns r and 0. -+func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { -+ var a, b Element -+ -+ // r = (u * v3) * (u * v7)^((p-5)/8) -+ v2 := a.Square(v) -+ uv3 := b.Multiply(u, b.Multiply(v2, v)) -+ uv7 := a.Multiply(uv3, a.Square(v2)) -+ r.Multiply(uv3, r.Pow22523(uv7)) -+ -+ check := a.Multiply(v, a.Square(r)) // check = v * r^2 -+ -+ uNeg := b.Negate(u) -+ correctSignSqrt := check.Equal(u) -+ flippedSignSqrt := check.Equal(uNeg) -+ flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) -+ -+ rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r -+ // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) -+ r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) -+ -+ r.Absolute(r) // Choose the nonnegative square root. -+ return r, correctSignSqrt | flippedSignSqrt -+} -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go -new file mode 100644 -index 000000000000..44dc8e8caf91 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go -@@ -0,0 +1,13 @@ -+// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. -+ -+// +build amd64,gc,!purego -+ -+package field -+ -+// feMul sets out = a * b. It works like feMulGeneric. -+//go:noescape -+func feMul(out *Element, a *Element, b *Element) -+ -+// feSquare sets out = a * a. It works like feSquareGeneric. -+//go:noescape -+func feSquare(out *Element, a *Element) -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s -new file mode 100644 -index 000000000000..293f013c94a6 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s -@@ -0,0 +1,379 @@ -+// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+// func feMul(out *Element, a *Element, b *Element) -+TEXT ·feMul(SB), NOSPLIT, $0-24 -+ MOVQ a+8(FP), CX -+ MOVQ b+16(FP), BX -+ -+ // r0 = a0×b0 -+ MOVQ (CX), AX -+ MULQ (BX) -+ MOVQ AX, DI -+ MOVQ DX, SI -+ -+ // r0 += 19×a1×b4 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r0 += 19×a2×b3 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r0 += 19×a3×b2 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 16(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r0 += 19×a4×b1 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 8(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r1 = a0×b1 -+ MOVQ (CX), AX -+ MULQ 8(BX) -+ MOVQ AX, R9 -+ MOVQ DX, R8 -+ -+ // r1 += a1×b0 -+ MOVQ 8(CX), AX -+ MULQ (BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r1 += 19×a2×b4 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r1 += 19×a3×b3 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r1 += 19×a4×b2 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 16(BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r2 = a0×b2 -+ MOVQ (CX), AX -+ MULQ 16(BX) -+ MOVQ AX, R11 -+ MOVQ DX, R10 -+ -+ // r2 += a1×b1 -+ MOVQ 8(CX), AX -+ MULQ 8(BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r2 += a2×b0 -+ MOVQ 16(CX), AX -+ MULQ (BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r2 += 19×a3×b4 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r2 += 19×a4×b3 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r3 = a0×b3 -+ MOVQ (CX), AX -+ MULQ 24(BX) -+ MOVQ AX, R13 -+ MOVQ DX, R12 -+ -+ // r3 += a1×b2 -+ MOVQ 8(CX), AX -+ MULQ 16(BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r3 += a2×b1 -+ MOVQ 16(CX), AX -+ MULQ 8(BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r3 += a3×b0 -+ MOVQ 24(CX), AX -+ MULQ (BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r3 += 19×a4×b4 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r4 = a0×b4 -+ MOVQ (CX), AX -+ MULQ 32(BX) -+ MOVQ AX, R15 -+ MOVQ DX, R14 -+ -+ // r4 += a1×b3 -+ MOVQ 8(CX), AX -+ MULQ 24(BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // r4 += a2×b2 -+ MOVQ 16(CX), AX -+ MULQ 16(BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // r4 += a3×b1 -+ MOVQ 24(CX), AX -+ MULQ 8(BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // r4 += a4×b0 -+ MOVQ 32(CX), AX -+ MULQ (BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // First reduction chain -+ MOVQ $0x0007ffffffffffff, AX -+ SHLQ $0x0d, DI, SI -+ SHLQ $0x0d, R9, R8 -+ SHLQ $0x0d, R11, R10 -+ SHLQ $0x0d, R13, R12 -+ SHLQ $0x0d, R15, R14 -+ ANDQ AX, DI -+ IMUL3Q $0x13, R14, R14 -+ ADDQ R14, DI -+ ANDQ AX, R9 -+ ADDQ SI, R9 -+ ANDQ AX, R11 -+ ADDQ R8, R11 -+ ANDQ AX, R13 -+ ADDQ R10, R13 -+ ANDQ AX, R15 -+ ADDQ R12, R15 -+ -+ // Second reduction chain (carryPropagate) -+ MOVQ DI, SI -+ SHRQ $0x33, SI -+ MOVQ R9, R8 -+ SHRQ $0x33, R8 -+ MOVQ R11, R10 -+ SHRQ $0x33, R10 -+ MOVQ R13, R12 -+ SHRQ $0x33, R12 -+ MOVQ R15, R14 -+ SHRQ $0x33, R14 -+ ANDQ AX, DI -+ IMUL3Q $0x13, R14, R14 -+ ADDQ R14, DI -+ ANDQ AX, R9 -+ ADDQ SI, R9 -+ ANDQ AX, R11 -+ ADDQ R8, R11 -+ ANDQ AX, R13 -+ ADDQ R10, R13 -+ ANDQ AX, R15 -+ ADDQ R12, R15 -+ -+ // Store output -+ MOVQ out+0(FP), AX -+ MOVQ DI, (AX) -+ MOVQ R9, 8(AX) -+ MOVQ R11, 16(AX) -+ MOVQ R13, 24(AX) -+ MOVQ R15, 32(AX) -+ RET -+ -+// func feSquare(out *Element, a *Element) -+TEXT ·feSquare(SB), NOSPLIT, $0-16 -+ MOVQ a+8(FP), CX -+ -+ // r0 = l0×l0 -+ MOVQ (CX), AX -+ MULQ (CX) -+ MOVQ AX, SI -+ MOVQ DX, BX -+ -+ // r0 += 38×l1×l4 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, SI -+ ADCQ DX, BX -+ -+ // r0 += 38×l2×l3 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 24(CX) -+ ADDQ AX, SI -+ ADCQ DX, BX -+ -+ // r1 = 2×l0×l1 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 8(CX) -+ MOVQ AX, R8 -+ MOVQ DX, DI -+ -+ // r1 += 38×l2×l4 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, R8 -+ ADCQ DX, DI -+ -+ // r1 += 19×l3×l3 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(CX) -+ ADDQ AX, R8 -+ ADCQ DX, DI -+ -+ // r2 = 2×l0×l2 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 16(CX) -+ MOVQ AX, R10 -+ MOVQ DX, R9 -+ -+ // r2 += l1×l1 -+ MOVQ 8(CX), AX -+ MULQ 8(CX) -+ ADDQ AX, R10 -+ ADCQ DX, R9 -+ -+ // r2 += 38×l3×l4 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, R10 -+ ADCQ DX, R9 -+ -+ // r3 = 2×l0×l3 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 24(CX) -+ MOVQ AX, R12 -+ MOVQ DX, R11 -+ -+ // r3 += 2×l1×l2 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x02, AX, AX -+ MULQ 16(CX) -+ ADDQ AX, R12 -+ ADCQ DX, R11 -+ -+ // r3 += 19×l4×l4 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, R12 -+ ADCQ DX, R11 -+ -+ // r4 = 2×l0×l4 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 32(CX) -+ MOVQ AX, R14 -+ MOVQ DX, R13 -+ -+ // r4 += 2×l1×l3 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x02, AX, AX -+ MULQ 24(CX) -+ ADDQ AX, R14 -+ ADCQ DX, R13 -+ -+ // r4 += l2×l2 -+ MOVQ 16(CX), AX -+ MULQ 16(CX) -+ ADDQ AX, R14 -+ ADCQ DX, R13 -+ -+ // First reduction chain -+ MOVQ $0x0007ffffffffffff, AX -+ SHLQ $0x0d, SI, BX -+ SHLQ $0x0d, R8, DI -+ SHLQ $0x0d, R10, R9 -+ SHLQ $0x0d, R12, R11 -+ SHLQ $0x0d, R14, R13 -+ ANDQ AX, SI -+ IMUL3Q $0x13, R13, R13 -+ ADDQ R13, SI -+ ANDQ AX, R8 -+ ADDQ BX, R8 -+ ANDQ AX, R10 -+ ADDQ DI, R10 -+ ANDQ AX, R12 -+ ADDQ R9, R12 -+ ANDQ AX, R14 -+ ADDQ R11, R14 -+ -+ // Second reduction chain (carryPropagate) -+ MOVQ SI, BX -+ SHRQ $0x33, BX -+ MOVQ R8, DI -+ SHRQ $0x33, DI -+ MOVQ R10, R9 -+ SHRQ $0x33, R9 -+ MOVQ R12, R11 -+ SHRQ $0x33, R11 -+ MOVQ R14, R13 -+ SHRQ $0x33, R13 -+ ANDQ AX, SI -+ IMUL3Q $0x13, R13, R13 -+ ADDQ R13, SI -+ ANDQ AX, R8 -+ ADDQ BX, R8 -+ ANDQ AX, R10 -+ ADDQ DI, R10 -+ ANDQ AX, R12 -+ ADDQ R9, R12 -+ ANDQ AX, R14 -+ ADDQ R11, R14 -+ -+ // Store output -+ MOVQ out+0(FP), AX -+ MOVQ SI, (AX) -+ MOVQ R8, 8(AX) -+ MOVQ R10, 16(AX) -+ MOVQ R12, 24(AX) -+ MOVQ R14, 32(AX) -+ RET -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go -new file mode 100644 -index 000000000000..ddb6c9b8f7f2 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go -@@ -0,0 +1,12 @@ -+// Copyright (c) 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || !gc || purego -+// +build !amd64 !gc purego -+ -+package field -+ -+func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } -+ -+func feSquare(v, x *Element) { feSquareGeneric(v, x) } -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go -new file mode 100644 -index 000000000000..af459ef51549 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go -@@ -0,0 +1,16 @@ -+// Copyright (c) 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build arm64 && gc && !purego -+// +build arm64,gc,!purego -+ -+package field -+ -+//go:noescape -+func carryPropagate(v *Element) -+ -+func (v *Element) carryPropagate() *Element { -+ carryPropagate(v) -+ return v -+} -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s -new file mode 100644 -index 000000000000..5c91e458923e ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s -@@ -0,0 +1,43 @@ -+// Copyright (c) 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build arm64 && gc && !purego -+// +build arm64,gc,!purego -+ -+#include "textflag.h" -+ -+// carryPropagate works exactly like carryPropagateGeneric and uses the -+// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but -+// avoids loading R0-R4 twice and uses LDP and STP. -+// -+// See https://golang.org/issues/43145 for the main compiler issue. -+// -+// func carryPropagate(v *Element) -+TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 -+ MOVD v+0(FP), R20 -+ -+ LDP 0(R20), (R0, R1) -+ LDP 16(R20), (R2, R3) -+ MOVD 32(R20), R4 -+ -+ AND $0x7ffffffffffff, R0, R10 -+ AND $0x7ffffffffffff, R1, R11 -+ AND $0x7ffffffffffff, R2, R12 -+ AND $0x7ffffffffffff, R3, R13 -+ AND $0x7ffffffffffff, R4, R14 -+ -+ ADD R0>>51, R11, R11 -+ ADD R1>>51, R12, R12 -+ ADD R2>>51, R13, R13 -+ ADD R3>>51, R14, R14 -+ // R4>>51 * 19 + R10 -> R10 -+ LSR $51, R4, R21 -+ MOVD $19, R22 -+ MADD R22, R10, R21, R10 -+ -+ STP (R10, R11), 0(R20) -+ STP (R12, R13), 16(R20) -+ MOVD R14, 32(R20) -+ -+ RET -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go -new file mode 100644 -index 000000000000..234a5b2e5d18 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go -@@ -0,0 +1,12 @@ -+// Copyright (c) 2021 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !arm64 || !gc || purego -+// +build !arm64 !gc purego -+ -+package field -+ -+func (v *Element) carryPropagate() *Element { -+ return v.carryPropagateGeneric() -+} -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go -new file mode 100644 -index 000000000000..7b5b78cbd6d7 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go -@@ -0,0 +1,264 @@ -+// Copyright (c) 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 field -+ -+import "math/bits" -+ -+// uint128 holds a 128-bit number as two 64-bit limbs, for use with the -+// bits.Mul64 and bits.Add64 intrinsics. -+type uint128 struct { -+ lo, hi uint64 -+} -+ -+// mul64 returns a * b. -+func mul64(a, b uint64) uint128 { -+ hi, lo := bits.Mul64(a, b) -+ return uint128{lo, hi} -+} -+ -+// addMul64 returns v + a * b. -+func addMul64(v uint128, a, b uint64) uint128 { -+ hi, lo := bits.Mul64(a, b) -+ lo, c := bits.Add64(lo, v.lo, 0) -+ hi, _ = bits.Add64(hi, v.hi, c) -+ return uint128{lo, hi} -+} -+ -+// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. -+func shiftRightBy51(a uint128) uint64 { -+ return (a.hi << (64 - 51)) | (a.lo >> 51) -+} -+ -+func feMulGeneric(v, a, b *Element) { -+ a0 := a.l0 -+ a1 := a.l1 -+ a2 := a.l2 -+ a3 := a.l3 -+ a4 := a.l4 -+ -+ b0 := b.l0 -+ b1 := b.l1 -+ b2 := b.l2 -+ b3 := b.l3 -+ b4 := b.l4 -+ -+ // Limb multiplication works like pen-and-paper columnar multiplication, but -+ // with 51-bit limbs instead of digits. -+ // -+ // a4 a3 a2 a1 a0 x -+ // b4 b3 b2 b1 b0 = -+ // ------------------------ -+ // a4b0 a3b0 a2b0 a1b0 a0b0 + -+ // a4b1 a3b1 a2b1 a1b1 a0b1 + -+ // a4b2 a3b2 a2b2 a1b2 a0b2 + -+ // a4b3 a3b3 a2b3 a1b3 a0b3 + -+ // a4b4 a3b4 a2b4 a1b4 a0b4 = -+ // ---------------------------------------------- -+ // r8 r7 r6 r5 r4 r3 r2 r1 r0 -+ // -+ // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to -+ // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5, -+ // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc. -+ // -+ // Reduction can be carried out simultaneously to multiplication. For -+ // example, we do not compute r5: whenever the result of a multiplication -+ // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. -+ // -+ // a4b0 a3b0 a2b0 a1b0 a0b0 + -+ // a3b1 a2b1 a1b1 a0b1 19×a4b1 + -+ // a2b2 a1b2 a0b2 19×a4b2 19×a3b2 + -+ // a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 + -+ // a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 = -+ // -------------------------------------- -+ // r4 r3 r2 r1 r0 -+ // -+ // Finally we add up the columns into wide, overlapping limbs. -+ -+ a1_19 := a1 * 19 -+ a2_19 := a2 * 19 -+ a3_19 := a3 * 19 -+ a4_19 := a4 * 19 -+ -+ // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) -+ r0 := mul64(a0, b0) -+ r0 = addMul64(r0, a1_19, b4) -+ r0 = addMul64(r0, a2_19, b3) -+ r0 = addMul64(r0, a3_19, b2) -+ r0 = addMul64(r0, a4_19, b1) -+ -+ // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) -+ r1 := mul64(a0, b1) -+ r1 = addMul64(r1, a1, b0) -+ r1 = addMul64(r1, a2_19, b4) -+ r1 = addMul64(r1, a3_19, b3) -+ r1 = addMul64(r1, a4_19, b2) -+ -+ // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) -+ r2 := mul64(a0, b2) -+ r2 = addMul64(r2, a1, b1) -+ r2 = addMul64(r2, a2, b0) -+ r2 = addMul64(r2, a3_19, b4) -+ r2 = addMul64(r2, a4_19, b3) -+ -+ // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 -+ r3 := mul64(a0, b3) -+ r3 = addMul64(r3, a1, b2) -+ r3 = addMul64(r3, a2, b1) -+ r3 = addMul64(r3, a3, b0) -+ r3 = addMul64(r3, a4_19, b4) -+ -+ // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 -+ r4 := mul64(a0, b4) -+ r4 = addMul64(r4, a1, b3) -+ r4 = addMul64(r4, a2, b2) -+ r4 = addMul64(r4, a3, b1) -+ r4 = addMul64(r4, a4, b0) -+ -+ // After the multiplication, we need to reduce (carry) the five coefficients -+ // to obtain a result with limbs that are at most slightly larger than 2⁵¹, -+ // to respect the Element invariant. -+ // -+ // Overall, the reduction works the same as carryPropagate, except with -+ // wider inputs: we take the carry for each coefficient by shifting it right -+ // by 51, and add it to the limb above it. The top carry is multiplied by 19 -+ // according to the reduction identity and added to the lowest limb. -+ // -+ // The largest coefficient (r0) will be at most 111 bits, which guarantees -+ // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. -+ // -+ // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) -+ // r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²) -+ // r0 < (1 + 19 × 4) × 2⁵² × 2⁵² -+ // r0 < 2⁷ × 2⁵² × 2⁵² -+ // r0 < 2¹¹¹ -+ // -+ // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most -+ // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and -+ // allows us to easily apply the reduction identity. -+ // -+ // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 -+ // r4 < 5 × 2⁵² × 2⁵² -+ // r4 < 2¹⁰⁷ -+ // -+ -+ c0 := shiftRightBy51(r0) -+ c1 := shiftRightBy51(r1) -+ c2 := shiftRightBy51(r2) -+ c3 := shiftRightBy51(r3) -+ c4 := shiftRightBy51(r4) -+ -+ rr0 := r0.lo&maskLow51Bits + c4*19 -+ rr1 := r1.lo&maskLow51Bits + c0 -+ rr2 := r2.lo&maskLow51Bits + c1 -+ rr3 := r3.lo&maskLow51Bits + c2 -+ rr4 := r4.lo&maskLow51Bits + c3 -+ -+ // Now all coefficients fit into 64-bit registers but are still too large to -+ // be passed around as a Element. We therefore do one last carry chain, -+ // where the carries will be small enough to fit in the wiggle room above 2⁵¹. -+ *v = Element{rr0, rr1, rr2, rr3, rr4} -+ v.carryPropagate() -+} -+ -+func feSquareGeneric(v, a *Element) { -+ l0 := a.l0 -+ l1 := a.l1 -+ l2 := a.l2 -+ l3 := a.l3 -+ l4 := a.l4 -+ -+ // Squaring works precisely like multiplication above, but thanks to its -+ // symmetry we get to group a few terms together. -+ // -+ // l4 l3 l2 l1 l0 x -+ // l4 l3 l2 l1 l0 = -+ // ------------------------ -+ // l4l0 l3l0 l2l0 l1l0 l0l0 + -+ // l4l1 l3l1 l2l1 l1l1 l0l1 + -+ // l4l2 l3l2 l2l2 l1l2 l0l2 + -+ // l4l3 l3l3 l2l3 l1l3 l0l3 + -+ // l4l4 l3l4 l2l4 l1l4 l0l4 = -+ // ---------------------------------------------- -+ // r8 r7 r6 r5 r4 r3 r2 r1 r0 -+ // -+ // l4l0 l3l0 l2l0 l1l0 l0l0 + -+ // l3l1 l2l1 l1l1 l0l1 19×l4l1 + -+ // l2l2 l1l2 l0l2 19×l4l2 19×l3l2 + -+ // l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 + -+ // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = -+ // -------------------------------------- -+ // r4 r3 r2 r1 r0 -+ // -+ // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with -+ // only three Mul64 and four Add64, instead of five and eight. -+ -+ l0_2 := l0 * 2 -+ l1_2 := l1 * 2 -+ -+ l1_38 := l1 * 38 -+ l2_38 := l2 * 38 -+ l3_38 := l3 * 38 -+ -+ l3_19 := l3 * 19 -+ l4_19 := l4 * 19 -+ -+ // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) -+ r0 := mul64(l0, l0) -+ r0 = addMul64(r0, l1_38, l4) -+ r0 = addMul64(r0, l2_38, l3) -+ -+ // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 -+ r1 := mul64(l0_2, l1) -+ r1 = addMul64(r1, l2_38, l4) -+ r1 = addMul64(r1, l3_19, l3) -+ -+ // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 -+ r2 := mul64(l0_2, l2) -+ r2 = addMul64(r2, l1, l1) -+ r2 = addMul64(r2, l3_38, l4) -+ -+ // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 -+ r3 := mul64(l0_2, l3) -+ r3 = addMul64(r3, l1_2, l2) -+ r3 = addMul64(r3, l4_19, l4) -+ -+ // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 -+ r4 := mul64(l0_2, l4) -+ r4 = addMul64(r4, l1_2, l3) -+ r4 = addMul64(r4, l2, l2) -+ -+ c0 := shiftRightBy51(r0) -+ c1 := shiftRightBy51(r1) -+ c2 := shiftRightBy51(r2) -+ c3 := shiftRightBy51(r3) -+ c4 := shiftRightBy51(r4) -+ -+ rr0 := r0.lo&maskLow51Bits + c4*19 -+ rr1 := r1.lo&maskLow51Bits + c0 -+ rr2 := r2.lo&maskLow51Bits + c1 -+ rr3 := r3.lo&maskLow51Bits + c2 -+ rr4 := r4.lo&maskLow51Bits + c3 -+ -+ *v = Element{rr0, rr1, rr2, rr3, rr4} -+ v.carryPropagate() -+} -+ -+// carryPropagate brings the limbs below 52 bits by applying the reduction -+// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline -+func (v *Element) carryPropagateGeneric() *Element { -+ c0 := v.l0 >> 51 -+ c1 := v.l1 >> 51 -+ c2 := v.l2 >> 51 -+ c3 := v.l3 >> 51 -+ c4 := v.l4 >> 51 -+ -+ v.l0 = v.l0&maskLow51Bits + c4*19 -+ v.l1 = v.l1&maskLow51Bits + c0 -+ v.l2 = v.l2&maskLow51Bits + c1 -+ v.l3 = v.l3&maskLow51Bits + c2 -+ v.l4 = v.l4&maskLow51Bits + c3 -+ -+ return v -+} -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint -new file mode 100644 -index 000000000000..e3685f95cab2 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint -@@ -0,0 +1 @@ -+b0c49ae9f59d233526f8934262c5bbbe14d4358d -diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh -new file mode 100755 -index 000000000000..1ba22a8b4c9a ---- /dev/null -+++ b/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh -@@ -0,0 +1,19 @@ -+#! /bin/bash -+set -euo pipefail -+ -+cd "$(git rev-parse --show-toplevel)" -+ -+STD_PATH=src/crypto/ed25519/internal/edwards25519/field -+LOCAL_PATH=curve25519/internal/field -+LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint) -+ -+git fetch https://go.googlesource.com/go master -+ -+if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then -+ echo "No changes." -+else -+ NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint) -+ echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..." -+ git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \ -+ git apply -3 --directory=$LOCAL_PATH -+fi -diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go -index c7f8c7e64ec8..a7828345fcc4 100644 ---- a/vendor/golang.org/x/crypto/ed25519/ed25519.go -+++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go -@@ -1,12 +1,7 @@ --// Copyright 2016 The Go Authors. All rights reserved. -+// Copyright 2019 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// In Go 1.13, the ed25519 package was promoted to the standard library as --// crypto/ed25519, and this package became a wrapper for the standard library one. --// --// +build !go1.13 -- - // Package ed25519 implements the Ed25519 signature algorithm. See - // https://ed25519.cr.yp.to/. - // -@@ -15,21 +10,15 @@ - // representation includes a public key suffix to make multiple signing - // operations with the same key more efficient. This package refers to the RFC - // 8032 private key as the “seed”. -+// -+// Beginning with Go 1.13, the functionality of this package was moved to the -+// standard library as crypto/ed25519. This package only acts as a compatibility -+// wrapper. - package ed25519 - --// This code is a port of the public domain, “ref10” implementation of ed25519 --// from SUPERCOP. -- - import ( -- "bytes" -- "crypto" -- cryptorand "crypto/rand" -- "crypto/sha512" -- "errors" -+ "crypto/ed25519" - "io" -- "strconv" -- -- "golang.org/x/crypto/ed25519/internal/edwards25519" - ) - - const ( -@@ -44,57 +33,21 @@ const ( - ) - - // PublicKey is the type of Ed25519 public keys. --type PublicKey []byte -+// -+// This type is an alias for crypto/ed25519's PublicKey type. -+// See the crypto/ed25519 package for the methods on this type. -+type PublicKey = ed25519.PublicKey - - // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. --type PrivateKey []byte -- --// Public returns the PublicKey corresponding to priv. --func (priv PrivateKey) Public() crypto.PublicKey { -- publicKey := make([]byte, PublicKeySize) -- copy(publicKey, priv[32:]) -- return PublicKey(publicKey) --} -- --// Seed returns the private key seed corresponding to priv. It is provided for --// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds --// in this package. --func (priv PrivateKey) Seed() []byte { -- seed := make([]byte, SeedSize) -- copy(seed, priv[:32]) -- return seed --} -- --// Sign signs the given message with priv. --// Ed25519 performs two passes over messages to be signed and therefore cannot --// handle pre-hashed messages. Thus opts.HashFunc() must return zero to --// indicate the message hasn't been hashed. This can be achieved by passing --// crypto.Hash(0) as the value for opts. --func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { -- if opts.HashFunc() != crypto.Hash(0) { -- return nil, errors.New("ed25519: cannot sign hashed message") -- } -- -- return Sign(priv, message), nil --} -+// -+// This type is an alias for crypto/ed25519's PrivateKey type. -+// See the crypto/ed25519 package for the methods on this type. -+type PrivateKey = ed25519.PrivateKey - - // GenerateKey generates a public/private key pair using entropy from rand. - // If rand is nil, crypto/rand.Reader will be used. - func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { -- if rand == nil { -- rand = cryptorand.Reader -- } -- -- seed := make([]byte, SeedSize) -- if _, err := io.ReadFull(rand, seed); err != nil { -- return nil, nil, err -- } -- -- privateKey := NewKeyFromSeed(seed) -- publicKey := make([]byte, PublicKeySize) -- copy(publicKey, privateKey[32:]) -- -- return publicKey, privateKey, nil -+ return ed25519.GenerateKey(rand) - } - - // NewKeyFromSeed calculates a private key from a seed. It will panic if -@@ -102,121 +55,17 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - // with RFC 8032. RFC 8032's private keys correspond to seeds in this - // package. - func NewKeyFromSeed(seed []byte) PrivateKey { -- if l := len(seed); l != SeedSize { -- panic("ed25519: bad seed length: " + strconv.Itoa(l)) -- } -- -- digest := sha512.Sum512(seed) -- digest[0] &= 248 -- digest[31] &= 127 -- digest[31] |= 64 -- -- var A edwards25519.ExtendedGroupElement -- var hBytes [32]byte -- copy(hBytes[:], digest[:]) -- edwards25519.GeScalarMultBase(&A, &hBytes) -- var publicKeyBytes [32]byte -- A.ToBytes(&publicKeyBytes) -- -- privateKey := make([]byte, PrivateKeySize) -- copy(privateKey, seed) -- copy(privateKey[32:], publicKeyBytes[:]) -- -- return privateKey -+ return ed25519.NewKeyFromSeed(seed) - } - - // Sign signs the message with privateKey and returns a signature. It will - // panic if len(privateKey) is not PrivateKeySize. - func Sign(privateKey PrivateKey, message []byte) []byte { -- if l := len(privateKey); l != PrivateKeySize { -- panic("ed25519: bad private key length: " + strconv.Itoa(l)) -- } -- -- h := sha512.New() -- h.Write(privateKey[:32]) -- -- var digest1, messageDigest, hramDigest [64]byte -- var expandedSecretKey [32]byte -- h.Sum(digest1[:0]) -- copy(expandedSecretKey[:], digest1[:]) -- expandedSecretKey[0] &= 248 -- expandedSecretKey[31] &= 63 -- expandedSecretKey[31] |= 64 -- -- h.Reset() -- h.Write(digest1[32:]) -- h.Write(message) -- h.Sum(messageDigest[:0]) -- -- var messageDigestReduced [32]byte -- edwards25519.ScReduce(&messageDigestReduced, &messageDigest) -- var R edwards25519.ExtendedGroupElement -- edwards25519.GeScalarMultBase(&R, &messageDigestReduced) -- -- var encodedR [32]byte -- R.ToBytes(&encodedR) -- -- h.Reset() -- h.Write(encodedR[:]) -- h.Write(privateKey[32:]) -- h.Write(message) -- h.Sum(hramDigest[:0]) -- var hramDigestReduced [32]byte -- edwards25519.ScReduce(&hramDigestReduced, &hramDigest) -- -- var s [32]byte -- edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) -- -- signature := make([]byte, SignatureSize) -- copy(signature[:], encodedR[:]) -- copy(signature[32:], s[:]) -- -- return signature -+ return ed25519.Sign(privateKey, message) - } - - // Verify reports whether sig is a valid signature of message by publicKey. It - // will panic if len(publicKey) is not PublicKeySize. - func Verify(publicKey PublicKey, message, sig []byte) bool { -- if l := len(publicKey); l != PublicKeySize { -- panic("ed25519: bad public key length: " + strconv.Itoa(l)) -- } -- -- if len(sig) != SignatureSize || sig[63]&224 != 0 { -- return false -- } -- -- var A edwards25519.ExtendedGroupElement -- var publicKeyBytes [32]byte -- copy(publicKeyBytes[:], publicKey) -- if !A.FromBytes(&publicKeyBytes) { -- return false -- } -- edwards25519.FeNeg(&A.X, &A.X) -- edwards25519.FeNeg(&A.T, &A.T) -- -- h := sha512.New() -- h.Write(sig[:32]) -- h.Write(publicKey[:]) -- h.Write(message) -- var digest [64]byte -- h.Sum(digest[:0]) -- -- var hReduced [32]byte -- edwards25519.ScReduce(&hReduced, &digest) -- -- var R edwards25519.ProjectiveGroupElement -- var s [32]byte -- copy(s[:], sig[32:]) -- -- // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in -- // the range [0, order) in order to prevent signature malleability. -- if !edwards25519.ScMinimal(&s) { -- return false -- } -- -- edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) -- -- var checkR [32]byte -- R.ToBytes(&checkR) -- return bytes.Equal(sig[:32], checkR[:]) -+ return ed25519.Verify(publicKey, message, sig) - } -diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go b/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go -deleted file mode 100644 -index d1448d8d2202..000000000000 ---- a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go -+++ /dev/null -@@ -1,73 +0,0 @@ --// Copyright 2019 The Go Authors. All rights reserved. --// Use of this source code is governed by a BSD-style --// license that can be found in the LICENSE file. -- --// +build go1.13 -- --// Package ed25519 implements the Ed25519 signature algorithm. See --// https://ed25519.cr.yp.to/. --// --// These functions are also compatible with the “Ed25519” function defined in --// RFC 8032. However, unlike RFC 8032's formulation, this package's private key --// representation includes a public key suffix to make multiple signing --// operations with the same key more efficient. This package refers to the RFC --// 8032 private key as the “seed”. --// --// Beginning with Go 1.13, the functionality of this package was moved to the --// standard library as crypto/ed25519. This package only acts as a compatibility --// wrapper. --package ed25519 -- --import ( -- "crypto/ed25519" -- "io" --) -- --const ( -- // PublicKeySize is the size, in bytes, of public keys as used in this package. -- PublicKeySize = 32 -- // PrivateKeySize is the size, in bytes, of private keys as used in this package. -- PrivateKeySize = 64 -- // SignatureSize is the size, in bytes, of signatures generated and verified by this package. -- SignatureSize = 64 -- // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. -- SeedSize = 32 --) -- --// PublicKey is the type of Ed25519 public keys. --// --// This type is an alias for crypto/ed25519's PublicKey type. --// See the crypto/ed25519 package for the methods on this type. --type PublicKey = ed25519.PublicKey -- --// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. --// --// This type is an alias for crypto/ed25519's PrivateKey type. --// See the crypto/ed25519 package for the methods on this type. --type PrivateKey = ed25519.PrivateKey -- --// GenerateKey generates a public/private key pair using entropy from rand. --// If rand is nil, crypto/rand.Reader will be used. --func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { -- return ed25519.GenerateKey(rand) --} -- --// NewKeyFromSeed calculates a private key from a seed. It will panic if --// len(seed) is not SeedSize. This function is provided for interoperability --// with RFC 8032. RFC 8032's private keys correspond to seeds in this --// package. --func NewKeyFromSeed(seed []byte) PrivateKey { -- return ed25519.NewKeyFromSeed(seed) --} -- --// Sign signs the message with privateKey and returns a signature. It will --// panic if len(privateKey) is not PrivateKeySize. --func Sign(privateKey PrivateKey, message []byte) []byte { -- return ed25519.Sign(privateKey, message) --} -- --// Verify reports whether sig is a valid signature of message by publicKey. It --// will panic if len(publicKey) is not PublicKeySize. --func Verify(publicKey PublicKey, message, sig []byte) bool { -- return ed25519.Verify(publicKey, message, sig) --} -diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go -deleted file mode 100644 -index e39f086c1d87..000000000000 ---- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go -+++ /dev/null -@@ -1,1422 +0,0 @@ --// Copyright 2016 The Go Authors. All rights reserved. --// Use of this source code is governed by a BSD-style --// license that can be found in the LICENSE file. -- --package edwards25519 -- --// These values are from the public domain, “ref10” implementation of ed25519 --// from SUPERCOP. -- --// d is a constant in the Edwards curve equation. --var d = FieldElement{ -- -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, --} -- --// d2 is 2*d. --var d2 = FieldElement{ -- -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, --} -- --// SqrtM1 is the square-root of -1 in the field. --var SqrtM1 = FieldElement{ -- -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, --} -- --// A is a constant in the Montgomery-form of curve25519. --var A = FieldElement{ -- 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, --} -- --// bi contains precomputed multiples of the base-point. See the Ed25519 paper --// for a discussion about how these values are used. --var bi = [8]PreComputedGroupElement{ -- { -- FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, -- FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, -- FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, -- }, -- { -- FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, -- FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, -- FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, -- }, -- { -- FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, -- FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, -- FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, -- }, -- { -- FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, -- FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, -- FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, -- }, -- { -- FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877}, -- FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951}, -- FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}, -- }, -- { -- FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436}, -- FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918}, -- FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}, -- }, -- { -- FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800}, -- FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305}, -- FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}, -- }, -- { -- FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876}, -- FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619}, -- FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}, -- }, --} -- --// base contains precomputed multiples of the base-point. See the Ed25519 paper --// for a discussion about how these values are used. --var base = [32][8]PreComputedGroupElement{ -- { -- { -- FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, -- FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, -- FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, -- }, -- { -- FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303}, -- FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081}, -- FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}, -- }, -- { -- FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, -- FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, -- FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, -- }, -- { -- FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, -- FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, -- FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}, -- }, -- { -- FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, -- FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, -- FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, -- }, -- { -- FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777}, -- FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737}, -- FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}, -- }, -- { -- FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, -- FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, -- FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, -- }, -- { -- FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, -- FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, -- FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}, -- }, -- }, -- { -- { -- FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, -- FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, -- FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}, -- }, -- { -- FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, -- FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, -- FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}, -- }, -- { -- FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, -- FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, -- FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}, -- }, -- { -- FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, -- FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, -- FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}, -- }, -- { -- FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, -- FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, -- FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}, -- }, -- { -- FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, -- FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, -- FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}, -- }, -- { -- FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, -- FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, -- FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}, -- }, -- { -- FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, -- FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, -- FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}, -- }, -- }, -- { -- { -- FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, -- FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, -- FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}, -- }, -- { -- FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, -- FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, -- FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}, -- }, -- { -- FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, -- FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, -- FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}, -- }, -- { -- FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, -- FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, -- FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}, -- }, -- { -- FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, -- FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, -- FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}, -- }, -- { -- FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, -- FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, -- FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}, -- }, -- { -- FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, -- FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, -- FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}, -- }, -- { -- FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, -- FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, -- FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}, -- }, -- }, -- { -- { -- FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, -- FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, -- FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}, -- }, -- { -- FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, -- FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, -- FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}, -- }, -- { -- FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, -- FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, -- FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}, -- }, -- { -- FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, -- FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, -- FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}, -- }, -- { -- FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, -- FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, -- FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}, -- }, -- { -- FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, -- FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, -- FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}, -- }, -- { -- FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, -- FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, -- FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}, -- }, -- { -- FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, -- FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, -- FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}, -- }, -- }, -- { -- { -- FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, -- FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, -- FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}, -- }, -- { -- FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, -- FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, -- FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}, -- }, -- { -- FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, -- FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, -- FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}, -- }, -- { -- FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, -- FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, -- FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}, -- }, -- { -- FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, -- FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, -- FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}, -- }, -- { -- FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, -- FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, -- FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}, -- }, -- { -- FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, -- FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, -- FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}, -- }, -- { -- FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, -- FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, -- FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}, -- }, -- }, -- { -- { -- FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, -- FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, -- FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}, -- }, -- { -- FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, -- FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, -- FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}, -- }, -- { -- FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, -- FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, -- FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}, -- }, -- { -- FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, -- FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, -- FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}, -- }, -- { -- FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, -- FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, -- FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}, -- }, -- { -- FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, -- FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, -- FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}, -- }, -- { -- FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, -- FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, -- FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}, -- }, -- { -- FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, -- FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, -- FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}, -- }, -- }, -- { -- { -- FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, -- FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, -- FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}, -- }, -- { -- FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, -- FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, -- FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}, -- }, -- { -- FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, -- FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, -- FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}, -- }, -- { -- FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, -- FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, -- FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}, -- }, -- { -- FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, -- FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, -- FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}, -- }, -- { -- FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, -- FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, -- FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}, -- }, -- { -- FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, -- FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, -- FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}, -- }, -- { -- FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, -- FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, -- FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}, -- }, -- }, -- { -- { -- FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, -- FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, -- FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}, -- }, -- { -- FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, -- FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, -- FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}, -- }, -- { -- FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, -- FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, -- FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}, -- }, -- { -- FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, -- FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, -- FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}, -- }, -- { -- FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, -- FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, -- FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}, -- }, -- { -- FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, -- FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, -- FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}, -- }, -- { -- FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, -- FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, -- FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}, -- }, -- { -- FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, -- FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, -- FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}, -- }, -- }, -- { -- { -- FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, -- FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, -- FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}, -- }, -- { -- FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, -- FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, -- FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}, -- }, -- { -- FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, -- FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, -- FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}, -- }, -- { -- FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, -- FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, -- FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}, -- }, -- { -- FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, -- FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, -- FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}, -- }, -- { -- FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, -- FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, -- FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}, -- }, -- { -- FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, -- FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, -- FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}, -- }, -- { -- FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, -- FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, -- FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}, -- }, -- }, -- { -- { -- FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, -- FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, -- FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}, -- }, -- { -- FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, -- FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, -- FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}, -- }, -- { -- FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, -- FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, -- FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}, -- }, -- { -- FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, -- FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, -- FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}, -- }, -- { -- FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, -- FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, -- FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}, -- }, -- { -- FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, -- FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, -- FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}, -- }, -- { -- FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, -- FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, -- FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}, -- }, -- { -- FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, -- FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, -- FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}, -- }, -- }, -- { -- { -- FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, -- FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, -- FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}, -- }, -- { -- FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, -- FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, -- FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}, -- }, -- { -- FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, -- FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, -- FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}, -- }, -- { -- FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, -- FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, -- FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}, -- }, -- { -- FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, -- FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, -- FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}, -- }, -- { -- FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, -- FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, -- FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}, -- }, -- { -- FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, -- FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, -- FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}, -- }, -- { -- FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, -- FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, -- FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}, -- }, -- }, -- { -- { -- FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, -- FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, -- FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}, -- }, -- { -- FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, -- FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, -- FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}, -- }, -- { -- FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, -- FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, -- FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}, -- }, -- { -- FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, -- FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, -- FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}, -- }, -- { -- FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, -- FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, -- FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}, -- }, -- { -- FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, -- FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, -- FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}, -- }, -- { -- FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, -- FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, -- FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}, -- }, -- { -- FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, -- FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, -- FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}, -- }, -- }, -- { -- { -- FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, -- FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, -- FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}, -- }, -- { -- FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, -- FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, -- FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}, -- }, -- { -- FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, -- FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, -- FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}, -- }, -- { -- FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, -- FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, -- FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}, -- }, -- { -- FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, -- FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, -- FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}, -- }, -- { -- FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, -- FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, -- FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}, -- }, -- { -- FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, -- FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, -- FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}, -- }, -- { -- FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, -- FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, -- FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}, -- }, -- }, -- { -- { -- FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, -- FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, -- FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}, -- }, -- { -- FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, -- FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, -- FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}, -- }, -- { -- FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, -- FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, -- FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}, -- }, -- { -- FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, -- FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, -- FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}, -- }, -- { -- FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, -- FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, -- FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}, -- }, -- { -- FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, -- FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, -- FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}, -- }, -- { -- FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, -- FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, -- FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}, -- }, -- { -- FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, -- FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, -- FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}, -- }, -- }, -- { -- { -- FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, -- FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, -- FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}, -- }, -- { -- FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, -- FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, -- FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}, -- }, -- { -- FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, -- FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, -- FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}, -- }, -- { -- FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, -- FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, -- FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}, -- }, -- { -- FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, -- FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, -- FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}, -- }, -- { -- FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, -- FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, -- FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}, -- }, -- { -- FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, -- FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, -- FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}, -- }, -- { -- FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, -- FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, -- FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}, -- }, -- }, -- { -- { -- FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, -- FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, -- FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}, -- }, -- { -- FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, -- FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, -- FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}, -- }, -- { -- FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, -- FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, -- FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}, -- }, -- { -- FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, -- FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, -- FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}, -- }, -- { -- FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, -- FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, -- FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}, -- }, -- { -- FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, -- FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, -- FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}, -- }, -- { -- FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, -- FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, -- FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}, -- }, -- { -- FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, -- FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, -- FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}, -- }, -- }, -- { -- { -- FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, -- FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, -- FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}, -- }, -- { -- FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, -- FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, -- FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}, -- }, -- { -- FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, -- FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, -- FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}, -- }, -- { -- FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, -- FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, -- FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}, -- }, -- { -- FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, -- FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, -- FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}, -- }, -- { -- FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, -- FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, -- FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}, -- }, -- { -- FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, -- FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, -- FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}, -- }, -- { -- FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, -- FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, -- FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}, -- }, -- }, -- { -- { -- FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, -- FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, -- FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}, -- }, -- { -- FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, -- FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, -- FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}, -- }, -- { -- FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, -- FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, -- FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}, -- }, -- { -- FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, -- FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, -- FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}, -- }, -- { -- FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, -- FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, -- FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}, -- }, -- { -- FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, -- FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, -- FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}, -- }, -- { -- FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, -- FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, -- FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}, -- }, -- { -- FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, -- FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, -- FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}, -- }, -- }, -- { -- { -- FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, -- FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, -- FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}, -- }, -- { -- FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, -- FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, -- FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}, -- }, -- { -- FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, -- FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, -- FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}, -- }, -- { -- FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, -- FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, -- FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}, -- }, -- { -- FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, -- FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, -- FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}, -- }, -- { -- FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, -- FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, -- FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}, -- }, -- { -- FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, -- FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, -- FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}, -- }, -- { -- FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, -- FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, -- FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}, -- }, -- }, -- { -- { -- FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, -- FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, -- FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}, -- }, -- { -- FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, -- FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, -- FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}, -- }, -- { -- FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, -- FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, -- FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}, -- }, -- { -- FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, -- FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, -- FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}, -- }, -- { -- FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, -- FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, -- FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}, -- }, -- { -- FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, -- FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, -- FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}, -- }, -- { -- FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, -- FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, -- FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}, -- }, -- { -- FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, -- FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, -- FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}, -- }, -- }, -- { -- { -- FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, -- FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, -- FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}, -- }, -- { -- FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, -- FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, -- FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}, -- }, -- { -- FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, -- FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, -- FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}, -- }, -- { -- FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, -- FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, -- FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}, -- }, -- { -- FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, -- FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, -- FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}, -- }, -- { -- FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, -- FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, -- FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}, -- }, -- { -- FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, -- FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, -- FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}, -- }, -- { -- FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, -- FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, -- FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}, -- }, -- }, -- { -- { -- FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, -- FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, -- FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}, -- }, -- { -- FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, -- FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, -- FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}, -- }, -- { -- FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, -- FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, -- FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}, -- }, -- { -- FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, -- FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, -- FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}, -- }, -- { -- FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, -- FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, -- FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}, -- }, -- { -- FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, -- FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, -- FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}, -- }, -- { -- FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, -- FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, -- FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}, -- }, -- { -- FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, -- FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, -- FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}, -- }, -- }, -- { -- { -- FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, -- FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, -- FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}, -- }, -- { -- FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, -- FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, -- FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}, -- }, -- { -- FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, -- FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, -- FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}, -- }, -- { -- FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, -- FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, -- FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}, -- }, -- { -- FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, -- FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, -- FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}, -- }, -- { -- FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, -- FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, -- FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}, -- }, -- { -- FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, -- FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, -- FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}, -- }, -- { -- FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, -- FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, -- FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}, -- }, -- }, -- { -- { -- FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, -- FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, -- FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}, -- }, -- { -- FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, -- FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, -- FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}, -- }, -- { -- FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, -- FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, -- FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}, -- }, -- { -- FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, -- FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, -- FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}, -- }, -- { -- FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, -- FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, -- FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}, -- }, -- { -- FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, -- FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, -- FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}, -- }, -- { -- FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, -- FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, -- FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}, -- }, -- { -- FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, -- FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, -- FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}, -- }, -- }, -- { -- { -- FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, -- FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, -- FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}, -- }, -- { -- FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, -- FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, -- FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}, -- }, -- { -- FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, -- FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, -- FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}, -- }, -- { -- FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, -- FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, -- FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}, -- }, -- { -- FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, -- FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, -- FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}, -- }, -- { -- FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, -- FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, -- FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}, -- }, -- { -- FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, -- FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, -- FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}, -- }, -- { -- FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, -- FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, -- FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}, -- }, -- }, -- { -- { -- FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, -- FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, -- FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}, -- }, -- { -- FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, -- FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, -- FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}, -- }, -- { -- FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, -- FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, -- FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}, -- }, -- { -- FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, -- FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, -- FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}, -- }, -- { -- FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, -- FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, -- FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}, -- }, -- { -- FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, -- FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, -- FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}, -- }, -- { -- FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, -- FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, -- FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}, -- }, -- { -- FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, -- FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, -- FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}, -- }, -- }, -- { -- { -- FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, -- FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, -- FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}, -- }, -- { -- FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, -- FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, -- FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}, -- }, -- { -- FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, -- FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, -- FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}, -- }, -- { -- FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, -- FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, -- FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}, -- }, -- { -- FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, -- FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, -- FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}, -- }, -- { -- FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, -- FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, -- FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}, -- }, -- { -- FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, -- FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, -- FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}, -- }, -- { -- FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, -- FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, -- FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}, -- }, -- }, -- { -- { -- FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, -- FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, -- FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}, -- }, -- { -- FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, -- FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, -- FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}, -- }, -- { -- FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, -- FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, -- FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}, -- }, -- { -- FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, -- FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, -- FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}, -- }, -- { -- FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, -- FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, -- FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}, -- }, -- { -- FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, -- FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, -- FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}, -- }, -- { -- FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, -- FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, -- FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}, -- }, -- { -- FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, -- FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, -- FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}, -- }, -- }, -- { -- { -- FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, -- FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, -- FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}, -- }, -- { -- FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, -- FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, -- FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}, -- }, -- { -- FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, -- FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, -- FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}, -- }, -- { -- FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, -- FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, -- FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}, -- }, -- { -- FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, -- FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, -- FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}, -- }, -- { -- FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, -- FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, -- FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}, -- }, -- { -- FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, -- FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, -- FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}, -- }, -- { -- FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, -- FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, -- FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}, -- }, -- }, -- { -- { -- FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, -- FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, -- FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}, -- }, -- { -- FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, -- FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, -- FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}, -- }, -- { -- FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, -- FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, -- FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}, -- }, -- { -- FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, -- FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, -- FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}, -- }, -- { -- FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, -- FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, -- FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}, -- }, -- { -- FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, -- FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, -- FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}, -- }, -- { -- FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, -- FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, -- FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}, -- }, -- { -- FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, -- FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, -- FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}, -- }, -- }, -- { -- { -- FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, -- FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, -- FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}, -- }, -- { -- FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, -- FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, -- FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}, -- }, -- { -- FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, -- FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, -- FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}, -- }, -- { -- FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, -- FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, -- FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}, -- }, -- { -- FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, -- FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, -- FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}, -- }, -- { -- FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, -- FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, -- FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}, -- }, -- { -- FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, -- FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, -- FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}, -- }, -- { -- FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, -- FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, -- FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}, -- }, -- }, -- { -- { -- FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, -- FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, -- FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}, -- }, -- { -- FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, -- FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, -- FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}, -- }, -- { -- FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, -- FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, -- FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}, -- }, -- { -- FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, -- FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, -- FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}, -- }, -- { -- FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, -- FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, -- FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}, -- }, -- { -- FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, -- FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, -- FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}, -- }, -- { -- FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, -- FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, -- FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}, -- }, -- { -- FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, -- FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, -- FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}, -- }, -- }, --} -diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go -deleted file mode 100644 -index fd03c252af42..000000000000 ---- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go -+++ /dev/null -@@ -1,1793 +0,0 @@ --// Copyright 2016 The Go Authors. All rights reserved. --// Use of this source code is governed by a BSD-style --// license that can be found in the LICENSE file. -- --package edwards25519 -- --import "encoding/binary" -- --// This code is a port of the public domain, “ref10” implementation of ed25519 --// from SUPERCOP. -- --// FieldElement represents an element of the field GF(2^255 - 19). An element --// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 --// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on --// context. --type FieldElement [10]int32 -- --var zero FieldElement -- --func FeZero(fe *FieldElement) { -- copy(fe[:], zero[:]) --} -- --func FeOne(fe *FieldElement) { -- FeZero(fe) -- fe[0] = 1 --} -- --func FeAdd(dst, a, b *FieldElement) { -- dst[0] = a[0] + b[0] -- dst[1] = a[1] + b[1] -- dst[2] = a[2] + b[2] -- dst[3] = a[3] + b[3] -- dst[4] = a[4] + b[4] -- dst[5] = a[5] + b[5] -- dst[6] = a[6] + b[6] -- dst[7] = a[7] + b[7] -- dst[8] = a[8] + b[8] -- dst[9] = a[9] + b[9] --} -- --func FeSub(dst, a, b *FieldElement) { -- dst[0] = a[0] - b[0] -- dst[1] = a[1] - b[1] -- dst[2] = a[2] - b[2] -- dst[3] = a[3] - b[3] -- dst[4] = a[4] - b[4] -- dst[5] = a[5] - b[5] -- dst[6] = a[6] - b[6] -- dst[7] = a[7] - b[7] -- dst[8] = a[8] - b[8] -- dst[9] = a[9] - b[9] --} -- --func FeCopy(dst, src *FieldElement) { -- copy(dst[:], src[:]) --} -- --// Replace (f,g) with (g,g) if b == 1; --// replace (f,g) with (f,g) if b == 0. --// --// Preconditions: b in {0,1}. --func FeCMove(f, g *FieldElement, b int32) { -- b = -b -- f[0] ^= b & (f[0] ^ g[0]) -- f[1] ^= b & (f[1] ^ g[1]) -- f[2] ^= b & (f[2] ^ g[2]) -- f[3] ^= b & (f[3] ^ g[3]) -- f[4] ^= b & (f[4] ^ g[4]) -- f[5] ^= b & (f[5] ^ g[5]) -- f[6] ^= b & (f[6] ^ g[6]) -- f[7] ^= b & (f[7] ^ g[7]) -- f[8] ^= b & (f[8] ^ g[8]) -- f[9] ^= b & (f[9] ^ g[9]) --} -- --func load3(in []byte) int64 { -- var r int64 -- r = int64(in[0]) -- r |= int64(in[1]) << 8 -- r |= int64(in[2]) << 16 -- return r --} -- --func load4(in []byte) int64 { -- var r int64 -- r = int64(in[0]) -- r |= int64(in[1]) << 8 -- r |= int64(in[2]) << 16 -- r |= int64(in[3]) << 24 -- return r --} -- --func FeFromBytes(dst *FieldElement, src *[32]byte) { -- h0 := load4(src[:]) -- h1 := load3(src[4:]) << 6 -- h2 := load3(src[7:]) << 5 -- h3 := load3(src[10:]) << 3 -- h4 := load3(src[13:]) << 2 -- h5 := load4(src[16:]) -- h6 := load3(src[20:]) << 7 -- h7 := load3(src[23:]) << 5 -- h8 := load3(src[26:]) << 4 -- h9 := (load3(src[29:]) & 8388607) << 2 -- -- FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) --} -- --// FeToBytes marshals h to s. --// Preconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --// --// Write p=2^255-19; q=floor(h/p). --// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). --// --// Proof: --// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. --// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. --// --// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). --// Then 0> 25 -- q = (h[0] + q) >> 26 -- q = (h[1] + q) >> 25 -- q = (h[2] + q) >> 26 -- q = (h[3] + q) >> 25 -- q = (h[4] + q) >> 26 -- q = (h[5] + q) >> 25 -- q = (h[6] + q) >> 26 -- q = (h[7] + q) >> 25 -- q = (h[8] + q) >> 26 -- q = (h[9] + q) >> 25 -- -- // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. -- h[0] += 19 * q -- // Goal: Output h-2^255 q, which is between 0 and 2^255-20. -- -- carry[0] = h[0] >> 26 -- h[1] += carry[0] -- h[0] -= carry[0] << 26 -- carry[1] = h[1] >> 25 -- h[2] += carry[1] -- h[1] -= carry[1] << 25 -- carry[2] = h[2] >> 26 -- h[3] += carry[2] -- h[2] -= carry[2] << 26 -- carry[3] = h[3] >> 25 -- h[4] += carry[3] -- h[3] -= carry[3] << 25 -- carry[4] = h[4] >> 26 -- h[5] += carry[4] -- h[4] -= carry[4] << 26 -- carry[5] = h[5] >> 25 -- h[6] += carry[5] -- h[5] -= carry[5] << 25 -- carry[6] = h[6] >> 26 -- h[7] += carry[6] -- h[6] -= carry[6] << 26 -- carry[7] = h[7] >> 25 -- h[8] += carry[7] -- h[7] -= carry[7] << 25 -- carry[8] = h[8] >> 26 -- h[9] += carry[8] -- h[8] -= carry[8] << 26 -- carry[9] = h[9] >> 25 -- h[9] -= carry[9] << 25 -- // h10 = carry9 -- -- // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. -- // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; -- // evidently 2^255 h10-2^255 q = 0. -- // Goal: Output h[0]+...+2^230 h[9]. -- -- s[0] = byte(h[0] >> 0) -- s[1] = byte(h[0] >> 8) -- s[2] = byte(h[0] >> 16) -- s[3] = byte((h[0] >> 24) | (h[1] << 2)) -- s[4] = byte(h[1] >> 6) -- s[5] = byte(h[1] >> 14) -- s[6] = byte((h[1] >> 22) | (h[2] << 3)) -- s[7] = byte(h[2] >> 5) -- s[8] = byte(h[2] >> 13) -- s[9] = byte((h[2] >> 21) | (h[3] << 5)) -- s[10] = byte(h[3] >> 3) -- s[11] = byte(h[3] >> 11) -- s[12] = byte((h[3] >> 19) | (h[4] << 6)) -- s[13] = byte(h[4] >> 2) -- s[14] = byte(h[4] >> 10) -- s[15] = byte(h[4] >> 18) -- s[16] = byte(h[5] >> 0) -- s[17] = byte(h[5] >> 8) -- s[18] = byte(h[5] >> 16) -- s[19] = byte((h[5] >> 24) | (h[6] << 1)) -- s[20] = byte(h[6] >> 7) -- s[21] = byte(h[6] >> 15) -- s[22] = byte((h[6] >> 23) | (h[7] << 3)) -- s[23] = byte(h[7] >> 5) -- s[24] = byte(h[7] >> 13) -- s[25] = byte((h[7] >> 21) | (h[8] << 4)) -- s[26] = byte(h[8] >> 4) -- s[27] = byte(h[8] >> 12) -- s[28] = byte((h[8] >> 20) | (h[9] << 6)) -- s[29] = byte(h[9] >> 2) -- s[30] = byte(h[9] >> 10) -- s[31] = byte(h[9] >> 18) --} -- --func FeIsNegative(f *FieldElement) byte { -- var s [32]byte -- FeToBytes(&s, f) -- return s[0] & 1 --} -- --func FeIsNonZero(f *FieldElement) int32 { -- var s [32]byte -- FeToBytes(&s, f) -- var x uint8 -- for _, b := range s { -- x |= b -- } -- x |= x >> 4 -- x |= x >> 2 -- x |= x >> 1 -- return int32(x & 1) --} -- --// FeNeg sets h = -f --// --// Preconditions: --// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --// --// Postconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --func FeNeg(h, f *FieldElement) { -- h[0] = -f[0] -- h[1] = -f[1] -- h[2] = -f[2] -- h[3] = -f[3] -- h[4] = -f[4] -- h[5] = -f[5] -- h[6] = -f[6] -- h[7] = -f[7] -- h[8] = -f[8] -- h[9] = -f[9] --} -- --func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { -- var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64 -- -- /* -- |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) -- i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 -- |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) -- i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 -- */ -- -- c0 = (h0 + (1 << 25)) >> 26 -- h1 += c0 -- h0 -= c0 << 26 -- c4 = (h4 + (1 << 25)) >> 26 -- h5 += c4 -- h4 -= c4 << 26 -- /* |h0| <= 2^25 */ -- /* |h4| <= 2^25 */ -- /* |h1| <= 1.51*2^58 */ -- /* |h5| <= 1.51*2^58 */ -- -- c1 = (h1 + (1 << 24)) >> 25 -- h2 += c1 -- h1 -= c1 << 25 -- c5 = (h5 + (1 << 24)) >> 25 -- h6 += c5 -- h5 -= c5 << 25 -- /* |h1| <= 2^24; from now on fits into int32 */ -- /* |h5| <= 2^24; from now on fits into int32 */ -- /* |h2| <= 1.21*2^59 */ -- /* |h6| <= 1.21*2^59 */ -- -- c2 = (h2 + (1 << 25)) >> 26 -- h3 += c2 -- h2 -= c2 << 26 -- c6 = (h6 + (1 << 25)) >> 26 -- h7 += c6 -- h6 -= c6 << 26 -- /* |h2| <= 2^25; from now on fits into int32 unchanged */ -- /* |h6| <= 2^25; from now on fits into int32 unchanged */ -- /* |h3| <= 1.51*2^58 */ -- /* |h7| <= 1.51*2^58 */ -- -- c3 = (h3 + (1 << 24)) >> 25 -- h4 += c3 -- h3 -= c3 << 25 -- c7 = (h7 + (1 << 24)) >> 25 -- h8 += c7 -- h7 -= c7 << 25 -- /* |h3| <= 2^24; from now on fits into int32 unchanged */ -- /* |h7| <= 2^24; from now on fits into int32 unchanged */ -- /* |h4| <= 1.52*2^33 */ -- /* |h8| <= 1.52*2^33 */ -- -- c4 = (h4 + (1 << 25)) >> 26 -- h5 += c4 -- h4 -= c4 << 26 -- c8 = (h8 + (1 << 25)) >> 26 -- h9 += c8 -- h8 -= c8 << 26 -- /* |h4| <= 2^25; from now on fits into int32 unchanged */ -- /* |h8| <= 2^25; from now on fits into int32 unchanged */ -- /* |h5| <= 1.01*2^24 */ -- /* |h9| <= 1.51*2^58 */ -- -- c9 = (h9 + (1 << 24)) >> 25 -- h0 += c9 * 19 -- h9 -= c9 << 25 -- /* |h9| <= 2^24; from now on fits into int32 unchanged */ -- /* |h0| <= 1.8*2^37 */ -- -- c0 = (h0 + (1 << 25)) >> 26 -- h1 += c0 -- h0 -= c0 << 26 -- /* |h0| <= 2^25; from now on fits into int32 unchanged */ -- /* |h1| <= 1.01*2^24 */ -- -- h[0] = int32(h0) -- h[1] = int32(h1) -- h[2] = int32(h2) -- h[3] = int32(h3) -- h[4] = int32(h4) -- h[5] = int32(h5) -- h[6] = int32(h6) -- h[7] = int32(h7) -- h[8] = int32(h8) -- h[9] = int32(h9) --} -- --// FeMul calculates h = f * g --// Can overlap h with f or g. --// --// Preconditions: --// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. --// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. --// --// Postconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --// --// Notes on implementation strategy: --// --// Using schoolbook multiplication. --// Karatsuba would save a little in some cost models. --// --// Most multiplications by 2 and 19 are 32-bit precomputations; --// cheaper than 64-bit postcomputations. --// --// There is one remaining multiplication by 19 in the carry chain; --// one *19 precomputation can be merged into this, --// but the resulting data flow is considerably less clean. --// --// There are 12 carries below. --// 10 of them are 2-way parallelizable and vectorizable. --// Can get away with 11 carries, but then data flow is much deeper. --// --// With tighter constraints on inputs, can squeeze carries into int32. --func FeMul(h, f, g *FieldElement) { -- f0 := int64(f[0]) -- f1 := int64(f[1]) -- f2 := int64(f[2]) -- f3 := int64(f[3]) -- f4 := int64(f[4]) -- f5 := int64(f[5]) -- f6 := int64(f[6]) -- f7 := int64(f[7]) -- f8 := int64(f[8]) -- f9 := int64(f[9]) -- -- f1_2 := int64(2 * f[1]) -- f3_2 := int64(2 * f[3]) -- f5_2 := int64(2 * f[5]) -- f7_2 := int64(2 * f[7]) -- f9_2 := int64(2 * f[9]) -- -- g0 := int64(g[0]) -- g1 := int64(g[1]) -- g2 := int64(g[2]) -- g3 := int64(g[3]) -- g4 := int64(g[4]) -- g5 := int64(g[5]) -- g6 := int64(g[6]) -- g7 := int64(g[7]) -- g8 := int64(g[8]) -- g9 := int64(g[9]) -- -- g1_19 := int64(19 * g[1]) /* 1.4*2^29 */ -- g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */ -- g3_19 := int64(19 * g[3]) -- g4_19 := int64(19 * g[4]) -- g5_19 := int64(19 * g[5]) -- g6_19 := int64(19 * g[6]) -- g7_19 := int64(19 * g[7]) -- g8_19 := int64(19 * g[8]) -- g9_19 := int64(19 * g[9]) -- -- h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19 -- h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19 -- h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19 -- h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19 -- h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19 -- h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19 -- h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19 -- h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19 -- h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19 -- h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0 -- -- FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) --} -- --func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { -- f0 := int64(f[0]) -- f1 := int64(f[1]) -- f2 := int64(f[2]) -- f3 := int64(f[3]) -- f4 := int64(f[4]) -- f5 := int64(f[5]) -- f6 := int64(f[6]) -- f7 := int64(f[7]) -- f8 := int64(f[8]) -- f9 := int64(f[9]) -- f0_2 := int64(2 * f[0]) -- f1_2 := int64(2 * f[1]) -- f2_2 := int64(2 * f[2]) -- f3_2 := int64(2 * f[3]) -- f4_2 := int64(2 * f[4]) -- f5_2 := int64(2 * f[5]) -- f6_2 := int64(2 * f[6]) -- f7_2 := int64(2 * f[7]) -- f5_38 := 38 * f5 // 1.31*2^30 -- f6_19 := 19 * f6 // 1.31*2^30 -- f7_38 := 38 * f7 // 1.31*2^30 -- f8_19 := 19 * f8 // 1.31*2^30 -- f9_38 := 38 * f9 // 1.31*2^30 -- -- h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38 -- h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19 -- h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19 -- h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38 -- h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38 -- h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19 -- h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19 -- h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38 -- h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38 -- h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5 -- -- return --} -- --// FeSquare calculates h = f*f. Can overlap h with f. --// --// Preconditions: --// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. --// --// Postconditions: --// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. --func FeSquare(h, f *FieldElement) { -- h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) -- FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) --} -- --// FeSquare2 sets h = 2 * f * f --// --// Can overlap h with f. --// --// Preconditions: --// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. --// --// Postconditions: --// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. --// See fe_mul.c for discussion of implementation strategy. --func FeSquare2(h, f *FieldElement) { -- h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) -- -- h0 += h0 -- h1 += h1 -- h2 += h2 -- h3 += h3 -- h4 += h4 -- h5 += h5 -- h6 += h6 -- h7 += h7 -- h8 += h8 -- h9 += h9 -- -- FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) --} -- --func FeInvert(out, z *FieldElement) { -- var t0, t1, t2, t3 FieldElement -- var i int -- -- FeSquare(&t0, z) // 2^1 -- FeSquare(&t1, &t0) // 2^2 -- for i = 1; i < 2; i++ { // 2^3 -- FeSquare(&t1, &t1) -- } -- FeMul(&t1, z, &t1) // 2^3 + 2^0 -- FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0 -- FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1 -- FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0 -- FeSquare(&t2, &t1) // 5,4,3,2,1 -- for i = 1; i < 5; i++ { // 9,8,7,6,5 -- FeSquare(&t2, &t2) -- } -- FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0 -- FeSquare(&t2, &t1) // 10..1 -- for i = 1; i < 10; i++ { // 19..10 -- FeSquare(&t2, &t2) -- } -- FeMul(&t2, &t2, &t1) // 19..0 -- FeSquare(&t3, &t2) // 20..1 -- for i = 1; i < 20; i++ { // 39..20 -- FeSquare(&t3, &t3) -- } -- FeMul(&t2, &t3, &t2) // 39..0 -- FeSquare(&t2, &t2) // 40..1 -- for i = 1; i < 10; i++ { // 49..10 -- FeSquare(&t2, &t2) -- } -- FeMul(&t1, &t2, &t1) // 49..0 -- FeSquare(&t2, &t1) // 50..1 -- for i = 1; i < 50; i++ { // 99..50 -- FeSquare(&t2, &t2) -- } -- FeMul(&t2, &t2, &t1) // 99..0 -- FeSquare(&t3, &t2) // 100..1 -- for i = 1; i < 100; i++ { // 199..100 -- FeSquare(&t3, &t3) -- } -- FeMul(&t2, &t3, &t2) // 199..0 -- FeSquare(&t2, &t2) // 200..1 -- for i = 1; i < 50; i++ { // 249..50 -- FeSquare(&t2, &t2) -- } -- FeMul(&t1, &t2, &t1) // 249..0 -- FeSquare(&t1, &t1) // 250..1 -- for i = 1; i < 5; i++ { // 254..5 -- FeSquare(&t1, &t1) -- } -- FeMul(out, &t1, &t0) // 254..5,3,1,0 --} -- --func fePow22523(out, z *FieldElement) { -- var t0, t1, t2 FieldElement -- var i int -- -- FeSquare(&t0, z) -- for i = 1; i < 1; i++ { -- FeSquare(&t0, &t0) -- } -- FeSquare(&t1, &t0) -- for i = 1; i < 2; i++ { -- FeSquare(&t1, &t1) -- } -- FeMul(&t1, z, &t1) -- FeMul(&t0, &t0, &t1) -- FeSquare(&t0, &t0) -- for i = 1; i < 1; i++ { -- FeSquare(&t0, &t0) -- } -- FeMul(&t0, &t1, &t0) -- FeSquare(&t1, &t0) -- for i = 1; i < 5; i++ { -- FeSquare(&t1, &t1) -- } -- FeMul(&t0, &t1, &t0) -- FeSquare(&t1, &t0) -- for i = 1; i < 10; i++ { -- FeSquare(&t1, &t1) -- } -- FeMul(&t1, &t1, &t0) -- FeSquare(&t2, &t1) -- for i = 1; i < 20; i++ { -- FeSquare(&t2, &t2) -- } -- FeMul(&t1, &t2, &t1) -- FeSquare(&t1, &t1) -- for i = 1; i < 10; i++ { -- FeSquare(&t1, &t1) -- } -- FeMul(&t0, &t1, &t0) -- FeSquare(&t1, &t0) -- for i = 1; i < 50; i++ { -- FeSquare(&t1, &t1) -- } -- FeMul(&t1, &t1, &t0) -- FeSquare(&t2, &t1) -- for i = 1; i < 100; i++ { -- FeSquare(&t2, &t2) -- } -- FeMul(&t1, &t2, &t1) -- FeSquare(&t1, &t1) -- for i = 1; i < 50; i++ { -- FeSquare(&t1, &t1) -- } -- FeMul(&t0, &t1, &t0) -- FeSquare(&t0, &t0) -- for i = 1; i < 2; i++ { -- FeSquare(&t0, &t0) -- } -- FeMul(out, &t0, z) --} -- --// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 * --// y^2 where d = -121665/121666. --// --// Several representations are used: --// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z --// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT --// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T --// PreComputedGroupElement: (y+x,y-x,2dxy) -- --type ProjectiveGroupElement struct { -- X, Y, Z FieldElement --} -- --type ExtendedGroupElement struct { -- X, Y, Z, T FieldElement --} -- --type CompletedGroupElement struct { -- X, Y, Z, T FieldElement --} -- --type PreComputedGroupElement struct { -- yPlusX, yMinusX, xy2d FieldElement --} -- --type CachedGroupElement struct { -- yPlusX, yMinusX, Z, T2d FieldElement --} -- --func (p *ProjectiveGroupElement) Zero() { -- FeZero(&p.X) -- FeOne(&p.Y) -- FeOne(&p.Z) --} -- --func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) { -- var t0 FieldElement -- -- FeSquare(&r.X, &p.X) -- FeSquare(&r.Z, &p.Y) -- FeSquare2(&r.T, &p.Z) -- FeAdd(&r.Y, &p.X, &p.Y) -- FeSquare(&t0, &r.Y) -- FeAdd(&r.Y, &r.Z, &r.X) -- FeSub(&r.Z, &r.Z, &r.X) -- FeSub(&r.X, &t0, &r.Y) -- FeSub(&r.T, &r.T, &r.Z) --} -- --func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) { -- var recip, x, y FieldElement -- -- FeInvert(&recip, &p.Z) -- FeMul(&x, &p.X, &recip) -- FeMul(&y, &p.Y, &recip) -- FeToBytes(s, &y) -- s[31] ^= FeIsNegative(&x) << 7 --} -- --func (p *ExtendedGroupElement) Zero() { -- FeZero(&p.X) -- FeOne(&p.Y) -- FeOne(&p.Z) -- FeZero(&p.T) --} -- --func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) { -- var q ProjectiveGroupElement -- p.ToProjective(&q) -- q.Double(r) --} -- --func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) { -- FeAdd(&r.yPlusX, &p.Y, &p.X) -- FeSub(&r.yMinusX, &p.Y, &p.X) -- FeCopy(&r.Z, &p.Z) -- FeMul(&r.T2d, &p.T, &d2) --} -- --func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) { -- FeCopy(&r.X, &p.X) -- FeCopy(&r.Y, &p.Y) -- FeCopy(&r.Z, &p.Z) --} -- --func (p *ExtendedGroupElement) ToBytes(s *[32]byte) { -- var recip, x, y FieldElement -- -- FeInvert(&recip, &p.Z) -- FeMul(&x, &p.X, &recip) -- FeMul(&y, &p.Y, &recip) -- FeToBytes(s, &y) -- s[31] ^= FeIsNegative(&x) << 7 --} -- --func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool { -- var u, v, v3, vxx, check FieldElement -- -- FeFromBytes(&p.Y, s) -- FeOne(&p.Z) -- FeSquare(&u, &p.Y) -- FeMul(&v, &u, &d) -- FeSub(&u, &u, &p.Z) // y = y^2-1 -- FeAdd(&v, &v, &p.Z) // v = dy^2+1 -- -- FeSquare(&v3, &v) -- FeMul(&v3, &v3, &v) // v3 = v^3 -- FeSquare(&p.X, &v3) -- FeMul(&p.X, &p.X, &v) -- FeMul(&p.X, &p.X, &u) // x = uv^7 -- -- fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8) -- FeMul(&p.X, &p.X, &v3) -- FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8) -- -- var tmpX, tmp2 [32]byte -- -- FeSquare(&vxx, &p.X) -- FeMul(&vxx, &vxx, &v) -- FeSub(&check, &vxx, &u) // vx^2-u -- if FeIsNonZero(&check) == 1 { -- FeAdd(&check, &vxx, &u) // vx^2+u -- if FeIsNonZero(&check) == 1 { -- return false -- } -- FeMul(&p.X, &p.X, &SqrtM1) -- -- FeToBytes(&tmpX, &p.X) -- for i, v := range tmpX { -- tmp2[31-i] = v -- } -- } -- -- if FeIsNegative(&p.X) != (s[31] >> 7) { -- FeNeg(&p.X, &p.X) -- } -- -- FeMul(&p.T, &p.X, &p.Y) -- return true --} -- --func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) { -- FeMul(&r.X, &p.X, &p.T) -- FeMul(&r.Y, &p.Y, &p.Z) -- FeMul(&r.Z, &p.Z, &p.T) --} -- --func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) { -- FeMul(&r.X, &p.X, &p.T) -- FeMul(&r.Y, &p.Y, &p.Z) -- FeMul(&r.Z, &p.Z, &p.T) -- FeMul(&r.T, &p.X, &p.Y) --} -- --func (p *PreComputedGroupElement) Zero() { -- FeOne(&p.yPlusX) -- FeOne(&p.yMinusX) -- FeZero(&p.xy2d) --} -- --func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { -- var t0 FieldElement -- -- FeAdd(&r.X, &p.Y, &p.X) -- FeSub(&r.Y, &p.Y, &p.X) -- FeMul(&r.Z, &r.X, &q.yPlusX) -- FeMul(&r.Y, &r.Y, &q.yMinusX) -- FeMul(&r.T, &q.T2d, &p.T) -- FeMul(&r.X, &p.Z, &q.Z) -- FeAdd(&t0, &r.X, &r.X) -- FeSub(&r.X, &r.Z, &r.Y) -- FeAdd(&r.Y, &r.Z, &r.Y) -- FeAdd(&r.Z, &t0, &r.T) -- FeSub(&r.T, &t0, &r.T) --} -- --func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { -- var t0 FieldElement -- -- FeAdd(&r.X, &p.Y, &p.X) -- FeSub(&r.Y, &p.Y, &p.X) -- FeMul(&r.Z, &r.X, &q.yMinusX) -- FeMul(&r.Y, &r.Y, &q.yPlusX) -- FeMul(&r.T, &q.T2d, &p.T) -- FeMul(&r.X, &p.Z, &q.Z) -- FeAdd(&t0, &r.X, &r.X) -- FeSub(&r.X, &r.Z, &r.Y) -- FeAdd(&r.Y, &r.Z, &r.Y) -- FeSub(&r.Z, &t0, &r.T) -- FeAdd(&r.T, &t0, &r.T) --} -- --func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { -- var t0 FieldElement -- -- FeAdd(&r.X, &p.Y, &p.X) -- FeSub(&r.Y, &p.Y, &p.X) -- FeMul(&r.Z, &r.X, &q.yPlusX) -- FeMul(&r.Y, &r.Y, &q.yMinusX) -- FeMul(&r.T, &q.xy2d, &p.T) -- FeAdd(&t0, &p.Z, &p.Z) -- FeSub(&r.X, &r.Z, &r.Y) -- FeAdd(&r.Y, &r.Z, &r.Y) -- FeAdd(&r.Z, &t0, &r.T) -- FeSub(&r.T, &t0, &r.T) --} -- --func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { -- var t0 FieldElement -- -- FeAdd(&r.X, &p.Y, &p.X) -- FeSub(&r.Y, &p.Y, &p.X) -- FeMul(&r.Z, &r.X, &q.yMinusX) -- FeMul(&r.Y, &r.Y, &q.yPlusX) -- FeMul(&r.T, &q.xy2d, &p.T) -- FeAdd(&t0, &p.Z, &p.Z) -- FeSub(&r.X, &r.Z, &r.Y) -- FeAdd(&r.Y, &r.Z, &r.Y) -- FeSub(&r.Z, &t0, &r.T) -- FeAdd(&r.T, &t0, &r.T) --} -- --func slide(r *[256]int8, a *[32]byte) { -- for i := range r { -- r[i] = int8(1 & (a[i>>3] >> uint(i&7))) -- } -- -- for i := range r { -- if r[i] != 0 { -- for b := 1; b <= 6 && i+b < 256; b++ { -- if r[i+b] != 0 { -- if r[i]+(r[i+b]<= -15 { -- r[i] -= r[i+b] << uint(b) -- for k := i + b; k < 256; k++ { -- if r[k] == 0 { -- r[k] = 1 -- break -- } -- r[k] = 0 -- } -- } else { -- break -- } -- } -- } -- } -- } --} -- --// GeDoubleScalarMultVartime sets r = a*A + b*B --// where a = a[0]+256*a[1]+...+256^31 a[31]. --// and b = b[0]+256*b[1]+...+256^31 b[31]. --// B is the Ed25519 base point (x,4/5) with x positive. --func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) { -- var aSlide, bSlide [256]int8 -- var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A -- var t CompletedGroupElement -- var u, A2 ExtendedGroupElement -- var i int -- -- slide(&aSlide, a) -- slide(&bSlide, b) -- -- A.ToCached(&Ai[0]) -- A.Double(&t) -- t.ToExtended(&A2) -- -- for i := 0; i < 7; i++ { -- geAdd(&t, &A2, &Ai[i]) -- t.ToExtended(&u) -- u.ToCached(&Ai[i+1]) -- } -- -- r.Zero() -- -- for i = 255; i >= 0; i-- { -- if aSlide[i] != 0 || bSlide[i] != 0 { -- break -- } -- } -- -- for ; i >= 0; i-- { -- r.Double(&t) -- -- if aSlide[i] > 0 { -- t.ToExtended(&u) -- geAdd(&t, &u, &Ai[aSlide[i]/2]) -- } else if aSlide[i] < 0 { -- t.ToExtended(&u) -- geSub(&t, &u, &Ai[(-aSlide[i])/2]) -- } -- -- if bSlide[i] > 0 { -- t.ToExtended(&u) -- geMixedAdd(&t, &u, &bi[bSlide[i]/2]) -- } else if bSlide[i] < 0 { -- t.ToExtended(&u) -- geMixedSub(&t, &u, &bi[(-bSlide[i])/2]) -- } -- -- t.ToProjective(r) -- } --} -- --// equal returns 1 if b == c and 0 otherwise, assuming that b and c are --// non-negative. --func equal(b, c int32) int32 { -- x := uint32(b ^ c) -- x-- -- return int32(x >> 31) --} -- --// negative returns 1 if b < 0 and 0 otherwise. --func negative(b int32) int32 { -- return (b >> 31) & 1 --} -- --func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) { -- FeCMove(&t.yPlusX, &u.yPlusX, b) -- FeCMove(&t.yMinusX, &u.yMinusX, b) -- FeCMove(&t.xy2d, &u.xy2d, b) --} -- --func selectPoint(t *PreComputedGroupElement, pos int32, b int32) { -- var minusT PreComputedGroupElement -- bNegative := negative(b) -- bAbs := b - (((-bNegative) & b) << 1) -- -- t.Zero() -- for i := int32(0); i < 8; i++ { -- PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1)) -- } -- FeCopy(&minusT.yPlusX, &t.yMinusX) -- FeCopy(&minusT.yMinusX, &t.yPlusX) -- FeNeg(&minusT.xy2d, &t.xy2d) -- PreComputedGroupElementCMove(t, &minusT, bNegative) --} -- --// GeScalarMultBase computes h = a*B, where --// a = a[0]+256*a[1]+...+256^31 a[31] --// B is the Ed25519 base point (x,4/5) with x positive. --// --// Preconditions: --// a[31] <= 127 --func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) { -- var e [64]int8 -- -- for i, v := range a { -- e[2*i] = int8(v & 15) -- e[2*i+1] = int8((v >> 4) & 15) -- } -- -- // each e[i] is between 0 and 15 and e[63] is between 0 and 7. -- -- carry := int8(0) -- for i := 0; i < 63; i++ { -- e[i] += carry -- carry = (e[i] + 8) >> 4 -- e[i] -= carry << 4 -- } -- e[63] += carry -- // each e[i] is between -8 and 8. -- -- h.Zero() -- var t PreComputedGroupElement -- var r CompletedGroupElement -- for i := int32(1); i < 64; i += 2 { -- selectPoint(&t, i/2, int32(e[i])) -- geMixedAdd(&r, h, &t) -- r.ToExtended(h) -- } -- -- var s ProjectiveGroupElement -- -- h.Double(&r) -- r.ToProjective(&s) -- s.Double(&r) -- r.ToProjective(&s) -- s.Double(&r) -- r.ToProjective(&s) -- s.Double(&r) -- r.ToExtended(h) -- -- for i := int32(0); i < 64; i += 2 { -- selectPoint(&t, i/2, int32(e[i])) -- geMixedAdd(&r, h, &t) -- r.ToExtended(h) -- } --} -- --// The scalars are GF(2^252 + 27742317777372353535851937790883648493). -- --// Input: --// a[0]+256*a[1]+...+256^31*a[31] = a --// b[0]+256*b[1]+...+256^31*b[31] = b --// c[0]+256*c[1]+...+256^31*c[31] = c --// --// Output: --// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l --// where l = 2^252 + 27742317777372353535851937790883648493. --func ScMulAdd(s, a, b, c *[32]byte) { -- a0 := 2097151 & load3(a[:]) -- a1 := 2097151 & (load4(a[2:]) >> 5) -- a2 := 2097151 & (load3(a[5:]) >> 2) -- a3 := 2097151 & (load4(a[7:]) >> 7) -- a4 := 2097151 & (load4(a[10:]) >> 4) -- a5 := 2097151 & (load3(a[13:]) >> 1) -- a6 := 2097151 & (load4(a[15:]) >> 6) -- a7 := 2097151 & (load3(a[18:]) >> 3) -- a8 := 2097151 & load3(a[21:]) -- a9 := 2097151 & (load4(a[23:]) >> 5) -- a10 := 2097151 & (load3(a[26:]) >> 2) -- a11 := (load4(a[28:]) >> 7) -- b0 := 2097151 & load3(b[:]) -- b1 := 2097151 & (load4(b[2:]) >> 5) -- b2 := 2097151 & (load3(b[5:]) >> 2) -- b3 := 2097151 & (load4(b[7:]) >> 7) -- b4 := 2097151 & (load4(b[10:]) >> 4) -- b5 := 2097151 & (load3(b[13:]) >> 1) -- b6 := 2097151 & (load4(b[15:]) >> 6) -- b7 := 2097151 & (load3(b[18:]) >> 3) -- b8 := 2097151 & load3(b[21:]) -- b9 := 2097151 & (load4(b[23:]) >> 5) -- b10 := 2097151 & (load3(b[26:]) >> 2) -- b11 := (load4(b[28:]) >> 7) -- c0 := 2097151 & load3(c[:]) -- c1 := 2097151 & (load4(c[2:]) >> 5) -- c2 := 2097151 & (load3(c[5:]) >> 2) -- c3 := 2097151 & (load4(c[7:]) >> 7) -- c4 := 2097151 & (load4(c[10:]) >> 4) -- c5 := 2097151 & (load3(c[13:]) >> 1) -- c6 := 2097151 & (load4(c[15:]) >> 6) -- c7 := 2097151 & (load3(c[18:]) >> 3) -- c8 := 2097151 & load3(c[21:]) -- c9 := 2097151 & (load4(c[23:]) >> 5) -- c10 := 2097151 & (load3(c[26:]) >> 2) -- c11 := (load4(c[28:]) >> 7) -- var carry [23]int64 -- -- s0 := c0 + a0*b0 -- s1 := c1 + a0*b1 + a1*b0 -- s2 := c2 + a0*b2 + a1*b1 + a2*b0 -- s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 -- s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 -- s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 -- s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 -- s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 -- s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 -- s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 -- s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 -- s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 -- s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 -- s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 -- s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 -- s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 -- s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 -- s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 -- s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 -- s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 -- s20 := a9*b11 + a10*b10 + a11*b9 -- s21 := a10*b11 + a11*b10 -- s22 := a11 * b11 -- s23 := int64(0) -- -- carry[0] = (s0 + (1 << 20)) >> 21 -- s1 += carry[0] -- s0 -= carry[0] << 21 -- carry[2] = (s2 + (1 << 20)) >> 21 -- s3 += carry[2] -- s2 -= carry[2] << 21 -- carry[4] = (s4 + (1 << 20)) >> 21 -- s5 += carry[4] -- s4 -= carry[4] << 21 -- carry[6] = (s6 + (1 << 20)) >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[8] = (s8 + (1 << 20)) >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[10] = (s10 + (1 << 20)) >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- carry[12] = (s12 + (1 << 20)) >> 21 -- s13 += carry[12] -- s12 -= carry[12] << 21 -- carry[14] = (s14 + (1 << 20)) >> 21 -- s15 += carry[14] -- s14 -= carry[14] << 21 -- carry[16] = (s16 + (1 << 20)) >> 21 -- s17 += carry[16] -- s16 -= carry[16] << 21 -- carry[18] = (s18 + (1 << 20)) >> 21 -- s19 += carry[18] -- s18 -= carry[18] << 21 -- carry[20] = (s20 + (1 << 20)) >> 21 -- s21 += carry[20] -- s20 -= carry[20] << 21 -- carry[22] = (s22 + (1 << 20)) >> 21 -- s23 += carry[22] -- s22 -= carry[22] << 21 -- -- carry[1] = (s1 + (1 << 20)) >> 21 -- s2 += carry[1] -- s1 -= carry[1] << 21 -- carry[3] = (s3 + (1 << 20)) >> 21 -- s4 += carry[3] -- s3 -= carry[3] << 21 -- carry[5] = (s5 + (1 << 20)) >> 21 -- s6 += carry[5] -- s5 -= carry[5] << 21 -- carry[7] = (s7 + (1 << 20)) >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[9] = (s9 + (1 << 20)) >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[11] = (s11 + (1 << 20)) >> 21 -- s12 += carry[11] -- s11 -= carry[11] << 21 -- carry[13] = (s13 + (1 << 20)) >> 21 -- s14 += carry[13] -- s13 -= carry[13] << 21 -- carry[15] = (s15 + (1 << 20)) >> 21 -- s16 += carry[15] -- s15 -= carry[15] << 21 -- carry[17] = (s17 + (1 << 20)) >> 21 -- s18 += carry[17] -- s17 -= carry[17] << 21 -- carry[19] = (s19 + (1 << 20)) >> 21 -- s20 += carry[19] -- s19 -= carry[19] << 21 -- carry[21] = (s21 + (1 << 20)) >> 21 -- s22 += carry[21] -- s21 -= carry[21] << 21 -- -- s11 += s23 * 666643 -- s12 += s23 * 470296 -- s13 += s23 * 654183 -- s14 -= s23 * 997805 -- s15 += s23 * 136657 -- s16 -= s23 * 683901 -- s23 = 0 -- -- s10 += s22 * 666643 -- s11 += s22 * 470296 -- s12 += s22 * 654183 -- s13 -= s22 * 997805 -- s14 += s22 * 136657 -- s15 -= s22 * 683901 -- s22 = 0 -- -- s9 += s21 * 666643 -- s10 += s21 * 470296 -- s11 += s21 * 654183 -- s12 -= s21 * 997805 -- s13 += s21 * 136657 -- s14 -= s21 * 683901 -- s21 = 0 -- -- s8 += s20 * 666643 -- s9 += s20 * 470296 -- s10 += s20 * 654183 -- s11 -= s20 * 997805 -- s12 += s20 * 136657 -- s13 -= s20 * 683901 -- s20 = 0 -- -- s7 += s19 * 666643 -- s8 += s19 * 470296 -- s9 += s19 * 654183 -- s10 -= s19 * 997805 -- s11 += s19 * 136657 -- s12 -= s19 * 683901 -- s19 = 0 -- -- s6 += s18 * 666643 -- s7 += s18 * 470296 -- s8 += s18 * 654183 -- s9 -= s18 * 997805 -- s10 += s18 * 136657 -- s11 -= s18 * 683901 -- s18 = 0 -- -- carry[6] = (s6 + (1 << 20)) >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[8] = (s8 + (1 << 20)) >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[10] = (s10 + (1 << 20)) >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- carry[12] = (s12 + (1 << 20)) >> 21 -- s13 += carry[12] -- s12 -= carry[12] << 21 -- carry[14] = (s14 + (1 << 20)) >> 21 -- s15 += carry[14] -- s14 -= carry[14] << 21 -- carry[16] = (s16 + (1 << 20)) >> 21 -- s17 += carry[16] -- s16 -= carry[16] << 21 -- -- carry[7] = (s7 + (1 << 20)) >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[9] = (s9 + (1 << 20)) >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[11] = (s11 + (1 << 20)) >> 21 -- s12 += carry[11] -- s11 -= carry[11] << 21 -- carry[13] = (s13 + (1 << 20)) >> 21 -- s14 += carry[13] -- s13 -= carry[13] << 21 -- carry[15] = (s15 + (1 << 20)) >> 21 -- s16 += carry[15] -- s15 -= carry[15] << 21 -- -- s5 += s17 * 666643 -- s6 += s17 * 470296 -- s7 += s17 * 654183 -- s8 -= s17 * 997805 -- s9 += s17 * 136657 -- s10 -= s17 * 683901 -- s17 = 0 -- -- s4 += s16 * 666643 -- s5 += s16 * 470296 -- s6 += s16 * 654183 -- s7 -= s16 * 997805 -- s8 += s16 * 136657 -- s9 -= s16 * 683901 -- s16 = 0 -- -- s3 += s15 * 666643 -- s4 += s15 * 470296 -- s5 += s15 * 654183 -- s6 -= s15 * 997805 -- s7 += s15 * 136657 -- s8 -= s15 * 683901 -- s15 = 0 -- -- s2 += s14 * 666643 -- s3 += s14 * 470296 -- s4 += s14 * 654183 -- s5 -= s14 * 997805 -- s6 += s14 * 136657 -- s7 -= s14 * 683901 -- s14 = 0 -- -- s1 += s13 * 666643 -- s2 += s13 * 470296 -- s3 += s13 * 654183 -- s4 -= s13 * 997805 -- s5 += s13 * 136657 -- s6 -= s13 * 683901 -- s13 = 0 -- -- s0 += s12 * 666643 -- s1 += s12 * 470296 -- s2 += s12 * 654183 -- s3 -= s12 * 997805 -- s4 += s12 * 136657 -- s5 -= s12 * 683901 -- s12 = 0 -- -- carry[0] = (s0 + (1 << 20)) >> 21 -- s1 += carry[0] -- s0 -= carry[0] << 21 -- carry[2] = (s2 + (1 << 20)) >> 21 -- s3 += carry[2] -- s2 -= carry[2] << 21 -- carry[4] = (s4 + (1 << 20)) >> 21 -- s5 += carry[4] -- s4 -= carry[4] << 21 -- carry[6] = (s6 + (1 << 20)) >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[8] = (s8 + (1 << 20)) >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[10] = (s10 + (1 << 20)) >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- -- carry[1] = (s1 + (1 << 20)) >> 21 -- s2 += carry[1] -- s1 -= carry[1] << 21 -- carry[3] = (s3 + (1 << 20)) >> 21 -- s4 += carry[3] -- s3 -= carry[3] << 21 -- carry[5] = (s5 + (1 << 20)) >> 21 -- s6 += carry[5] -- s5 -= carry[5] << 21 -- carry[7] = (s7 + (1 << 20)) >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[9] = (s9 + (1 << 20)) >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[11] = (s11 + (1 << 20)) >> 21 -- s12 += carry[11] -- s11 -= carry[11] << 21 -- -- s0 += s12 * 666643 -- s1 += s12 * 470296 -- s2 += s12 * 654183 -- s3 -= s12 * 997805 -- s4 += s12 * 136657 -- s5 -= s12 * 683901 -- s12 = 0 -- -- carry[0] = s0 >> 21 -- s1 += carry[0] -- s0 -= carry[0] << 21 -- carry[1] = s1 >> 21 -- s2 += carry[1] -- s1 -= carry[1] << 21 -- carry[2] = s2 >> 21 -- s3 += carry[2] -- s2 -= carry[2] << 21 -- carry[3] = s3 >> 21 -- s4 += carry[3] -- s3 -= carry[3] << 21 -- carry[4] = s4 >> 21 -- s5 += carry[4] -- s4 -= carry[4] << 21 -- carry[5] = s5 >> 21 -- s6 += carry[5] -- s5 -= carry[5] << 21 -- carry[6] = s6 >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[7] = s7 >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[8] = s8 >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[9] = s9 >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[10] = s10 >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- carry[11] = s11 >> 21 -- s12 += carry[11] -- s11 -= carry[11] << 21 -- -- s0 += s12 * 666643 -- s1 += s12 * 470296 -- s2 += s12 * 654183 -- s3 -= s12 * 997805 -- s4 += s12 * 136657 -- s5 -= s12 * 683901 -- s12 = 0 -- -- carry[0] = s0 >> 21 -- s1 += carry[0] -- s0 -= carry[0] << 21 -- carry[1] = s1 >> 21 -- s2 += carry[1] -- s1 -= carry[1] << 21 -- carry[2] = s2 >> 21 -- s3 += carry[2] -- s2 -= carry[2] << 21 -- carry[3] = s3 >> 21 -- s4 += carry[3] -- s3 -= carry[3] << 21 -- carry[4] = s4 >> 21 -- s5 += carry[4] -- s4 -= carry[4] << 21 -- carry[5] = s5 >> 21 -- s6 += carry[5] -- s5 -= carry[5] << 21 -- carry[6] = s6 >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[7] = s7 >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[8] = s8 >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[9] = s9 >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[10] = s10 >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- -- s[0] = byte(s0 >> 0) -- s[1] = byte(s0 >> 8) -- s[2] = byte((s0 >> 16) | (s1 << 5)) -- s[3] = byte(s1 >> 3) -- s[4] = byte(s1 >> 11) -- s[5] = byte((s1 >> 19) | (s2 << 2)) -- s[6] = byte(s2 >> 6) -- s[7] = byte((s2 >> 14) | (s3 << 7)) -- s[8] = byte(s3 >> 1) -- s[9] = byte(s3 >> 9) -- s[10] = byte((s3 >> 17) | (s4 << 4)) -- s[11] = byte(s4 >> 4) -- s[12] = byte(s4 >> 12) -- s[13] = byte((s4 >> 20) | (s5 << 1)) -- s[14] = byte(s5 >> 7) -- s[15] = byte((s5 >> 15) | (s6 << 6)) -- s[16] = byte(s6 >> 2) -- s[17] = byte(s6 >> 10) -- s[18] = byte((s6 >> 18) | (s7 << 3)) -- s[19] = byte(s7 >> 5) -- s[20] = byte(s7 >> 13) -- s[21] = byte(s8 >> 0) -- s[22] = byte(s8 >> 8) -- s[23] = byte((s8 >> 16) | (s9 << 5)) -- s[24] = byte(s9 >> 3) -- s[25] = byte(s9 >> 11) -- s[26] = byte((s9 >> 19) | (s10 << 2)) -- s[27] = byte(s10 >> 6) -- s[28] = byte((s10 >> 14) | (s11 << 7)) -- s[29] = byte(s11 >> 1) -- s[30] = byte(s11 >> 9) -- s[31] = byte(s11 >> 17) --} -- --// Input: --// s[0]+256*s[1]+...+256^63*s[63] = s --// --// Output: --// s[0]+256*s[1]+...+256^31*s[31] = s mod l --// where l = 2^252 + 27742317777372353535851937790883648493. --func ScReduce(out *[32]byte, s *[64]byte) { -- s0 := 2097151 & load3(s[:]) -- s1 := 2097151 & (load4(s[2:]) >> 5) -- s2 := 2097151 & (load3(s[5:]) >> 2) -- s3 := 2097151 & (load4(s[7:]) >> 7) -- s4 := 2097151 & (load4(s[10:]) >> 4) -- s5 := 2097151 & (load3(s[13:]) >> 1) -- s6 := 2097151 & (load4(s[15:]) >> 6) -- s7 := 2097151 & (load3(s[18:]) >> 3) -- s8 := 2097151 & load3(s[21:]) -- s9 := 2097151 & (load4(s[23:]) >> 5) -- s10 := 2097151 & (load3(s[26:]) >> 2) -- s11 := 2097151 & (load4(s[28:]) >> 7) -- s12 := 2097151 & (load4(s[31:]) >> 4) -- s13 := 2097151 & (load3(s[34:]) >> 1) -- s14 := 2097151 & (load4(s[36:]) >> 6) -- s15 := 2097151 & (load3(s[39:]) >> 3) -- s16 := 2097151 & load3(s[42:]) -- s17 := 2097151 & (load4(s[44:]) >> 5) -- s18 := 2097151 & (load3(s[47:]) >> 2) -- s19 := 2097151 & (load4(s[49:]) >> 7) -- s20 := 2097151 & (load4(s[52:]) >> 4) -- s21 := 2097151 & (load3(s[55:]) >> 1) -- s22 := 2097151 & (load4(s[57:]) >> 6) -- s23 := (load4(s[60:]) >> 3) -- -- s11 += s23 * 666643 -- s12 += s23 * 470296 -- s13 += s23 * 654183 -- s14 -= s23 * 997805 -- s15 += s23 * 136657 -- s16 -= s23 * 683901 -- s23 = 0 -- -- s10 += s22 * 666643 -- s11 += s22 * 470296 -- s12 += s22 * 654183 -- s13 -= s22 * 997805 -- s14 += s22 * 136657 -- s15 -= s22 * 683901 -- s22 = 0 -- -- s9 += s21 * 666643 -- s10 += s21 * 470296 -- s11 += s21 * 654183 -- s12 -= s21 * 997805 -- s13 += s21 * 136657 -- s14 -= s21 * 683901 -- s21 = 0 -- -- s8 += s20 * 666643 -- s9 += s20 * 470296 -- s10 += s20 * 654183 -- s11 -= s20 * 997805 -- s12 += s20 * 136657 -- s13 -= s20 * 683901 -- s20 = 0 -- -- s7 += s19 * 666643 -- s8 += s19 * 470296 -- s9 += s19 * 654183 -- s10 -= s19 * 997805 -- s11 += s19 * 136657 -- s12 -= s19 * 683901 -- s19 = 0 -- -- s6 += s18 * 666643 -- s7 += s18 * 470296 -- s8 += s18 * 654183 -- s9 -= s18 * 997805 -- s10 += s18 * 136657 -- s11 -= s18 * 683901 -- s18 = 0 -- -- var carry [17]int64 -- -- carry[6] = (s6 + (1 << 20)) >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[8] = (s8 + (1 << 20)) >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[10] = (s10 + (1 << 20)) >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- carry[12] = (s12 + (1 << 20)) >> 21 -- s13 += carry[12] -- s12 -= carry[12] << 21 -- carry[14] = (s14 + (1 << 20)) >> 21 -- s15 += carry[14] -- s14 -= carry[14] << 21 -- carry[16] = (s16 + (1 << 20)) >> 21 -- s17 += carry[16] -- s16 -= carry[16] << 21 -- -- carry[7] = (s7 + (1 << 20)) >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[9] = (s9 + (1 << 20)) >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[11] = (s11 + (1 << 20)) >> 21 -- s12 += carry[11] -- s11 -= carry[11] << 21 -- carry[13] = (s13 + (1 << 20)) >> 21 -- s14 += carry[13] -- s13 -= carry[13] << 21 -- carry[15] = (s15 + (1 << 20)) >> 21 -- s16 += carry[15] -- s15 -= carry[15] << 21 -- -- s5 += s17 * 666643 -- s6 += s17 * 470296 -- s7 += s17 * 654183 -- s8 -= s17 * 997805 -- s9 += s17 * 136657 -- s10 -= s17 * 683901 -- s17 = 0 -- -- s4 += s16 * 666643 -- s5 += s16 * 470296 -- s6 += s16 * 654183 -- s7 -= s16 * 997805 -- s8 += s16 * 136657 -- s9 -= s16 * 683901 -- s16 = 0 -- -- s3 += s15 * 666643 -- s4 += s15 * 470296 -- s5 += s15 * 654183 -- s6 -= s15 * 997805 -- s7 += s15 * 136657 -- s8 -= s15 * 683901 -- s15 = 0 -- -- s2 += s14 * 666643 -- s3 += s14 * 470296 -- s4 += s14 * 654183 -- s5 -= s14 * 997805 -- s6 += s14 * 136657 -- s7 -= s14 * 683901 -- s14 = 0 -- -- s1 += s13 * 666643 -- s2 += s13 * 470296 -- s3 += s13 * 654183 -- s4 -= s13 * 997805 -- s5 += s13 * 136657 -- s6 -= s13 * 683901 -- s13 = 0 -- -- s0 += s12 * 666643 -- s1 += s12 * 470296 -- s2 += s12 * 654183 -- s3 -= s12 * 997805 -- s4 += s12 * 136657 -- s5 -= s12 * 683901 -- s12 = 0 -- -- carry[0] = (s0 + (1 << 20)) >> 21 -- s1 += carry[0] -- s0 -= carry[0] << 21 -- carry[2] = (s2 + (1 << 20)) >> 21 -- s3 += carry[2] -- s2 -= carry[2] << 21 -- carry[4] = (s4 + (1 << 20)) >> 21 -- s5 += carry[4] -- s4 -= carry[4] << 21 -- carry[6] = (s6 + (1 << 20)) >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[8] = (s8 + (1 << 20)) >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[10] = (s10 + (1 << 20)) >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- -- carry[1] = (s1 + (1 << 20)) >> 21 -- s2 += carry[1] -- s1 -= carry[1] << 21 -- carry[3] = (s3 + (1 << 20)) >> 21 -- s4 += carry[3] -- s3 -= carry[3] << 21 -- carry[5] = (s5 + (1 << 20)) >> 21 -- s6 += carry[5] -- s5 -= carry[5] << 21 -- carry[7] = (s7 + (1 << 20)) >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[9] = (s9 + (1 << 20)) >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[11] = (s11 + (1 << 20)) >> 21 -- s12 += carry[11] -- s11 -= carry[11] << 21 -- -- s0 += s12 * 666643 -- s1 += s12 * 470296 -- s2 += s12 * 654183 -- s3 -= s12 * 997805 -- s4 += s12 * 136657 -- s5 -= s12 * 683901 -- s12 = 0 -- -- carry[0] = s0 >> 21 -- s1 += carry[0] -- s0 -= carry[0] << 21 -- carry[1] = s1 >> 21 -- s2 += carry[1] -- s1 -= carry[1] << 21 -- carry[2] = s2 >> 21 -- s3 += carry[2] -- s2 -= carry[2] << 21 -- carry[3] = s3 >> 21 -- s4 += carry[3] -- s3 -= carry[3] << 21 -- carry[4] = s4 >> 21 -- s5 += carry[4] -- s4 -= carry[4] << 21 -- carry[5] = s5 >> 21 -- s6 += carry[5] -- s5 -= carry[5] << 21 -- carry[6] = s6 >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[7] = s7 >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[8] = s8 >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[9] = s9 >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[10] = s10 >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- carry[11] = s11 >> 21 -- s12 += carry[11] -- s11 -= carry[11] << 21 -- -- s0 += s12 * 666643 -- s1 += s12 * 470296 -- s2 += s12 * 654183 -- s3 -= s12 * 997805 -- s4 += s12 * 136657 -- s5 -= s12 * 683901 -- s12 = 0 -- -- carry[0] = s0 >> 21 -- s1 += carry[0] -- s0 -= carry[0] << 21 -- carry[1] = s1 >> 21 -- s2 += carry[1] -- s1 -= carry[1] << 21 -- carry[2] = s2 >> 21 -- s3 += carry[2] -- s2 -= carry[2] << 21 -- carry[3] = s3 >> 21 -- s4 += carry[3] -- s3 -= carry[3] << 21 -- carry[4] = s4 >> 21 -- s5 += carry[4] -- s4 -= carry[4] << 21 -- carry[5] = s5 >> 21 -- s6 += carry[5] -- s5 -= carry[5] << 21 -- carry[6] = s6 >> 21 -- s7 += carry[6] -- s6 -= carry[6] << 21 -- carry[7] = s7 >> 21 -- s8 += carry[7] -- s7 -= carry[7] << 21 -- carry[8] = s8 >> 21 -- s9 += carry[8] -- s8 -= carry[8] << 21 -- carry[9] = s9 >> 21 -- s10 += carry[9] -- s9 -= carry[9] << 21 -- carry[10] = s10 >> 21 -- s11 += carry[10] -- s10 -= carry[10] << 21 -- -- out[0] = byte(s0 >> 0) -- out[1] = byte(s0 >> 8) -- out[2] = byte((s0 >> 16) | (s1 << 5)) -- out[3] = byte(s1 >> 3) -- out[4] = byte(s1 >> 11) -- out[5] = byte((s1 >> 19) | (s2 << 2)) -- out[6] = byte(s2 >> 6) -- out[7] = byte((s2 >> 14) | (s3 << 7)) -- out[8] = byte(s3 >> 1) -- out[9] = byte(s3 >> 9) -- out[10] = byte((s3 >> 17) | (s4 << 4)) -- out[11] = byte(s4 >> 4) -- out[12] = byte(s4 >> 12) -- out[13] = byte((s4 >> 20) | (s5 << 1)) -- out[14] = byte(s5 >> 7) -- out[15] = byte((s5 >> 15) | (s6 << 6)) -- out[16] = byte(s6 >> 2) -- out[17] = byte(s6 >> 10) -- out[18] = byte((s6 >> 18) | (s7 << 3)) -- out[19] = byte(s7 >> 5) -- out[20] = byte(s7 >> 13) -- out[21] = byte(s8 >> 0) -- out[22] = byte(s8 >> 8) -- out[23] = byte((s8 >> 16) | (s9 << 5)) -- out[24] = byte(s9 >> 3) -- out[25] = byte(s9 >> 11) -- out[26] = byte((s9 >> 19) | (s10 << 2)) -- out[27] = byte(s10 >> 6) -- out[28] = byte((s10 >> 14) | (s11 << 7)) -- out[29] = byte(s11 >> 1) -- out[30] = byte(s11 >> 9) -- out[31] = byte(s11 >> 17) --} -- --// order is the order of Curve25519 in little-endian form. --var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} -- --// ScMinimal returns true if the given scalar is less than the order of the --// curve. --func ScMinimal(scalar *[32]byte) bool { -- for i := 3; ; i-- { -- v := binary.LittleEndian.Uint64(scalar[i*8:]) -- if v > order[i] { -- return false -- } else if v < order[i] { -- break -- } else if i == 0 { -- return false -- } -- } -- -- return true --} -diff --git a/vendor/golang.org/x/crypto/go.mod b/vendor/golang.org/x/crypto/go.mod -index b8e07279f0ce..525ffa6a94e3 100644 ---- a/vendor/golang.org/x/crypto/go.mod -+++ b/vendor/golang.org/x/crypto/go.mod -@@ -1,9 +1,11 @@ - module golang.org/x/crypto - --go 1.11 -+go 1.17 - - require ( -- golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 -- golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 -- golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 -+ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 -+ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 -+ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 - ) -+ -+require golang.org/x/text v0.3.6 // indirect -diff --git a/vendor/golang.org/x/crypto/go.sum b/vendor/golang.org/x/crypto/go.sum -new file mode 100644 -index 000000000000..cccfa807ac9a ---- /dev/null -+++ b/vendor/golang.org/x/crypto/go.sum -@@ -0,0 +1,11 @@ -+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= -+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= -+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= -+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= -+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -diff --git a/vendor/golang.org/x/crypto/hkdf/hkdf.go b/vendor/golang.org/x/crypto/hkdf/hkdf.go -new file mode 100644 -index 000000000000..dda3f143bec5 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/hkdf/hkdf.go -@@ -0,0 +1,93 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation -+// Function (HKDF) as defined in RFC 5869. -+// -+// HKDF is a cryptographic key derivation function (KDF) with the goal of -+// expanding limited input keying material into one or more cryptographically -+// strong secret keys. -+package hkdf // import "golang.org/x/crypto/hkdf" -+ -+import ( -+ "crypto/hmac" -+ "errors" -+ "hash" -+ "io" -+) -+ -+// Extract generates a pseudorandom key for use with Expand from an input secret -+// and an optional independent salt. -+// -+// Only use this function if you need to reuse the extracted key with multiple -+// Expand invocations and different context values. Most common scenarios, -+// including the generation of multiple keys, should use New instead. -+func Extract(hash func() hash.Hash, secret, salt []byte) []byte { -+ if salt == nil { -+ salt = make([]byte, hash().Size()) -+ } -+ extractor := hmac.New(hash, salt) -+ extractor.Write(secret) -+ return extractor.Sum(nil) -+} -+ -+type hkdf struct { -+ expander hash.Hash -+ size int -+ -+ info []byte -+ counter byte -+ -+ prev []byte -+ buf []byte -+} -+ -+func (f *hkdf) Read(p []byte) (int, error) { -+ // Check whether enough data can be generated -+ need := len(p) -+ remains := len(f.buf) + int(255-f.counter+1)*f.size -+ if remains < need { -+ return 0, errors.New("hkdf: entropy limit reached") -+ } -+ // Read any leftover from the buffer -+ n := copy(p, f.buf) -+ p = p[n:] -+ -+ // Fill the rest of the buffer -+ for len(p) > 0 { -+ f.expander.Reset() -+ f.expander.Write(f.prev) -+ f.expander.Write(f.info) -+ f.expander.Write([]byte{f.counter}) -+ f.prev = f.expander.Sum(f.prev[:0]) -+ f.counter++ -+ -+ // Copy the new batch into p -+ f.buf = f.prev -+ n = copy(p, f.buf) -+ p = p[n:] -+ } -+ // Save leftovers for next run -+ f.buf = f.buf[n:] -+ -+ return need, nil -+} -+ -+// Expand returns a Reader, from which keys can be read, using the given -+// pseudorandom key and optional context info, skipping the extraction step. -+// -+// The pseudorandomKey should have been generated by Extract, or be a uniformly -+// random or pseudorandom cryptographically strong key. See RFC 5869, Section -+// 3.3. Most common scenarios will want to use New instead. -+func Expand(hash func() hash.Hash, pseudorandomKey, info []byte) io.Reader { -+ expander := hmac.New(hash, pseudorandomKey) -+ return &hkdf{expander, expander.Size(), info, 1, nil, nil} -+} -+ -+// New returns a Reader, from which keys can be read, using the given hash, -+// secret, salt and context info. Salt and info can be nil. -+func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader { -+ prk := Extract(hash, secret, salt) -+ return Expand(hash, prk, info) -+} -diff --git a/vendor/golang.org/x/crypto/poly1305/bits_compat.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go -similarity index 98% -rename from vendor/golang.org/x/crypto/poly1305/bits_compat.go -rename to vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go -index 157a69f61bd9..45b5c966b2be 100644 ---- a/vendor/golang.org/x/crypto/poly1305/bits_compat.go -+++ b/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go -@@ -2,6 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - -+//go:build !go1.13 - // +build !go1.13 - - package poly1305 -diff --git a/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go -similarity index 96% -rename from vendor/golang.org/x/crypto/poly1305/bits_go1.13.go -rename to vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go -index a0a185f0fc77..ed52b3418ab5 100644 ---- a/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go -+++ b/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go -@@ -2,6 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - -+//go:build go1.13 - // +build go1.13 - - package poly1305 -diff --git a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go -similarity index 66% -rename from vendor/golang.org/x/crypto/poly1305/mac_noasm.go -rename to vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go -index d118f30ed56c..f184b67d98db 100644 ---- a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go -+++ b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !amd64,!ppc64le,!s390x gccgo purego -+//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego -+// +build !amd64,!ppc64le,!s390x !gc purego - - package poly1305 - -diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go -similarity index 98% -rename from vendor/golang.org/x/crypto/poly1305/poly1305.go -rename to vendor/golang.org/x/crypto/internal/poly1305/poly1305.go -index 9d7a6af09feb..4aaea810a268 100644 ---- a/vendor/golang.org/x/crypto/poly1305/poly1305.go -+++ b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go -@@ -15,7 +15,7 @@ - // used with a fixed key in order to generate one-time keys from an nonce. - // However, in this package AES isn't used and the one-time key is specified - // directly. --package poly1305 // import "golang.org/x/crypto/poly1305" -+package poly1305 - - import "crypto/subtle" - -diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go -similarity index 95% -rename from vendor/golang.org/x/crypto/poly1305/sum_amd64.go -rename to vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go -index 99e5a1d50efc..6d522333f29e 100644 ---- a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go -+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - package poly1305 - -diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s -similarity index 98% -rename from vendor/golang.org/x/crypto/poly1305/sum_amd64.s -rename to vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s -index 8d394a212ee9..1d74f0f88189 100644 ---- a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s -+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - #include "textflag.h" - -diff --git a/vendor/golang.org/x/crypto/poly1305/sum_generic.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go -similarity index 100% -rename from vendor/golang.org/x/crypto/poly1305/sum_generic.go -rename to vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go -diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go -similarity index 95% -rename from vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go -rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go -index 2e7a120b1923..4a069941a6ef 100644 ---- a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go -+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - package poly1305 - -diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s -similarity index 94% -rename from vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s -rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s -index 4e0281387968..58422aad2305 100644 ---- a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s -+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - #include "textflag.h" - -@@ -82,7 +83,7 @@ multiply: - BGE loop - - bytes_between_0_and_15: -- CMP $0, R5 -+ CMP R5, $0 - BEQ done - MOVD $0, R16 // h0 - MOVD $0, R17 // h1 -@@ -122,7 +123,7 @@ just1: - // Exactly 8 - MOVD (R4), R16 - -- CMP $0, R17 -+ CMP R17, $0 - - // Check if we've already set R17; if not - // set 1 to indicate end of msg. -@@ -151,7 +152,7 @@ less4: - ADD $2, R4 - - less2: -- CMP $0, R5 -+ CMP R5, $0 - BEQ insert1 - MOVBZ (R4), R21 - SLD R22, R21, R21 -@@ -166,12 +167,12 @@ insert1: - - carry: - // Add new values to h0, h1, h2 -- ADDC R16, R8 -- ADDE R17, R9 -- ADDE $0, R10 -- MOVD $16, R5 -- ADD R5, R4 -- BR multiply -+ ADDC R16, R8 -+ ADDE R17, R9 -+ ADDZE R10, R10 -+ MOVD $16, R5 -+ ADD R5, R4 -+ BR multiply - - done: - // Save h0, h1, h2 in state -diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go -similarity index 97% -rename from vendor/golang.org/x/crypto/poly1305/sum_s390x.go -rename to vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go -index 958fedc0790b..62cc9f84709e 100644 ---- a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go -+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - package poly1305 - -diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s -similarity index 99% -rename from vendor/golang.org/x/crypto/poly1305/sum_s390x.s -rename to vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s -index 0fa9ee6e0bff..aa9e0494c909 100644 ---- a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s -+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !gccgo,!purego -+//go:build gc && !purego -+// +build gc,!purego - - #include "textflag.h" - -@@ -17,7 +18,7 @@ - // value. These limbs are, for the most part, zero extended and - // placed into 64-bit vector register elements. Each vector - // register is 128-bits wide and so holds 2 of these elements. --// Using 26-bit limbs allows us plenty of headroom to accomodate -+// Using 26-bit limbs allows us plenty of headroom to accommodate - // accumulations before and after multiplication without - // overflowing either 32-bits (before multiplication) or 64-bits - // (after multiplication). -diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go -index f38797bfa1bf..4fad24f8dcde 100644 ---- a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go -+++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !appengine -+//go:build !purego -+// +build !purego - - // Package subtle implements functions that are often useful in cryptographic - // code but require careful thought to use correctly. -diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go -similarity index 97% -rename from vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go -rename to vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go -index 0cc4a8a642c9..80ccbed2c0de 100644 ---- a/vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go -+++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build appengine -+//go:build purego -+// +build purego - - // Package subtle implements functions that are often useful in cryptographic - // code but require careful thought to use correctly. -diff --git a/vendor/golang.org/x/crypto/internal/wycheproof/README.md b/vendor/golang.org/x/crypto/internal/wycheproof/README.md -new file mode 100644 -index 000000000000..8ae6c6c3d5a5 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/internal/wycheproof/README.md -@@ -0,0 +1,12 @@ -+This package runs a set of the Wycheproof tests provided by -+https://github.com/google/wycheproof. -+ -+The JSON test files live in -+https://github.com/google/wycheproof/tree/master/testvectors -+and are being fetched and cached at a pinned version every time -+these tests are run. To change the version of the wycheproof -+repository that is being used for testing, update wycheproofModVer. -+ -+The structs for these tests are generated from the -+schemas provided in https://github.com/google/wycheproof/tree/master/schemas -+using https://github.com/a-h/generate. -\ No newline at end of file -diff --git a/vendor/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go b/vendor/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go -new file mode 100644 -index 000000000000..3101dfc1c23e ---- /dev/null -+++ b/vendor/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go -@@ -0,0 +1,33 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package dsa provides an internal version of dsa.Verify -+// that is used for the Wycheproof tests. -+package dsa -+ -+import ( -+ "crypto/dsa" -+ "math/big" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+// VerifyASN1 verifies the ASN1 encoded signature, sig, of hash using the -+// public key, pub. Its return value records whether the signature is valid. -+func VerifyASN1(pub *dsa.PublicKey, hash, sig []byte) bool { -+ var ( -+ r, s = &big.Int{}, &big.Int{} -+ inner cryptobyte.String -+ ) -+ input := cryptobyte.String(sig) -+ if !input.ReadASN1(&inner, asn1.SEQUENCE) || -+ !input.Empty() || -+ !inner.ReadASN1Integer(r) || -+ !inner.ReadASN1Integer(s) || -+ !inner.Empty() { -+ return false -+ } -+ return dsa.Verify(pub, hash, r, s) -+} -diff --git a/vendor/golang.org/x/crypto/md4/md4.go b/vendor/golang.org/x/crypto/md4/md4.go -new file mode 100644 -index 000000000000..59d348069305 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/md4/md4.go -@@ -0,0 +1,122 @@ -+// Copyright 2009 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 md4 implements the MD4 hash algorithm as defined in RFC 1320. -+// -+// Deprecated: MD4 is cryptographically broken and should should only be used -+// where compatibility with legacy systems, not security, is the goal. Instead, -+// use a secure hash like SHA-256 (from crypto/sha256). -+package md4 // import "golang.org/x/crypto/md4" -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ crypto.RegisterHash(crypto.MD4, New) -+} -+ -+// The size of an MD4 checksum in bytes. -+const Size = 16 -+ -+// The blocksize of MD4 in bytes. -+const BlockSize = 64 -+ -+const ( -+ _Chunk = 64 -+ _Init0 = 0x67452301 -+ _Init1 = 0xEFCDAB89 -+ _Init2 = 0x98BADCFE -+ _Init3 = 0x10325476 -+) -+ -+// digest represents the partial evaluation of a checksum. -+type digest struct { -+ s [4]uint32 -+ x [_Chunk]byte -+ nx int -+ len uint64 -+} -+ -+func (d *digest) Reset() { -+ d.s[0] = _Init0 -+ d.s[1] = _Init1 -+ d.s[2] = _Init2 -+ d.s[3] = _Init3 -+ d.nx = 0 -+ d.len = 0 -+} -+ -+// New returns a new hash.Hash computing the MD4 checksum. -+func New() hash.Hash { -+ d := new(digest) -+ d.Reset() -+ return d -+} -+ -+func (d *digest) Size() int { return Size } -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Write(p []byte) (nn int, err error) { -+ nn = len(p) -+ d.len += uint64(nn) -+ if d.nx > 0 { -+ n := len(p) -+ if n > _Chunk-d.nx { -+ n = _Chunk - d.nx -+ } -+ for i := 0; i < n; i++ { -+ d.x[d.nx+i] = p[i] -+ } -+ d.nx += n -+ if d.nx == _Chunk { -+ _Block(d, d.x[0:]) -+ d.nx = 0 -+ } -+ p = p[n:] -+ } -+ n := _Block(d, p) -+ p = p[n:] -+ if len(p) > 0 { -+ d.nx = copy(d.x[:], p) -+ } -+ return -+} -+ -+func (d0 *digest) Sum(in []byte) []byte { -+ // Make a copy of d0, so that caller can keep writing and summing. -+ d := new(digest) -+ *d = *d0 -+ -+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. -+ len := d.len -+ var tmp [64]byte -+ tmp[0] = 0x80 -+ if len%64 < 56 { -+ d.Write(tmp[0 : 56-len%64]) -+ } else { -+ d.Write(tmp[0 : 64+56-len%64]) -+ } -+ -+ // Length in bits. -+ len <<= 3 -+ for i := uint(0); i < 8; i++ { -+ tmp[i] = byte(len >> (8 * i)) -+ } -+ d.Write(tmp[0:8]) -+ -+ if d.nx != 0 { -+ panic("d.nx != 0") -+ } -+ -+ for _, s := range d.s { -+ in = append(in, byte(s>>0)) -+ in = append(in, byte(s>>8)) -+ in = append(in, byte(s>>16)) -+ in = append(in, byte(s>>24)) -+ } -+ return in -+} -diff --git a/vendor/golang.org/x/crypto/md4/md4block.go b/vendor/golang.org/x/crypto/md4/md4block.go -new file mode 100644 -index 000000000000..3fed475f3f60 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/md4/md4block.go -@@ -0,0 +1,89 @@ -+// Copyright 2009 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. -+ -+// MD4 block step. -+// In its own file so that a faster assembly or C version -+// can be substituted easily. -+ -+package md4 -+ -+var shift1 = []uint{3, 7, 11, 19} -+var shift2 = []uint{3, 5, 9, 13} -+var shift3 = []uint{3, 9, 11, 15} -+ -+var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15} -+var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15} -+ -+func _Block(dig *digest, p []byte) int { -+ a := dig.s[0] -+ b := dig.s[1] -+ c := dig.s[2] -+ d := dig.s[3] -+ n := 0 -+ var X [16]uint32 -+ for len(p) >= _Chunk { -+ aa, bb, cc, dd := a, b, c, d -+ -+ j := 0 -+ for i := 0; i < 16; i++ { -+ X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 -+ j += 4 -+ } -+ -+ // If this needs to be made faster in the future, -+ // the usual trick is to unroll each of these -+ // loops by a factor of 4; that lets you replace -+ // the shift[] lookups with constants and, -+ // with suitable variable renaming in each -+ // unrolled body, delete the a, b, c, d = d, a, b, c -+ // (or you can let the optimizer do the renaming). -+ // -+ // The index variables are uint so that % by a power -+ // of two can be optimized easily by a compiler. -+ -+ // Round 1. -+ for i := uint(0); i < 16; i++ { -+ x := i -+ s := shift1[i%4] -+ f := ((c ^ d) & b) ^ d -+ a += f + X[x] -+ a = a<>(32-s) -+ a, b, c, d = d, a, b, c -+ } -+ -+ // Round 2. -+ for i := uint(0); i < 16; i++ { -+ x := xIndex2[i] -+ s := shift2[i%4] -+ g := (b & c) | (b & d) | (c & d) -+ a += g + X[x] + 0x5a827999 -+ a = a<>(32-s) -+ a, b, c, d = d, a, b, c -+ } -+ -+ // Round 3. -+ for i := uint(0); i < 16; i++ { -+ x := xIndex3[i] -+ s := shift3[i%4] -+ h := b ^ c ^ d -+ a += h + X[x] + 0x6ed9eba1 -+ a = a<>(32-s) -+ a, b, c, d = d, a, b, c -+ } -+ -+ a += aa -+ b += bb -+ c += cc -+ d += dd -+ -+ p = p[_Chunk:] -+ n += _Chunk -+ } -+ -+ dig.s[0] = a -+ dig.s[1] = b -+ dig.s[2] = c -+ dig.s[3] = d -+ return n -+} -diff --git a/vendor/golang.org/x/crypto/nacl/auth/auth.go b/vendor/golang.org/x/crypto/nacl/auth/auth.go -new file mode 100644 -index 000000000000..1d588d5c1cd2 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/nacl/auth/auth.go -@@ -0,0 +1,58 @@ -+// 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 auth authenticates a message using a secret key. -+ -+The Sum function, viewed as a function of the message for a uniform random -+key, is designed to meet the standard notion of unforgeability. This means -+that an attacker cannot find authenticators for any messages not authenticated -+by the sender, even if the attacker has adaptively influenced the messages -+authenticated by the sender. For a formal definition see, e.g., Section 2.4 -+of Bellare, Kilian, and Rogaway, "The security of the cipher block chaining -+message authentication code," Journal of Computer and System Sciences 61 (2000), -+362–399; http://www-cse.ucsd.edu/~mihir/papers/cbc.html. -+ -+auth does not make any promises regarding "strong" unforgeability; perhaps -+one valid authenticator can be converted into another valid authenticator for -+the same message. NaCl also does not make any promises regarding "truncated -+unforgeability." -+ -+This package is interoperable with NaCl: https://nacl.cr.yp.to/auth.html. -+*/ -+package auth -+ -+import ( -+ "crypto/hmac" -+ "crypto/sha512" -+) -+ -+const ( -+ // Size is the size, in bytes, of an authenticated digest. -+ Size = 32 -+ // KeySize is the size, in bytes, of an authentication key. -+ KeySize = 32 -+) -+ -+// Sum generates an authenticator for m using a secret key and returns the -+// 32-byte digest. -+func Sum(m []byte, key *[KeySize]byte) *[Size]byte { -+ mac := hmac.New(sha512.New, key[:]) -+ mac.Write(m) -+ out := new([Size]byte) -+ copy(out[:], mac.Sum(nil)[:Size]) -+ return out -+} -+ -+// Verify checks that digest is a valid authenticator of message m under the -+// given secret key. Verify does not leak timing information. -+func Verify(digest []byte, m []byte, key *[KeySize]byte) bool { -+ if len(digest) != Size { -+ return false -+ } -+ mac := hmac.New(sha512.New, key[:]) -+ mac.Write(m) -+ expectedMAC := mac.Sum(nil) // first 256 bits of 512-bit sum -+ return hmac.Equal(digest, expectedMAC[:Size]) -+} -diff --git a/vendor/golang.org/x/crypto/nacl/box/box.go b/vendor/golang.org/x/crypto/nacl/box/box.go -new file mode 100644 -index 000000000000..7f3b830ee22f ---- /dev/null -+++ b/vendor/golang.org/x/crypto/nacl/box/box.go -@@ -0,0 +1,182 @@ -+// Copyright 2012 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 box authenticates and encrypts small messages using public-key cryptography. -+ -+Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate -+messages. The length of messages is not hidden. -+ -+It is the caller's responsibility to ensure the uniqueness of nonces—for -+example, by using nonce 1 for the first message, nonce 2 for the second -+message, etc. Nonces are long enough that randomly generated nonces have -+negligible risk of collision. -+ -+Messages should be small because: -+ -+1. The whole message needs to be held in memory to be processed. -+ -+2. Using large messages pressures implementations on small machines to decrypt -+and process plaintext before authenticating it. This is very dangerous, and -+this API does not allow it, but a protocol that uses excessive message sizes -+might present some implementations with no other choice. -+ -+3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. -+ -+4. Performance may be improved by working with messages that fit into data caches. -+ -+Thus large amounts of data should be chunked so that each message is small. -+(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable -+chunk size. -+ -+This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html. -+Anonymous sealing/opening is an extension of NaCl defined by and interoperable -+with libsodium: -+https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes. -+*/ -+package box // import "golang.org/x/crypto/nacl/box" -+ -+import ( -+ cryptorand "crypto/rand" -+ "io" -+ -+ "golang.org/x/crypto/blake2b" -+ "golang.org/x/crypto/curve25519" -+ "golang.org/x/crypto/nacl/secretbox" -+ "golang.org/x/crypto/salsa20/salsa" -+) -+ -+const ( -+ // Overhead is the number of bytes of overhead when boxing a message. -+ Overhead = secretbox.Overhead -+ -+ // AnonymousOverhead is the number of bytes of overhead when using anonymous -+ // sealed boxes. -+ AnonymousOverhead = Overhead + 32 -+) -+ -+// GenerateKey generates a new public/private key pair suitable for use with -+// Seal and Open. -+func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { -+ publicKey = new([32]byte) -+ privateKey = new([32]byte) -+ _, err = io.ReadFull(rand, privateKey[:]) -+ if err != nil { -+ publicKey = nil -+ privateKey = nil -+ return -+ } -+ -+ curve25519.ScalarBaseMult(publicKey, privateKey) -+ return -+} -+ -+var zeros [16]byte -+ -+// Precompute calculates the shared key between peersPublicKey and privateKey -+// and writes it to sharedKey. The shared key can be used with -+// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing -+// when using the same pair of keys repeatedly. -+func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { -+ curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) -+ salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) -+} -+ -+// Seal appends an encrypted and authenticated copy of message to out, which -+// will be Overhead bytes longer than the original and must not overlap it. The -+// nonce must be unique for each distinct message for a given pair of keys. -+func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { -+ var sharedKey [32]byte -+ Precompute(&sharedKey, peersPublicKey, privateKey) -+ return secretbox.Seal(out, message, nonce, &sharedKey) -+} -+ -+// SealAfterPrecomputation performs the same actions as Seal, but takes a -+// shared key as generated by Precompute. -+func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { -+ return secretbox.Seal(out, message, nonce, sharedKey) -+} -+ -+// Open authenticates and decrypts a box produced by Seal and appends the -+// message to out, which must not overlap box. The output will be Overhead -+// bytes smaller than box. -+func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { -+ var sharedKey [32]byte -+ Precompute(&sharedKey, peersPublicKey, privateKey) -+ return secretbox.Open(out, box, nonce, &sharedKey) -+} -+ -+// OpenAfterPrecomputation performs the same actions as Open, but takes a -+// shared key as generated by Precompute. -+func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { -+ return secretbox.Open(out, box, nonce, sharedKey) -+} -+ -+// SealAnonymous appends an encrypted and authenticated copy of message to out, -+// which will be AnonymousOverhead bytes longer than the original and must not -+// overlap it. This differs from Seal in that the sender is not required to -+// provide a private key. -+func SealAnonymous(out, message []byte, recipient *[32]byte, rand io.Reader) ([]byte, error) { -+ if rand == nil { -+ rand = cryptorand.Reader -+ } -+ ephemeralPub, ephemeralPriv, err := GenerateKey(rand) -+ if err != nil { -+ return nil, err -+ } -+ -+ var nonce [24]byte -+ if err := sealNonce(ephemeralPub, recipient, &nonce); err != nil { -+ return nil, err -+ } -+ -+ if total := len(out) + AnonymousOverhead + len(message); cap(out) < total { -+ original := out -+ out = make([]byte, 0, total) -+ out = append(out, original...) -+ } -+ out = append(out, ephemeralPub[:]...) -+ -+ return Seal(out, message, &nonce, recipient, ephemeralPriv), nil -+} -+ -+// OpenAnonymous authenticates and decrypts a box produced by SealAnonymous and -+// appends the message to out, which must not overlap box. The output will be -+// AnonymousOverhead bytes smaller than box. -+func OpenAnonymous(out, box []byte, publicKey, privateKey *[32]byte) (message []byte, ok bool) { -+ if len(box) < AnonymousOverhead { -+ return nil, false -+ } -+ -+ var ephemeralPub [32]byte -+ copy(ephemeralPub[:], box[:32]) -+ -+ var nonce [24]byte -+ if err := sealNonce(&ephemeralPub, publicKey, &nonce); err != nil { -+ return nil, false -+ } -+ -+ return Open(out, box[32:], &nonce, &ephemeralPub, privateKey) -+} -+ -+// sealNonce generates a 24 byte nonce that is a blake2b digest of the -+// ephemeral public key and the receiver's public key. -+func sealNonce(ephemeralPub, peersPublicKey *[32]byte, nonce *[24]byte) error { -+ h, err := blake2b.New(24, nil) -+ if err != nil { -+ return err -+ } -+ -+ if _, err = h.Write(ephemeralPub[:]); err != nil { -+ return err -+ } -+ -+ if _, err = h.Write(peersPublicKey[:]); err != nil { -+ return err -+ } -+ -+ h.Sum(nonce[:0]) -+ -+ return nil -+} -diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go -index a98d1bd45cdc..a2973e626fd8 100644 ---- a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go -+++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go -@@ -35,8 +35,8 @@ This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. - package secretbox // import "golang.org/x/crypto/nacl/secretbox" - - import ( -+ "golang.org/x/crypto/internal/poly1305" - "golang.org/x/crypto/internal/subtle" -- "golang.org/x/crypto/poly1305" - "golang.org/x/crypto/salsa20/salsa" - ) - -diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go -index 9d3fffa8fedd..96972aeabab8 100644 ---- a/vendor/golang.org/x/crypto/ocsp/ocsp.go -+++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go -@@ -668,7 +668,7 @@ func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte - // The responder cert is used to populate the responder's name field, and the - // certificate itself is provided alongside the OCSP response signature. - // --// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields. -+// The issuer cert is used to populate the IssuerNameHash and IssuerKeyHash fields. - // - // The template is used to populate the SerialNumber, Status, RevokedAt, - // RevocationReason, ThisUpdate, and NextUpdate fields. -diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/golang.org/x/crypto/openpgp/armor/armor.go -new file mode 100644 -index 000000000000..ebc87876e6a5 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/armor/armor.go -@@ -0,0 +1,230 @@ -+// Copyright 2010 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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is -+// very similar to PEM except that it has an additional CRC checksum. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package armor // import "golang.org/x/crypto/openpgp/armor" -+ -+import ( -+ "bufio" -+ "bytes" -+ "encoding/base64" -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+) -+ -+// A Block represents an OpenPGP armored structure. -+// -+// The encoded form is: -+// -----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 -+// interface. -+type Block struct { -+ Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). -+ Header map[string]string // Optional headers. -+ Body io.Reader // A Reader from which the contents can be read -+ lReader lineReader -+ oReader openpgpReader -+} -+ -+var ArmorCorrupt error = errors.StructuralError("armor invalid") -+ -+const crc24Init = 0xb704ce -+const crc24Poly = 0x1864cfb -+const crc24Mask = 0xffffff -+ -+// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 -+func crc24(crc uint32, d []byte) uint32 { -+ for _, b := range d { -+ crc ^= uint32(b) << 16 -+ for i := 0; i < 8; i++ { -+ crc <<= 1 -+ if crc&0x1000000 != 0 { -+ crc ^= crc24Poly -+ } -+ } -+ } -+ return crc -+} -+ -+var armorStart = []byte("-----BEGIN ") -+var armorEnd = []byte("-----END ") -+var armorEndOfLine = []byte("-----") -+ -+// lineReader wraps a line based reader. It watches for the end of an armor -+// block and records the expected CRC value. -+type lineReader struct { -+ in *bufio.Reader -+ buf []byte -+ eof bool -+ crc uint32 -+ crcSet bool -+} -+ -+func (l *lineReader) Read(p []byte) (n int, err error) { -+ if l.eof { -+ return 0, io.EOF -+ } -+ -+ if len(l.buf) > 0 { -+ n = copy(p, l.buf) -+ l.buf = l.buf[n:] -+ return -+ } -+ -+ line, isPrefix, err := l.in.ReadLine() -+ if err != nil { -+ return -+ } -+ if isPrefix { -+ return 0, ArmorCorrupt -+ } -+ -+ if bytes.HasPrefix(line, armorEnd) { -+ l.eof = true -+ return 0, io.EOF -+ } -+ -+ if len(line) == 5 && line[0] == '=' { -+ // This is the checksum line -+ var expectedBytes [3]byte -+ var m int -+ m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) -+ if m != 3 || err != nil { -+ return -+ } -+ l.crc = uint32(expectedBytes[0])<<16 | -+ uint32(expectedBytes[1])<<8 | -+ uint32(expectedBytes[2]) -+ -+ line, _, err = l.in.ReadLine() -+ if err != nil && err != io.EOF { -+ return -+ } -+ if !bytes.HasPrefix(line, armorEnd) { -+ return 0, ArmorCorrupt -+ } -+ -+ l.eof = true -+ l.crcSet = true -+ return 0, io.EOF -+ } -+ -+ if len(line) > 96 { -+ return 0, ArmorCorrupt -+ } -+ -+ n = copy(p, line) -+ bytesToSave := len(line) - n -+ if bytesToSave > 0 { -+ if cap(l.buf) < bytesToSave { -+ l.buf = make([]byte, 0, bytesToSave) -+ } -+ l.buf = l.buf[0:bytesToSave] -+ copy(l.buf, line[n:]) -+ } -+ -+ return -+} -+ -+// openpgpReader passes Read calls to the underlying base64 decoder, but keeps -+// a running CRC of the resulting data and checks the CRC against the value -+// found by the lineReader at EOF. -+type openpgpReader struct { -+ lReader *lineReader -+ b64Reader io.Reader -+ currentCRC uint32 -+} -+ -+func (r *openpgpReader) Read(p []byte) (n int, err error) { -+ n, err = r.b64Reader.Read(p) -+ r.currentCRC = crc24(r.currentCRC, p[:n]) -+ -+ if err == io.EOF && r.lReader.crcSet && r.lReader.crc != uint32(r.currentCRC&crc24Mask) { -+ return 0, ArmorCorrupt -+ } -+ -+ return -+} -+ -+// Decode reads a PGP armored block from the given Reader. It will ignore -+// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The -+// given Reader is not usable after calling this function: an arbitrary amount -+// of data may have been read past the end of the block. -+func Decode(in io.Reader) (p *Block, err error) { -+ r := bufio.NewReaderSize(in, 100) -+ var line []byte -+ ignoreNext := false -+ -+TryNextBlock: -+ p = nil -+ -+ // Skip leading garbage -+ for { -+ ignoreThis := ignoreNext -+ line, ignoreNext, err = r.ReadLine() -+ if err != nil { -+ return -+ } -+ if ignoreNext || ignoreThis { -+ continue -+ } -+ line = bytes.TrimSpace(line) -+ if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { -+ break -+ } -+ } -+ -+ p = new(Block) -+ p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) -+ p.Header = make(map[string]string) -+ nextIsContinuation := false -+ var lastKey string -+ -+ // Read headers -+ for { -+ isContinuation := nextIsContinuation -+ line, nextIsContinuation, err = r.ReadLine() -+ if err != nil { -+ p = nil -+ return -+ } -+ if isContinuation { -+ p.Header[lastKey] += string(line) -+ continue -+ } -+ line = bytes.TrimSpace(line) -+ if len(line) == 0 { -+ break -+ } -+ -+ i := bytes.Index(line, []byte(": ")) -+ if i == -1 { -+ goto TryNextBlock -+ } -+ lastKey = string(line[:i]) -+ p.Header[lastKey] = string(line[i+2:]) -+ } -+ -+ p.lReader.in = r -+ p.oReader.currentCRC = crc24Init -+ p.oReader.lReader = &p.lReader -+ p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) -+ p.Body = &p.oReader -+ -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/golang.org/x/crypto/openpgp/armor/encode.go -new file mode 100644 -index 000000000000..6f07582c37ce ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/armor/encode.go -@@ -0,0 +1,160 @@ -+// Copyright 2010 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 armor -+ -+import ( -+ "encoding/base64" -+ "io" -+) -+ -+var armorHeaderSep = []byte(": ") -+var blockEnd = []byte("\n=") -+var newline = []byte("\n") -+var armorEndOfLineOut = []byte("-----\n") -+ -+// writeSlices writes its arguments to the given Writer. -+func writeSlices(out io.Writer, slices ...[]byte) (err error) { -+ for _, s := range slices { -+ _, err = out.Write(s) -+ if err != nil { -+ return err -+ } -+ } -+ return -+} -+ -+// lineBreaker breaks data across several lines, all of the same byte length -+// (except possibly the last). Lines are broken with a single '\n'. -+type lineBreaker struct { -+ lineLength int -+ line []byte -+ used int -+ out io.Writer -+ haveWritten bool -+} -+ -+func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { -+ return &lineBreaker{ -+ lineLength: lineLength, -+ line: make([]byte, lineLength), -+ used: 0, -+ out: out, -+ } -+} -+ -+func (l *lineBreaker) Write(b []byte) (n int, err error) { -+ n = len(b) -+ -+ if n == 0 { -+ return -+ } -+ -+ if l.used == 0 && l.haveWritten { -+ _, err = l.out.Write([]byte{'\n'}) -+ if err != nil { -+ return -+ } -+ } -+ -+ if l.used+len(b) < l.lineLength { -+ l.used += copy(l.line[l.used:], b) -+ return -+ } -+ -+ l.haveWritten = true -+ _, err = l.out.Write(l.line[0:l.used]) -+ if err != nil { -+ return -+ } -+ excess := l.lineLength - l.used -+ l.used = 0 -+ -+ _, err = l.out.Write(b[0:excess]) -+ if err != nil { -+ return -+ } -+ -+ _, err = l.Write(b[excess:]) -+ return -+} -+ -+func (l *lineBreaker) Close() (err error) { -+ if l.used > 0 { -+ _, err = l.out.Write(l.line[0:l.used]) -+ if err != nil { -+ return -+ } -+ } -+ -+ return -+} -+ -+// encoding keeps track of a running CRC24 over the data which has been written -+// to it and outputs a OpenPGP checksum when closed, followed by an armor -+// trailer. -+// -+// It's built into a stack of io.Writers: -+// encoding -> base64 encoder -> lineBreaker -> out -+type encoding struct { -+ out io.Writer -+ breaker *lineBreaker -+ b64 io.WriteCloser -+ crc uint32 -+ blockType []byte -+} -+ -+func (e *encoding) Write(data []byte) (n int, err error) { -+ e.crc = crc24(e.crc, data) -+ return e.b64.Write(data) -+} -+ -+func (e *encoding) Close() (err error) { -+ err = e.b64.Close() -+ if err != nil { -+ return -+ } -+ e.breaker.Close() -+ -+ var checksumBytes [3]byte -+ checksumBytes[0] = byte(e.crc >> 16) -+ checksumBytes[1] = byte(e.crc >> 8) -+ checksumBytes[2] = byte(e.crc) -+ -+ var b64ChecksumBytes [4]byte -+ base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) -+ -+ return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) -+} -+ -+// Encode returns a WriteCloser which will encode the data written to it in -+// OpenPGP armor. -+func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { -+ bType := []byte(blockType) -+ err = writeSlices(out, armorStart, bType, armorEndOfLineOut) -+ if err != nil { -+ return -+ } -+ -+ for k, v := range headers { -+ err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) -+ if err != nil { -+ return -+ } -+ } -+ -+ _, err = out.Write(newline) -+ if err != nil { -+ return -+ } -+ -+ e := &encoding{ -+ out: out, -+ breaker: newLineBreaker(out, 64), -+ crc: crc24Init, -+ blockType: bType, -+ } -+ e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) -+ return e, nil -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/golang.org/x/crypto/openpgp/canonical_text.go -new file mode 100644 -index 000000000000..e601e389f129 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/canonical_text.go -@@ -0,0 +1,59 @@ -+// 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 openpgp -+ -+import "hash" -+ -+// NewCanonicalTextHash reformats text written to it into the canonical -+// form and then applies the hash h. See RFC 4880, section 5.2.1. -+func NewCanonicalTextHash(h hash.Hash) hash.Hash { -+ return &canonicalTextHash{h, 0} -+} -+ -+type canonicalTextHash struct { -+ h hash.Hash -+ s int -+} -+ -+var newline = []byte{'\r', '\n'} -+ -+func (cth *canonicalTextHash) Write(buf []byte) (int, error) { -+ start := 0 -+ -+ for i, c := range buf { -+ switch cth.s { -+ case 0: -+ if c == '\r' { -+ cth.s = 1 -+ } else if c == '\n' { -+ cth.h.Write(buf[start:i]) -+ cth.h.Write(newline) -+ start = i + 1 -+ } -+ case 1: -+ cth.s = 0 -+ } -+ } -+ -+ cth.h.Write(buf[start:]) -+ return len(buf), nil -+} -+ -+func (cth *canonicalTextHash) Sum(in []byte) []byte { -+ return cth.h.Sum(in) -+} -+ -+func (cth *canonicalTextHash) Reset() { -+ cth.h.Reset() -+ cth.s = 0 -+} -+ -+func (cth *canonicalTextHash) Size() int { -+ return cth.h.Size() -+} -+ -+func (cth *canonicalTextHash) BlockSize() int { -+ return cth.h.BlockSize() -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go -new file mode 100644 -index 000000000000..644b2e078bc9 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go -@@ -0,0 +1,424 @@ -+// Copyright 2012 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 clearsign generates and processes OpenPGP, clear-signed data. See -+// RFC 4880, section 7. -+// -+// Clearsigned messages are cryptographically signed, but the contents of the -+// message are kept in plaintext so that it can be read without special tools. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package clearsign // import "golang.org/x/crypto/openpgp/clearsign" -+ -+import ( -+ "bufio" -+ "bytes" -+ "crypto" -+ "fmt" -+ "hash" -+ "io" -+ "net/textproto" -+ "strconv" -+ "strings" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+// A Block represents a clearsigned message. A signature on a Block can -+// be checked by passing Bytes into openpgp.CheckDetachedSignature. -+type Block struct { -+ Headers textproto.MIMEHeader // Optional unverified Hash headers -+ Plaintext []byte // The original message text -+ Bytes []byte // The signed message -+ ArmoredSignature *armor.Block // The signature block -+} -+ -+// start is the marker which denotes the beginning of a clearsigned message. -+var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----") -+ -+// dashEscape is prefixed to any lines that begin with a hyphen so that they -+// can't be confused with endText. -+var dashEscape = []byte("- ") -+ -+// endText is a marker which denotes the end of the message and the start of -+// an armored signature. -+var endText = []byte("-----BEGIN PGP SIGNATURE-----") -+ -+// end is a marker which denotes the end of the armored signature. -+var end = []byte("\n-----END PGP SIGNATURE-----") -+ -+var crlf = []byte("\r\n") -+var lf = byte('\n') -+ -+// getLine returns the first \r\n or \n delineated line from the given byte -+// array. The line does not include the \r\n or \n. The remainder of the byte -+// array (also not including the new line bytes) is also returned and this will -+// always be smaller than the original argument. -+func getLine(data []byte) (line, rest []byte) { -+ i := bytes.Index(data, []byte{'\n'}) -+ var j int -+ if i < 0 { -+ i = len(data) -+ j = i -+ } else { -+ j = i + 1 -+ if i > 0 && data[i-1] == '\r' { -+ i-- -+ } -+ } -+ return data[0:i], data[j:] -+} -+ -+// Decode finds the first clearsigned message in data and returns it, as well as -+// the suffix of data which remains after the message. Any prefix data is -+// discarded. -+// -+// If no message is found, or if the message is invalid, Decode returns nil and -+// the whole data slice. The only allowed header type is Hash, and it is not -+// verified against the signature hash. -+func Decode(data []byte) (b *Block, rest []byte) { -+ // start begins with a newline. However, at the very beginning of -+ // the byte array, we'll accept the start string without it. -+ rest = data -+ if bytes.HasPrefix(data, start[1:]) { -+ rest = rest[len(start)-1:] -+ } else if i := bytes.Index(data, start); i >= 0 { -+ rest = rest[i+len(start):] -+ } else { -+ return nil, data -+ } -+ -+ // Consume the start line and check it does not have a suffix. -+ suffix, rest := getLine(rest) -+ if len(suffix) != 0 { -+ return nil, data -+ } -+ -+ var line []byte -+ b = &Block{ -+ Headers: make(textproto.MIMEHeader), -+ } -+ -+ // Next come a series of header lines. -+ for { -+ // This loop terminates because getLine's second result is -+ // always smaller than its argument. -+ if len(rest) == 0 { -+ return nil, data -+ } -+ // An empty line marks the end of the headers. -+ if line, rest = getLine(rest); len(line) == 0 { -+ break -+ } -+ -+ // Reject headers with control or Unicode characters. -+ if i := bytes.IndexFunc(line, func(r rune) bool { -+ return r < 0x20 || r > 0x7e -+ }); i != -1 { -+ return nil, data -+ } -+ -+ i := bytes.Index(line, []byte{':'}) -+ if i == -1 { -+ return nil, data -+ } -+ -+ key, val := string(line[0:i]), string(line[i+1:]) -+ key = strings.TrimSpace(key) -+ if key != "Hash" { -+ return nil, data -+ } -+ val = strings.TrimSpace(val) -+ b.Headers.Add(key, val) -+ } -+ -+ firstLine := true -+ for { -+ start := rest -+ -+ line, rest = getLine(rest) -+ if len(line) == 0 && len(rest) == 0 { -+ // No armored data was found, so this isn't a complete message. -+ return nil, data -+ } -+ if bytes.Equal(line, endText) { -+ // Back up to the start of the line because armor expects to see the -+ // header line. -+ rest = start -+ break -+ } -+ -+ // The final CRLF isn't included in the hash so we don't write it until -+ // we've seen the next line. -+ if firstLine { -+ firstLine = false -+ } else { -+ b.Bytes = append(b.Bytes, crlf...) -+ } -+ -+ if bytes.HasPrefix(line, dashEscape) { -+ line = line[2:] -+ } -+ line = bytes.TrimRight(line, " \t") -+ b.Bytes = append(b.Bytes, line...) -+ -+ b.Plaintext = append(b.Plaintext, line...) -+ b.Plaintext = append(b.Plaintext, lf) -+ } -+ -+ // We want to find the extent of the armored data (including any newlines at -+ // the end). -+ i := bytes.Index(rest, end) -+ if i == -1 { -+ return nil, data -+ } -+ i += len(end) -+ for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') { -+ i++ -+ } -+ armored := rest[:i] -+ rest = rest[i:] -+ -+ var err error -+ b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored)) -+ if err != nil { -+ return nil, data -+ } -+ -+ return b, rest -+} -+ -+// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed -+// message. The clear-signed message is written to buffered and a hash, suitable -+// for signing, is maintained in h. -+// -+// When closed, an armored signature is created and written to complete the -+// message. -+type dashEscaper struct { -+ buffered *bufio.Writer -+ hashers []hash.Hash // one per key in privateKeys -+ hashType crypto.Hash -+ toHash io.Writer // writes to all the hashes in hashers -+ -+ atBeginningOfLine bool -+ isFirstLine bool -+ -+ whitespace []byte -+ byteBuf []byte // a one byte buffer to save allocations -+ -+ privateKeys []*packet.PrivateKey -+ config *packet.Config -+} -+ -+func (d *dashEscaper) Write(data []byte) (n int, err error) { -+ for _, b := range data { -+ d.byteBuf[0] = b -+ -+ if d.atBeginningOfLine { -+ // The final CRLF isn't included in the hash so we have to wait -+ // until this point (the start of the next line) before writing it. -+ if !d.isFirstLine { -+ d.toHash.Write(crlf) -+ } -+ d.isFirstLine = false -+ } -+ -+ // Any whitespace at the end of the line has to be removed so we -+ // buffer it until we find out whether there's more on this line. -+ if b == ' ' || b == '\t' || b == '\r' { -+ d.whitespace = append(d.whitespace, b) -+ d.atBeginningOfLine = false -+ continue -+ } -+ -+ if d.atBeginningOfLine { -+ // At the beginning of a line, hyphens have to be escaped. -+ if b == '-' { -+ // The signature isn't calculated over the dash-escaped text so -+ // the escape is only written to buffered. -+ if _, err = d.buffered.Write(dashEscape); err != nil { -+ return -+ } -+ d.toHash.Write(d.byteBuf) -+ d.atBeginningOfLine = false -+ } else if b == '\n' { -+ // Nothing to do because we delay writing CRLF to the hash. -+ } else { -+ d.toHash.Write(d.byteBuf) -+ d.atBeginningOfLine = false -+ } -+ if err = d.buffered.WriteByte(b); err != nil { -+ return -+ } -+ } else { -+ if b == '\n' { -+ // We got a raw \n. Drop any trailing whitespace and write a -+ // CRLF. -+ d.whitespace = d.whitespace[:0] -+ // We delay writing CRLF to the hash until the start of the -+ // next line. -+ if err = d.buffered.WriteByte(b); err != nil { -+ return -+ } -+ d.atBeginningOfLine = true -+ } else { -+ // Any buffered whitespace wasn't at the end of the line so -+ // we need to write it out. -+ if len(d.whitespace) > 0 { -+ d.toHash.Write(d.whitespace) -+ if _, err = d.buffered.Write(d.whitespace); err != nil { -+ return -+ } -+ d.whitespace = d.whitespace[:0] -+ } -+ d.toHash.Write(d.byteBuf) -+ if err = d.buffered.WriteByte(b); err != nil { -+ return -+ } -+ } -+ } -+ } -+ -+ n = len(data) -+ return -+} -+ -+func (d *dashEscaper) Close() (err error) { -+ if !d.atBeginningOfLine { -+ if err = d.buffered.WriteByte(lf); err != nil { -+ return -+ } -+ } -+ -+ out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil) -+ if err != nil { -+ return -+ } -+ -+ t := d.config.Now() -+ for i, k := range d.privateKeys { -+ sig := new(packet.Signature) -+ sig.SigType = packet.SigTypeText -+ sig.PubKeyAlgo = k.PubKeyAlgo -+ sig.Hash = d.hashType -+ sig.CreationTime = t -+ sig.IssuerKeyId = &k.KeyId -+ -+ if err = sig.Sign(d.hashers[i], k, d.config); err != nil { -+ return -+ } -+ if err = sig.Serialize(out); err != nil { -+ return -+ } -+ } -+ -+ if err = out.Close(); err != nil { -+ return -+ } -+ if err = d.buffered.Flush(); err != nil { -+ return -+ } -+ return -+} -+ -+// Encode returns a WriteCloser which will clear-sign a message with privateKey -+// and write it to w. If config is nil, sensible defaults are used. -+func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ return EncodeMulti(w, []*packet.PrivateKey{privateKey}, config) -+} -+ -+// EncodeMulti returns a WriteCloser which will clear-sign a message with all the -+// private keys indicated and write it to w. If config is nil, sensible defaults -+// are used. -+func EncodeMulti(w io.Writer, privateKeys []*packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ for _, k := range privateKeys { -+ if k.Encrypted { -+ return nil, errors.InvalidArgumentError(fmt.Sprintf("signing key %s is encrypted", k.KeyIdString())) -+ } -+ } -+ -+ hashType := config.Hash() -+ name := nameOfHash(hashType) -+ if len(name) == 0 { -+ return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType))) -+ } -+ -+ if !hashType.Available() { -+ return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType))) -+ } -+ var hashers []hash.Hash -+ var ws []io.Writer -+ for range privateKeys { -+ h := hashType.New() -+ hashers = append(hashers, h) -+ ws = append(ws, h) -+ } -+ toHash := io.MultiWriter(ws...) -+ -+ buffered := bufio.NewWriter(w) -+ // start has a \n at the beginning that we don't want here. -+ if _, err = buffered.Write(start[1:]); err != nil { -+ return -+ } -+ if err = buffered.WriteByte(lf); err != nil { -+ return -+ } -+ if _, err = buffered.WriteString("Hash: "); err != nil { -+ return -+ } -+ if _, err = buffered.WriteString(name); err != nil { -+ return -+ } -+ if err = buffered.WriteByte(lf); err != nil { -+ return -+ } -+ if err = buffered.WriteByte(lf); err != nil { -+ return -+ } -+ -+ plaintext = &dashEscaper{ -+ buffered: buffered, -+ hashers: hashers, -+ hashType: hashType, -+ toHash: toHash, -+ -+ atBeginningOfLine: true, -+ isFirstLine: true, -+ -+ byteBuf: make([]byte, 1), -+ -+ privateKeys: privateKeys, -+ config: config, -+ } -+ -+ return -+} -+ -+// nameOfHash returns the OpenPGP name for the given hash, or the empty string -+// if the name isn't known. See RFC 4880, section 9.4. -+func nameOfHash(h crypto.Hash) string { -+ switch h { -+ case crypto.MD5: -+ return "MD5" -+ case crypto.SHA1: -+ return "SHA1" -+ case crypto.RIPEMD160: -+ return "RIPEMD160" -+ case crypto.SHA224: -+ return "SHA224" -+ case crypto.SHA256: -+ return "SHA256" -+ case crypto.SHA384: -+ return "SHA384" -+ case crypto.SHA512: -+ return "SHA512" -+ } -+ return "" -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go -new file mode 100644 -index 000000000000..84396a089669 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go -@@ -0,0 +1,130 @@ -+// 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 elgamal implements ElGamal encryption, suitable for OpenPGP, -+// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on -+// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, -+// n. 4, 1985, pp. 469-472. -+// -+// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it -+// unsuitable for other protocols. RSA should be used in preference in any -+// case. -+// -+// Deprecated: this package was only provided to support ElGamal encryption in -+// OpenPGP. The golang.org/x/crypto/openpgp package is now deprecated (see -+// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has -+// compatibility and security issues (see https://eprint.iacr.org/2021/923). -+// Moreover, this package doesn't protect against side-channel attacks. -+package elgamal // import "golang.org/x/crypto/openpgp/elgamal" -+ -+import ( -+ "crypto/rand" -+ "crypto/subtle" -+ "errors" -+ "io" -+ "math/big" -+) -+ -+// PublicKey represents an ElGamal public key. -+type PublicKey struct { -+ G, P, Y *big.Int -+} -+ -+// PrivateKey represents an ElGamal private key. -+type PrivateKey struct { -+ PublicKey -+ X *big.Int -+} -+ -+// Encrypt encrypts the given message to the given public key. The result is a -+// pair of integers. Errors can result from reading random, or because msg is -+// too large to be encrypted to the public key. -+func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { -+ pLen := (pub.P.BitLen() + 7) / 8 -+ if len(msg) > pLen-11 { -+ err = errors.New("elgamal: message too long") -+ return -+ } -+ -+ // EM = 0x02 || PS || 0x00 || M -+ em := make([]byte, pLen-1) -+ em[0] = 2 -+ ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] -+ err = nonZeroRandomBytes(ps, random) -+ if err != nil { -+ return -+ } -+ em[len(em)-len(msg)-1] = 0 -+ copy(mm, msg) -+ -+ m := new(big.Int).SetBytes(em) -+ -+ k, err := rand.Int(random, pub.P) -+ if err != nil { -+ return -+ } -+ -+ c1 = new(big.Int).Exp(pub.G, k, pub.P) -+ s := new(big.Int).Exp(pub.Y, k, pub.P) -+ c2 = s.Mul(s, m) -+ c2.Mod(c2, pub.P) -+ -+ return -+} -+ -+// Decrypt takes two integers, resulting from an ElGamal encryption, and -+// 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 -+// 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) -+ if s.ModInverse(s, priv.P) == nil { -+ return nil, errors.New("elgamal: invalid private key") -+ } -+ s.Mul(s, c2) -+ s.Mod(s, priv.P) -+ em := s.Bytes() -+ -+ firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) -+ -+ // The remainder of the plaintext must be a string of non-zero random -+ // octets, followed by a 0, followed by the message. -+ // lookingForIndex: 1 iff we are still looking for the zero. -+ // index: the offset of the first zero byte. -+ var lookingForIndex, index int -+ lookingForIndex = 1 -+ -+ for i := 1; i < len(em); i++ { -+ equals0 := subtle.ConstantTimeByteEq(em[i], 0) -+ index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) -+ lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) -+ } -+ -+ if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { -+ return nil, errors.New("elgamal: decryption error") -+ } -+ return em[index+1:], nil -+} -+ -+// nonZeroRandomBytes fills the given slice with non-zero random octets. -+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { -+ _, err = io.ReadFull(rand, s) -+ if err != nil { -+ return -+ } -+ -+ for i := 0; i < len(s); i++ { -+ for s[i] == 0 { -+ _, err = io.ReadFull(rand, s[i:i+1]) -+ if err != nil { -+ return -+ } -+ } -+ } -+ -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/golang.org/x/crypto/openpgp/errors/errors.go -new file mode 100644 -index 000000000000..1d7a0ea05adf ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/errors/errors.go -@@ -0,0 +1,78 @@ -+// Copyright 2010 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 errors contains common error types for the OpenPGP packages. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package errors // import "golang.org/x/crypto/openpgp/errors" -+ -+import ( -+ "strconv" -+) -+ -+// A StructuralError is returned when OpenPGP data is found to be syntactically -+// invalid. -+type StructuralError string -+ -+func (s StructuralError) Error() string { -+ return "openpgp: invalid data: " + string(s) -+} -+ -+// UnsupportedError indicates that, although the OpenPGP data is valid, it -+// makes use of currently unimplemented features. -+type UnsupportedError string -+ -+func (s UnsupportedError) Error() string { -+ return "openpgp: unsupported feature: " + string(s) -+} -+ -+// InvalidArgumentError indicates that the caller is in error and passed an -+// incorrect value. -+type InvalidArgumentError string -+ -+func (i InvalidArgumentError) Error() string { -+ return "openpgp: invalid argument: " + string(i) -+} -+ -+// SignatureError indicates that a syntactically valid signature failed to -+// validate. -+type SignatureError string -+ -+func (b SignatureError) Error() string { -+ return "openpgp: invalid signature: " + string(b) -+} -+ -+type keyIncorrectError int -+ -+func (ki keyIncorrectError) Error() string { -+ return "openpgp: incorrect key" -+} -+ -+var ErrKeyIncorrect error = keyIncorrectError(0) -+ -+type unknownIssuerError int -+ -+func (unknownIssuerError) Error() string { -+ return "openpgp: signature made by unknown entity" -+} -+ -+var ErrUnknownIssuer error = unknownIssuerError(0) -+ -+type keyRevokedError int -+ -+func (keyRevokedError) Error() string { -+ return "openpgp: signature made by revoked key" -+} -+ -+var ErrKeyRevoked error = keyRevokedError(0) -+ -+type UnknownPacketTypeError uint8 -+ -+func (upte UnknownPacketTypeError) Error() string { -+ return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go -new file mode 100644 -index 000000000000..faa2fb3693e9 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/keys.go -@@ -0,0 +1,693 @@ -+// 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 openpgp -+ -+import ( -+ "crypto/rsa" -+ "io" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+// PublicKeyType is the armor type for a PGP public key. -+var PublicKeyType = "PGP PUBLIC KEY BLOCK" -+ -+// PrivateKeyType is the armor type for a PGP private key. -+var PrivateKeyType = "PGP PRIVATE KEY BLOCK" -+ -+// An Entity represents the components of an OpenPGP key: a primary public key -+// (which must be a signing key), one or more identities claimed by that key, -+// and zero or more subkeys, which may be encryption keys. -+type Entity struct { -+ PrimaryKey *packet.PublicKey -+ PrivateKey *packet.PrivateKey -+ Identities map[string]*Identity // indexed by Identity.Name -+ Revocations []*packet.Signature -+ Subkeys []Subkey -+} -+ -+// An Identity represents an identity claimed by an Entity and zero or more -+// assertions by other entities about that claim. -+type Identity struct { -+ Name string // by convention, has the form "Full Name (comment) " -+ UserId *packet.UserId -+ SelfSignature *packet.Signature -+ Signatures []*packet.Signature -+} -+ -+// A Subkey is an additional public key in an Entity. Subkeys can be used for -+// encryption. -+type Subkey struct { -+ PublicKey *packet.PublicKey -+ PrivateKey *packet.PrivateKey -+ Sig *packet.Signature -+} -+ -+// A Key identifies a specific public key in an Entity. This is either the -+// Entity's primary key or a subkey. -+type Key struct { -+ Entity *Entity -+ PublicKey *packet.PublicKey -+ PrivateKey *packet.PrivateKey -+ SelfSignature *packet.Signature -+} -+ -+// A KeyRing provides access to public and private keys. -+type KeyRing interface { -+ // KeysById returns the set of keys that have the given key id. -+ KeysById(id uint64) []Key -+ // KeysByIdAndUsage returns the set of keys with the given id -+ // that also meet the key usage given by requiredUsage. -+ // The requiredUsage is expressed as the bitwise-OR of -+ // packet.KeyFlag* values. -+ KeysByIdUsage(id uint64, requiredUsage byte) []Key -+ // DecryptionKeys returns all private keys that are valid for -+ // decryption. -+ DecryptionKeys() []Key -+} -+ -+// primaryIdentity returns the Identity marked as primary or the first identity -+// if none are so marked. -+func (e *Entity) primaryIdentity() *Identity { -+ var firstIdentity *Identity -+ for _, ident := range e.Identities { -+ if firstIdentity == nil { -+ firstIdentity = ident -+ } -+ if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { -+ return ident -+ } -+ } -+ return firstIdentity -+} -+ -+// encryptionKey returns the best candidate Key for encrypting a message to the -+// given Entity. -+func (e *Entity) encryptionKey(now time.Time) (Key, bool) { -+ candidateSubkey := -1 -+ -+ // Iterate the keys to find the newest key -+ var maxTime time.Time -+ for i, subkey := range e.Subkeys { -+ if subkey.Sig.FlagsValid && -+ subkey.Sig.FlagEncryptCommunications && -+ subkey.PublicKey.PubKeyAlgo.CanEncrypt() && -+ !subkey.Sig.KeyExpired(now) && -+ (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { -+ candidateSubkey = i -+ maxTime = subkey.Sig.CreationTime -+ } -+ } -+ -+ if candidateSubkey != -1 { -+ subkey := e.Subkeys[candidateSubkey] -+ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, 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 to, then we can obviously use it. -+ i := e.primaryIdentity() -+ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && -+ e.PrimaryKey.PubKeyAlgo.CanEncrypt() && -+ !i.SelfSignature.KeyExpired(now) { -+ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true -+ } -+ -+ // This Entity appears to be signing only. -+ return Key{}, false -+} -+ -+// signingKey return the best candidate Key for signing a message with this -+// Entity. -+func (e *Entity) signingKey(now time.Time) (Key, bool) { -+ candidateSubkey := -1 -+ -+ for i, subkey := range e.Subkeys { -+ if subkey.Sig.FlagsValid && -+ subkey.Sig.FlagSign && -+ subkey.PublicKey.PubKeyAlgo.CanSign() && -+ !subkey.Sig.KeyExpired(now) { -+ candidateSubkey = i -+ break -+ } -+ } -+ -+ if candidateSubkey != -1 { -+ subkey := e.Subkeys[candidateSubkey] -+ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true -+ } -+ -+ // If we have no candidate subkey then we assume that it's ok to sign -+ // with the primary key. -+ i := e.primaryIdentity() -+ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && -+ !i.SelfSignature.KeyExpired(now) { -+ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true -+ } -+ -+ return Key{}, false -+} -+ -+// An EntityList contains one or more Entities. -+type EntityList []*Entity -+ -+// KeysById returns the set of keys that have the given key id. -+func (el EntityList) KeysById(id uint64) (keys []Key) { -+ for _, e := range el { -+ if e.PrimaryKey.KeyId == id { -+ var selfSig *packet.Signature -+ for _, ident := range e.Identities { -+ if selfSig == nil { -+ selfSig = ident.SelfSignature -+ } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { -+ selfSig = ident.SelfSignature -+ break -+ } -+ } -+ keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) -+ } -+ -+ for _, subKey := range e.Subkeys { -+ if subKey.PublicKey.KeyId == id { -+ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) -+ } -+ } -+ } -+ return -+} -+ -+// KeysByIdAndUsage returns the set of keys with the given id that also meet -+// the key usage given by requiredUsage. The requiredUsage is expressed as -+// the bitwise-OR of packet.KeyFlag* values. -+func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { -+ for _, key := range el.KeysById(id) { -+ if len(key.Entity.Revocations) > 0 { -+ continue -+ } -+ -+ if key.SelfSignature.RevocationReason != nil { -+ continue -+ } -+ -+ if key.SelfSignature.FlagsValid && requiredUsage != 0 { -+ var usage byte -+ if key.SelfSignature.FlagCertify { -+ usage |= packet.KeyFlagCertify -+ } -+ if key.SelfSignature.FlagSign { -+ usage |= packet.KeyFlagSign -+ } -+ if key.SelfSignature.FlagEncryptCommunications { -+ usage |= packet.KeyFlagEncryptCommunications -+ } -+ if key.SelfSignature.FlagEncryptStorage { -+ usage |= packet.KeyFlagEncryptStorage -+ } -+ if usage&requiredUsage != requiredUsage { -+ continue -+ } -+ } -+ -+ keys = append(keys, key) -+ } -+ return -+} -+ -+// DecryptionKeys returns all private keys that are valid for decryption. -+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) { -+ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) -+ } -+ } -+ } -+ return -+} -+ -+// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. -+func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { -+ block, err := armor.Decode(r) -+ if err == io.EOF { -+ return nil, errors.InvalidArgumentError("no armored data found") -+ } -+ if err != nil { -+ return nil, err -+ } -+ if block.Type != PublicKeyType && block.Type != PrivateKeyType { -+ return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) -+ } -+ -+ return ReadKeyRing(block.Body) -+} -+ -+// ReadKeyRing reads one or more public/private keys. Unsupported keys are -+// ignored as long as at least a single valid key is found. -+func ReadKeyRing(r io.Reader) (el EntityList, err error) { -+ packets := packet.NewReader(r) -+ var lastUnsupportedError error -+ -+ for { -+ var e *Entity -+ e, err = ReadEntity(packets) -+ if err != nil { -+ // TODO: warn about skipped unsupported/unreadable keys -+ if _, ok := err.(errors.UnsupportedError); ok { -+ lastUnsupportedError = err -+ err = readToNextPublicKey(packets) -+ } else if _, ok := err.(errors.StructuralError); ok { -+ // Skip unreadable, badly-formatted keys -+ lastUnsupportedError = err -+ err = readToNextPublicKey(packets) -+ } -+ if err == io.EOF { -+ err = nil -+ break -+ } -+ if err != nil { -+ el = nil -+ break -+ } -+ } else { -+ el = append(el, e) -+ } -+ } -+ -+ if len(el) == 0 && err == nil { -+ err = lastUnsupportedError -+ } -+ return -+} -+ -+// readToNextPublicKey reads packets until the start of the entity and leaves -+// the first packet of the new entity in the Reader. -+func readToNextPublicKey(packets *packet.Reader) (err error) { -+ var p packet.Packet -+ for { -+ p, err = packets.Next() -+ if err == io.EOF { -+ return -+ } else if err != nil { -+ if _, ok := err.(errors.UnsupportedError); ok { -+ err = nil -+ continue -+ } -+ return -+ } -+ -+ if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { -+ packets.Unread(p) -+ return -+ } -+ } -+} -+ -+// ReadEntity reads an entity (public key, identities, subkeys etc) from the -+// given Reader. -+func ReadEntity(packets *packet.Reader) (*Entity, error) { -+ e := new(Entity) -+ e.Identities = make(map[string]*Identity) -+ -+ p, err := packets.Next() -+ if err != nil { -+ return nil, err -+ } -+ -+ var ok bool -+ if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { -+ if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { -+ packets.Unread(p) -+ return nil, errors.StructuralError("first packet was not a public/private key") -+ } -+ e.PrimaryKey = &e.PrivateKey.PublicKey -+ } -+ -+ if !e.PrimaryKey.PubKeyAlgo.CanSign() { -+ return nil, errors.StructuralError("primary key cannot be used for signatures") -+ } -+ -+ var revocations []*packet.Signature -+EachPacket: -+ for { -+ p, err := packets.Next() -+ if err == io.EOF { -+ break -+ } else if err != nil { -+ return nil, err -+ } -+ -+ switch pkt := p.(type) { -+ case *packet.UserId: -+ if err := addUserID(e, packets, pkt); err != nil { -+ return nil, err -+ } -+ case *packet.Signature: -+ if pkt.SigType == packet.SigTypeKeyRevocation { -+ revocations = append(revocations, pkt) -+ } else if pkt.SigType == packet.SigTypeDirectSignature { -+ // TODO: RFC4880 5.2.1 permits signatures -+ // directly on keys (eg. to bind additional -+ // revocation keys). -+ } -+ // Else, ignoring the signature as it does not follow anything -+ // we would know to attach it to. -+ case *packet.PrivateKey: -+ if pkt.IsSubkey == false { -+ packets.Unread(p) -+ break EachPacket -+ } -+ err = addSubkey(e, packets, &pkt.PublicKey, pkt) -+ if err != nil { -+ return nil, err -+ } -+ case *packet.PublicKey: -+ if pkt.IsSubkey == false { -+ packets.Unread(p) -+ break EachPacket -+ } -+ err = addSubkey(e, packets, pkt, nil) -+ if err != nil { -+ return nil, err -+ } -+ default: -+ // we ignore unknown packets -+ } -+ } -+ -+ if len(e.Identities) == 0 { -+ return nil, errors.StructuralError("entity without any identities") -+ } -+ -+ for _, revocation := range revocations { -+ err = e.PrimaryKey.VerifyRevocationSignature(revocation) -+ if err == nil { -+ e.Revocations = append(e.Revocations, revocation) -+ } else { -+ // TODO: RFC 4880 5.2.3.15 defines revocation keys. -+ return nil, errors.StructuralError("revocation signature signed by alternate key") -+ } -+ } -+ -+ return e, nil -+} -+ -+func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error { -+ // Make a new Identity object, that we might wind up throwing away. -+ // We'll only add it if we get a valid self-signature over this -+ // userID. -+ identity := new(Identity) -+ identity.Name = pkt.Id -+ identity.UserId = pkt -+ -+ for { -+ p, err := packets.Next() -+ if err == io.EOF { -+ break -+ } else if err != nil { -+ return err -+ } -+ -+ sig, ok := p.(*packet.Signature) -+ if !ok { -+ packets.Unread(p) -+ break -+ } -+ -+ if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { -+ if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { -+ return errors.StructuralError("user ID self-signature invalid: " + err.Error()) -+ } -+ identity.SelfSignature = sig -+ e.Identities[pkt.Id] = identity -+ } else { -+ identity.Signatures = append(identity.Signatures, sig) -+ } -+ } -+ -+ return nil -+} -+ -+func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { -+ var subKey Subkey -+ subKey.PublicKey = pub -+ subKey.PrivateKey = priv -+ -+ for { -+ p, err := packets.Next() -+ if err == io.EOF { -+ break -+ } else if err != nil { -+ return errors.StructuralError("subkey signature invalid: " + err.Error()) -+ } -+ -+ sig, ok := p.(*packet.Signature) -+ if !ok { -+ packets.Unread(p) -+ break -+ } -+ -+ if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation { -+ return errors.StructuralError("subkey signature with wrong type") -+ } -+ -+ if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil { -+ return errors.StructuralError("subkey signature invalid: " + err.Error()) -+ } -+ -+ switch sig.SigType { -+ case packet.SigTypeSubkeyRevocation: -+ subKey.Sig = sig -+ case packet.SigTypeSubkeyBinding: -+ -+ if shouldReplaceSubkeySig(subKey.Sig, sig) { -+ subKey.Sig = sig -+ } -+ } -+ } -+ -+ if subKey.Sig == nil { -+ return errors.StructuralError("subkey packet not followed by signature") -+ } -+ -+ e.Subkeys = append(e.Subkeys, subKey) -+ -+ return nil -+} -+ -+func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool { -+ if potentialNewSig == nil { -+ return false -+ } -+ -+ if existingSig == nil { -+ return true -+ } -+ -+ if existingSig.SigType == packet.SigTypeSubkeyRevocation { -+ return false // never override a revocation signature -+ } -+ -+ return potentialNewSig.CreationTime.After(existingSig.CreationTime) -+} -+ -+const defaultRSAKeyBits = 2048 -+ -+// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a -+// single identity composed of the given full name, comment and email, any of -+// which may be empty but must not contain any of "()<>\x00". -+// If config is nil, sensible defaults will be used. -+func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { -+ creationTime := config.Now() -+ -+ bits := defaultRSAKeyBits -+ if config != nil && config.RSABits != 0 { -+ bits = config.RSABits -+ } -+ -+ uid := packet.NewUserId(name, comment, email) -+ if uid == nil { -+ return nil, errors.InvalidArgumentError("user id field contained invalid characters") -+ } -+ signingPriv, err := rsa.GenerateKey(config.Random(), bits) -+ if err != nil { -+ return nil, err -+ } -+ encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) -+ if err != nil { -+ return nil, err -+ } -+ -+ e := &Entity{ -+ PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey), -+ PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv), -+ Identities: make(map[string]*Identity), -+ } -+ isPrimaryId := true -+ e.Identities[uid.Id] = &Identity{ -+ Name: uid.Id, -+ UserId: uid, -+ SelfSignature: &packet.Signature{ -+ CreationTime: creationTime, -+ SigType: packet.SigTypePositiveCert, -+ PubKeyAlgo: packet.PubKeyAlgoRSA, -+ Hash: config.Hash(), -+ IsPrimaryId: &isPrimaryId, -+ FlagsValid: true, -+ FlagSign: true, -+ FlagCertify: true, -+ IssuerKeyId: &e.PrimaryKey.KeyId, -+ }, -+ } -+ err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) -+ if err != nil { -+ return nil, err -+ } -+ -+ // If the user passes in a DefaultHash via packet.Config, -+ // set the PreferredHash for the SelfSignature. -+ if config != nil && config.DefaultHash != 0 { -+ e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} -+ } -+ -+ // Likewise for DefaultCipher. -+ if config != nil && config.DefaultCipher != 0 { -+ e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} -+ } -+ -+ e.Subkeys = make([]Subkey, 1) -+ e.Subkeys[0] = Subkey{ -+ PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey), -+ PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv), -+ Sig: &packet.Signature{ -+ CreationTime: creationTime, -+ SigType: packet.SigTypeSubkeyBinding, -+ PubKeyAlgo: packet.PubKeyAlgoRSA, -+ Hash: config.Hash(), -+ FlagsValid: true, -+ FlagEncryptStorage: true, -+ FlagEncryptCommunications: true, -+ IssuerKeyId: &e.PrimaryKey.KeyId, -+ }, -+ } -+ e.Subkeys[0].PublicKey.IsSubkey = true -+ e.Subkeys[0].PrivateKey.IsSubkey = true -+ err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) -+ if err != nil { -+ return nil, err -+ } -+ return e, nil -+} -+ -+// SerializePrivate serializes an Entity, including private key material, but -+// excluding signatures from other entities, to the given Writer. -+// Identities and subkeys are re-signed in case they changed since NewEntry. -+// If config is nil, sensible defaults will be used. -+func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { -+ err = e.PrivateKey.Serialize(w) -+ if err != nil { -+ return -+ } -+ for _, ident := range e.Identities { -+ err = ident.UserId.Serialize(w) -+ if err != nil { -+ return -+ } -+ err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) -+ if err != nil { -+ return -+ } -+ err = ident.SelfSignature.Serialize(w) -+ if err != nil { -+ return -+ } -+ } -+ for _, subkey := range e.Subkeys { -+ err = subkey.PrivateKey.Serialize(w) -+ if err != nil { -+ return -+ } -+ err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) -+ if err != nil { -+ return -+ } -+ err = subkey.Sig.Serialize(w) -+ if err != nil { -+ return -+ } -+ } -+ return nil -+} -+ -+// Serialize writes the public part of the given Entity to w, including -+// signatures from other entities. No private key material will be output. -+func (e *Entity) Serialize(w io.Writer) error { -+ err := e.PrimaryKey.Serialize(w) -+ if err != nil { -+ return err -+ } -+ for _, ident := range e.Identities { -+ err = ident.UserId.Serialize(w) -+ if err != nil { -+ return err -+ } -+ err = ident.SelfSignature.Serialize(w) -+ if err != nil { -+ return err -+ } -+ for _, sig := range ident.Signatures { -+ err = sig.Serialize(w) -+ if err != nil { -+ return err -+ } -+ } -+ } -+ for _, subkey := range e.Subkeys { -+ err = subkey.PublicKey.Serialize(w) -+ if err != nil { -+ return err -+ } -+ err = subkey.Sig.Serialize(w) -+ if err != nil { -+ return err -+ } -+ } -+ return nil -+} -+ -+// SignIdentity adds a signature to e, from signer, attesting that identity is -+// associated with e. The provided identity must already be an element of -+// e.Identities and the private key of signer must have been decrypted if -+// 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") -+ } -+ if signer.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{ -+ SigType: packet.SigTypeGenericCert, -+ PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, -+ Hash: config.Hash(), -+ CreationTime: config.Now(), -+ IssuerKeyId: &signer.PrivateKey.KeyId, -+ } -+ if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { -+ return err -+ } -+ ident.Signatures = append(ident.Signatures, sig) -+ return nil -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go -new file mode 100644 -index 000000000000..e8f0b5caa7df ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go -@@ -0,0 +1,123 @@ -+// 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 ( -+ "compress/bzip2" -+ "compress/flate" -+ "compress/zlib" -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+ "strconv" -+) -+ -+// Compressed represents a compressed OpenPGP packet. The decompressed contents -+// will contain more OpenPGP packets. See RFC 4880, section 5.6. -+type Compressed struct { -+ Body io.Reader -+} -+ -+const ( -+ NoCompression = flate.NoCompression -+ BestSpeed = flate.BestSpeed -+ BestCompression = flate.BestCompression -+ DefaultCompression = flate.DefaultCompression -+) -+ -+// CompressionConfig contains compressor configuration settings. -+type CompressionConfig struct { -+ // Level is the compression level to use. It must be set to -+ // between -1 and 9, with -1 causing the compressor to use the -+ // default compression level, 0 causing the compressor to use -+ // no compression and 1 to 9 representing increasing (better, -+ // slower) compression levels. If Level is less than -1 or -+ // more then 9, a non-nil error will be returned during -+ // encryption. See the constants above for convenient common -+ // settings for Level. -+ Level int -+} -+ -+func (c *Compressed) parse(r io.Reader) error { -+ var buf [1]byte -+ _, err := readFull(r, buf[:]) -+ if err != nil { -+ return err -+ } -+ -+ switch buf[0] { -+ case 1: -+ c.Body = flate.NewReader(r) -+ case 2: -+ c.Body, err = zlib.NewReader(r) -+ case 3: -+ c.Body = bzip2.NewReader(r) -+ default: -+ err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) -+ } -+ -+ return err -+} -+ -+// compressedWriterCloser represents the serialized compression stream -+// header and the compressor. Its Close() method ensures that both the -+// compressor and serialized stream header are closed. Its Write() -+// method writes to the compressor. -+type compressedWriteCloser struct { -+ sh io.Closer // Stream Header -+ c io.WriteCloser // Compressor -+} -+ -+func (cwc compressedWriteCloser) Write(p []byte) (int, error) { -+ return cwc.c.Write(p) -+} -+ -+func (cwc compressedWriteCloser) Close() (err error) { -+ err = cwc.c.Close() -+ if err != nil { -+ return err -+ } -+ -+ return cwc.sh.Close() -+} -+ -+// SerializeCompressed serializes a compressed data packet to w and -+// returns a WriteCloser to which the literal data packets themselves -+// can be written and which MUST be closed on completion. If cc is -+// nil, sensible defaults will be used to configure the compression -+// algorithm. -+func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { -+ compressed, err := serializeStreamHeader(w, packetTypeCompressed) -+ if err != nil { -+ return -+ } -+ -+ _, err = compressed.Write([]byte{uint8(algo)}) -+ if err != nil { -+ return -+ } -+ -+ level := DefaultCompression -+ if cc != nil { -+ level = cc.Level -+ } -+ -+ var compressor io.WriteCloser -+ switch algo { -+ case CompressionZIP: -+ compressor, err = flate.NewWriter(compressed, level) -+ case CompressionZLIB: -+ compressor, err = zlib.NewWriterLevel(compressed, level) -+ default: -+ s := strconv.Itoa(int(algo)) -+ err = errors.UnsupportedError("Unsupported compression algorithm: " + s) -+ } -+ if err != nil { -+ return -+ } -+ -+ literaldata = compressedWriteCloser{compressed, compressor} -+ -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/golang.org/x/crypto/openpgp/packet/config.go -new file mode 100644 -index 000000000000..c76eecc963ac ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/config.go -@@ -0,0 +1,91 @@ -+// Copyright 2012 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" -+ "crypto/rand" -+ "io" -+ "time" -+) -+ -+// Config collects a number of parameters along with sensible defaults. -+// A nil *Config is valid and results in all default values. -+type Config struct { -+ // Rand provides the source of entropy. -+ // If nil, the crypto/rand Reader is used. -+ Rand io.Reader -+ // DefaultHash is the default hash function to be used. -+ // If zero, SHA-256 is used. -+ DefaultHash crypto.Hash -+ // DefaultCipher is the cipher to be used. -+ // If zero, AES-128 is used. -+ DefaultCipher CipherFunction -+ // Time returns the current time as the number of seconds since the -+ // epoch. If Time is nil, time.Now is used. -+ Time func() time.Time -+ // DefaultCompressionAlgo is the compression algorithm to be -+ // applied to the plaintext before encryption. If zero, no -+ // compression is done. -+ 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 -+ // 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 -+ // 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 -+ // RSABits is the number of bits in new RSA keys made with NewEntity. -+ // If zero, then 2048 bit keys are created. -+ RSABits int -+} -+ -+func (c *Config) Random() io.Reader { -+ if c == nil || c.Rand == nil { -+ return rand.Reader -+ } -+ return c.Rand -+} -+ -+func (c *Config) Hash() crypto.Hash { -+ if c == nil || uint(c.DefaultHash) == 0 { -+ return crypto.SHA256 -+ } -+ return c.DefaultHash -+} -+ -+func (c *Config) Cipher() CipherFunction { -+ if c == nil || uint8(c.DefaultCipher) == 0 { -+ return CipherAES128 -+ } -+ return c.DefaultCipher -+} -+ -+func (c *Config) Now() time.Time { -+ if c == nil || c.Time == nil { -+ return time.Now() -+ } -+ return c.Time() -+} -+ -+func (c *Config) Compression() CompressionAlgo { -+ if c == nil { -+ return CompressionNone -+ } -+ return c.DefaultCompressionAlgo -+} -+ -+func (c *Config) PasswordHashIterations() int { -+ if c == nil || c.S2KCount == 0 { -+ return 0 -+ } -+ return c.S2KCount -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go -new file mode 100644 -index 000000000000..6d7639722c90 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go -@@ -0,0 +1,208 @@ -+// 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" -+ "crypto/rsa" -+ "encoding/binary" -+ "io" -+ "math/big" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/elgamal" -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+const encryptedKeyVersion = 3 -+ -+// EncryptedKey represents a public-key encrypted session key. See RFC 4880, -+// section 5.1. -+type EncryptedKey struct { -+ KeyId uint64 -+ Algo PublicKeyAlgorithm -+ CipherFunc CipherFunction // only valid after a successful Decrypt -+ Key []byte // only valid after a successful Decrypt -+ -+ encryptedMPI1, encryptedMPI2 parsedMPI -+} -+ -+func (e *EncryptedKey) parse(r io.Reader) (err error) { -+ var buf [10]byte -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ if buf[0] != encryptedKeyVersion { -+ return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) -+ } -+ e.KeyId = binary.BigEndian.Uint64(buf[1:9]) -+ e.Algo = PublicKeyAlgorithm(buf[9]) -+ switch e.Algo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ case PubKeyAlgoElGamal: -+ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ } -+ _, err = consumeAll(r) -+ return -+} -+ -+func checksumKeyMaterial(key []byte) uint16 { -+ var checksum uint16 -+ for _, v := range key { -+ checksum += uint16(v) -+ } -+ return checksum -+} -+ -+// Decrypt decrypts an encrypted session key with the given private key. The -+// private key must have been decrypted first. -+// If config is nil, sensible defaults will be used. -+func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { -+ var err error -+ var b []byte -+ -+ // TODO(agl): use session key decryption routines here to avoid -+ // padding oracle attacks. -+ switch priv.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ // Supports both *rsa.PrivateKey and crypto.Decrypter -+ k := priv.PrivateKey.(crypto.Decrypter) -+ b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) -+ case PubKeyAlgoElGamal: -+ c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) -+ c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) -+ b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) -+ default: -+ err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) -+ } -+ -+ if err != nil { -+ return err -+ } -+ -+ e.CipherFunc = CipherFunction(b[0]) -+ e.Key = b[1 : len(b)-2] -+ expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) -+ checksum := checksumKeyMaterial(e.Key) -+ if checksum != expectedChecksum { -+ return errors.StructuralError("EncryptedKey checksum incorrect") -+ } -+ -+ return nil -+} -+ -+// Serialize writes the encrypted key packet, e, to w. -+func (e *EncryptedKey) Serialize(w io.Writer) error { -+ var mpiLen int -+ switch e.Algo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ mpiLen = 2 + len(e.encryptedMPI1.bytes) -+ case PubKeyAlgoElGamal: -+ mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) -+ default: -+ return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) -+ } -+ -+ serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) -+ -+ w.Write([]byte{encryptedKeyVersion}) -+ binary.Write(w, binary.BigEndian, e.KeyId) -+ w.Write([]byte{byte(e.Algo)}) -+ -+ switch e.Algo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ writeMPIs(w, e.encryptedMPI1) -+ case PubKeyAlgoElGamal: -+ writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) -+ default: -+ panic("internal error") -+ } -+ -+ return nil -+} -+ -+// SerializeEncryptedKey serializes an encrypted key packet to w that contains -+// key, encrypted to pub. -+// If config is nil, sensible defaults will be used. -+func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { -+ var buf [10]byte -+ buf[0] = encryptedKeyVersion -+ binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) -+ buf[9] = byte(pub.PubKeyAlgo) -+ -+ keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) -+ keyBlock[0] = byte(cipherFunc) -+ copy(keyBlock[1:], key) -+ checksum := checksumKeyMaterial(key) -+ keyBlock[1+len(key)] = byte(checksum >> 8) -+ keyBlock[1+len(key)+1] = byte(checksum) -+ -+ switch pub.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) -+ case PubKeyAlgoElGamal: -+ return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) -+ case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: -+ return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) -+ } -+ -+ return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) -+} -+ -+func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { -+ cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) -+ if err != nil { -+ return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) -+ } -+ -+ packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) -+ -+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen) -+ if err != nil { -+ return err -+ } -+ _, err = w.Write(header[:]) -+ if err != nil { -+ return err -+ } -+ return writeMPI(w, 8*uint16(len(cipherText)), cipherText) -+} -+ -+func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { -+ c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) -+ if err != nil { -+ return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) -+ } -+ -+ packetLen := 10 /* header length */ -+ packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 -+ packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 -+ -+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen) -+ if err != nil { -+ return err -+ } -+ _, err = w.Write(header[:]) -+ if err != nil { -+ return err -+ } -+ err = writeBig(w, c1) -+ if err != nil { -+ return err -+ } -+ return writeBig(w, c2) -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/golang.org/x/crypto/openpgp/packet/literal.go -new file mode 100644 -index 000000000000..1a9ec6e51e81 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/literal.go -@@ -0,0 +1,89 @@ -+// 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 ( -+ "encoding/binary" -+ "io" -+) -+ -+// LiteralData represents an encrypted file. See RFC 4880, section 5.9. -+type LiteralData struct { -+ IsBinary bool -+ FileName string -+ Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. -+ Body io.Reader -+} -+ -+// ForEyesOnly returns whether the contents of the LiteralData have been marked -+// as especially sensitive. -+func (l *LiteralData) ForEyesOnly() bool { -+ return l.FileName == "_CONSOLE" -+} -+ -+func (l *LiteralData) parse(r io.Reader) (err error) { -+ var buf [256]byte -+ -+ _, err = readFull(r, buf[:2]) -+ if err != nil { -+ return -+ } -+ -+ l.IsBinary = buf[0] == 'b' -+ fileNameLen := int(buf[1]) -+ -+ _, err = readFull(r, buf[:fileNameLen]) -+ if err != nil { -+ return -+ } -+ -+ l.FileName = string(buf[:fileNameLen]) -+ -+ _, err = readFull(r, buf[:4]) -+ if err != nil { -+ return -+ } -+ -+ l.Time = binary.BigEndian.Uint32(buf[:4]) -+ l.Body = r -+ return -+} -+ -+// SerializeLiteral serializes a literal data packet to w and returns a -+// WriteCloser to which the data itself can be written and which MUST be closed -+// on completion. The fileName is truncated to 255 bytes. -+func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { -+ var buf [4]byte -+ buf[0] = 't' -+ if isBinary { -+ buf[0] = 'b' -+ } -+ if len(fileName) > 255 { -+ fileName = fileName[:255] -+ } -+ buf[1] = byte(len(fileName)) -+ -+ inner, err := serializeStreamHeader(w, packetTypeLiteralData) -+ if err != nil { -+ return -+ } -+ -+ _, err = inner.Write(buf[:2]) -+ if err != nil { -+ return -+ } -+ _, err = inner.Write([]byte(fileName)) -+ if err != nil { -+ return -+ } -+ binary.BigEndian.PutUint32(buf[:], time) -+ _, err = inner.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ -+ plaintext = inner -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go -new file mode 100644 -index 000000000000..ce2a33a547ce ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go -@@ -0,0 +1,143 @@ -+// Copyright 2010 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. -+ -+// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 -+ -+package packet -+ -+import ( -+ "crypto/cipher" -+) -+ -+type ocfbEncrypter struct { -+ b cipher.Block -+ fre []byte -+ outUsed int -+} -+ -+// An OCFBResyncOption determines if the "resynchronization step" of OCFB is -+// performed. -+type OCFBResyncOption bool -+ -+const ( -+ OCFBResync OCFBResyncOption = true -+ OCFBNoResync OCFBResyncOption = false -+) -+ -+// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's -+// cipher feedback mode using the given cipher.Block, and an initial amount of -+// ciphertext. randData must be random bytes and be the same length as the -+// cipher.Block's block size. Resync determines if the "resynchronization step" -+// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on -+// this point. -+func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { -+ blockSize := block.BlockSize() -+ if len(randData) != blockSize { -+ return nil, nil -+ } -+ -+ x := &ocfbEncrypter{ -+ b: block, -+ fre: make([]byte, blockSize), -+ outUsed: 0, -+ } -+ prefix := make([]byte, blockSize+2) -+ -+ block.Encrypt(x.fre, x.fre) -+ for i := 0; i < blockSize; i++ { -+ prefix[i] = randData[i] ^ x.fre[i] -+ } -+ -+ block.Encrypt(x.fre, prefix[:blockSize]) -+ prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] -+ prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] -+ -+ if resync { -+ block.Encrypt(x.fre, prefix[2:]) -+ } else { -+ x.fre[0] = prefix[blockSize] -+ x.fre[1] = prefix[blockSize+1] -+ x.outUsed = 2 -+ } -+ return x, prefix -+} -+ -+func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { -+ for i := 0; i < len(src); i++ { -+ if x.outUsed == len(x.fre) { -+ x.b.Encrypt(x.fre, x.fre) -+ x.outUsed = 0 -+ } -+ -+ x.fre[x.outUsed] ^= src[i] -+ dst[i] = x.fre[x.outUsed] -+ x.outUsed++ -+ } -+} -+ -+type ocfbDecrypter struct { -+ b cipher.Block -+ fre []byte -+ outUsed int -+} -+ -+// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's -+// cipher feedback mode using the given cipher.Block. Prefix must be the first -+// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's -+// block size. If an incorrect key is detected then nil is returned. On -+// successful exit, blockSize+2 bytes of decrypted data are written into -+// prefix. Resync determines if the "resynchronization step" from RFC 4880, -+// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. -+func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { -+ blockSize := block.BlockSize() -+ if len(prefix) != blockSize+2 { -+ return nil -+ } -+ -+ x := &ocfbDecrypter{ -+ b: block, -+ fre: make([]byte, blockSize), -+ outUsed: 0, -+ } -+ prefixCopy := make([]byte, len(prefix)) -+ copy(prefixCopy, prefix) -+ -+ block.Encrypt(x.fre, x.fre) -+ for i := 0; i < blockSize; i++ { -+ prefixCopy[i] ^= x.fre[i] -+ } -+ -+ block.Encrypt(x.fre, prefix[:blockSize]) -+ prefixCopy[blockSize] ^= x.fre[0] -+ prefixCopy[blockSize+1] ^= x.fre[1] -+ -+ if prefixCopy[blockSize-2] != prefixCopy[blockSize] || -+ prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { -+ return nil -+ } -+ -+ if resync { -+ block.Encrypt(x.fre, prefix[2:]) -+ } else { -+ x.fre[0] = prefix[blockSize] -+ x.fre[1] = prefix[blockSize+1] -+ x.outUsed = 2 -+ } -+ copy(prefix, prefixCopy) -+ return x -+} -+ -+func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { -+ for i := 0; i < len(src); i++ { -+ if x.outUsed == len(x.fre) { -+ x.b.Encrypt(x.fre, x.fre) -+ x.outUsed = 0 -+ } -+ -+ c := src[i] -+ dst[i] = x.fre[x.outUsed] ^ src[i] -+ x.fre[x.outUsed] = c -+ x.outUsed++ -+ } -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go -new file mode 100644 -index 000000000000..1713503395e3 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go -@@ -0,0 +1,73 @@ -+// 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" -+ "encoding/binary" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+ "io" -+ "strconv" -+) -+ -+// OnePassSignature represents a one-pass signature packet. See RFC 4880, -+// section 5.4. -+type OnePassSignature struct { -+ SigType SignatureType -+ Hash crypto.Hash -+ PubKeyAlgo PublicKeyAlgorithm -+ KeyId uint64 -+ IsLast bool -+} -+ -+const onePassSignatureVersion = 3 -+ -+func (ops *OnePassSignature) parse(r io.Reader) (err error) { -+ var buf [13]byte -+ -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ if buf[0] != onePassSignatureVersion { -+ err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) -+ } -+ -+ var ok bool -+ ops.Hash, ok = s2k.HashIdToHash(buf[2]) -+ if !ok { -+ return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) -+ } -+ -+ ops.SigType = SignatureType(buf[1]) -+ ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) -+ ops.KeyId = binary.BigEndian.Uint64(buf[4:12]) -+ ops.IsLast = buf[12] != 0 -+ return -+} -+ -+// Serialize marshals the given OnePassSignature to w. -+func (ops *OnePassSignature) Serialize(w io.Writer) error { -+ var buf [13]byte -+ buf[0] = onePassSignatureVersion -+ buf[1] = uint8(ops.SigType) -+ var ok bool -+ buf[2], ok = s2k.HashToHashId(ops.Hash) -+ if !ok { -+ return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) -+ } -+ buf[3] = uint8(ops.PubKeyAlgo) -+ binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) -+ if ops.IsLast { -+ buf[12] = 1 -+ } -+ -+ if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { -+ return err -+ } -+ _, err := w.Write(buf[:]) -+ return err -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go -new file mode 100644 -index 000000000000..456d807f255c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go -@@ -0,0 +1,162 @@ -+// Copyright 2012 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 ( -+ "bytes" -+ "io" -+ "io/ioutil" -+ -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is -+// useful for splitting and storing the original packet contents separately, -+// handling unsupported packet types or accessing parts of the packet not yet -+// implemented by this package. -+type OpaquePacket struct { -+ // Packet type -+ Tag uint8 -+ // Reason why the packet was parsed opaquely -+ Reason error -+ // Binary contents of the packet data -+ Contents []byte -+} -+ -+func (op *OpaquePacket) parse(r io.Reader) (err error) { -+ op.Contents, err = ioutil.ReadAll(r) -+ return -+} -+ -+// Serialize marshals the packet to a writer in its original form, including -+// the packet header. -+func (op *OpaquePacket) Serialize(w io.Writer) (err error) { -+ err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) -+ if err == nil { -+ _, err = w.Write(op.Contents) -+ } -+ return -+} -+ -+// Parse attempts to parse the opaque contents into a structure supported by -+// this package. If the packet is not known then the result will be another -+// OpaquePacket. -+func (op *OpaquePacket) Parse() (p Packet, err error) { -+ hdr := bytes.NewBuffer(nil) -+ err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) -+ if err != nil { -+ op.Reason = err -+ return op, err -+ } -+ p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) -+ if err != nil { -+ op.Reason = err -+ p = op -+ } -+ return -+} -+ -+// OpaqueReader reads OpaquePackets from an io.Reader. -+type OpaqueReader struct { -+ r io.Reader -+} -+ -+func NewOpaqueReader(r io.Reader) *OpaqueReader { -+ return &OpaqueReader{r: r} -+} -+ -+// Read the next OpaquePacket. -+func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { -+ tag, _, contents, err := readHeader(or.r) -+ if err != nil { -+ return -+ } -+ op = &OpaquePacket{Tag: uint8(tag), Reason: err} -+ err = op.parse(contents) -+ if err != nil { -+ consumeAll(contents) -+ } -+ return -+} -+ -+// OpaqueSubpacket represents an unparsed OpenPGP subpacket, -+// as found in signature and user attribute packets. -+type OpaqueSubpacket struct { -+ SubType uint8 -+ Contents []byte -+} -+ -+// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from -+// their byte representation. -+func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { -+ var ( -+ subHeaderLen int -+ subPacket *OpaqueSubpacket -+ ) -+ for len(contents) > 0 { -+ subHeaderLen, subPacket, err = nextSubpacket(contents) -+ if err != nil { -+ break -+ } -+ result = append(result, subPacket) -+ contents = contents[subHeaderLen+len(subPacket.Contents):] -+ } -+ return -+} -+ -+func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { -+ // RFC 4880, section 5.2.3.1 -+ var subLen uint32 -+ if len(contents) < 1 { -+ goto Truncated -+ } -+ subPacket = &OpaqueSubpacket{} -+ switch { -+ case contents[0] < 192: -+ subHeaderLen = 2 // 1 length byte, 1 subtype byte -+ if len(contents) < subHeaderLen { -+ goto Truncated -+ } -+ subLen = uint32(contents[0]) -+ contents = contents[1:] -+ case contents[0] < 255: -+ subHeaderLen = 3 // 2 length bytes, 1 subtype -+ if len(contents) < subHeaderLen { -+ goto Truncated -+ } -+ subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 -+ contents = contents[2:] -+ default: -+ subHeaderLen = 6 // 5 length bytes, 1 subtype -+ if len(contents) < subHeaderLen { -+ goto Truncated -+ } -+ 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.Contents = contents[1:subLen] -+ return -+Truncated: -+ err = errors.StructuralError("subpacket truncated") -+ return -+} -+ -+func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { -+ buf := make([]byte, 6) -+ n := serializeSubpacketLength(buf, len(osp.Contents)+1) -+ buf[n] = osp.SubType -+ if _, err = w.Write(buf[:n+1]); err != nil { -+ return -+ } -+ _, err = w.Write(osp.Contents) -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go -new file mode 100644 -index 000000000000..0a19794a8e49 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go -@@ -0,0 +1,590 @@ -+// 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 implements parsing and serialization of OpenPGP packets, as -+// specified in RFC 4880. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package packet // import "golang.org/x/crypto/openpgp/packet" -+ -+import ( -+ "bufio" -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/des" -+ "crypto/rsa" -+ "io" -+ "math/big" -+ "math/bits" -+ -+ "golang.org/x/crypto/cast5" -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// readFull is the same as io.ReadFull except that reading zero bytes returns -+// ErrUnexpectedEOF rather than EOF. -+func readFull(r io.Reader, buf []byte) (n int, err error) { -+ n, err = io.ReadFull(r, buf) -+ if err == io.EOF { -+ err = io.ErrUnexpectedEOF -+ } -+ return -+} -+ -+// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. -+func readLength(r io.Reader) (length int64, isPartial bool, err error) { -+ var buf [4]byte -+ _, err = readFull(r, buf[:1]) -+ if err != nil { -+ return -+ } -+ switch { -+ case buf[0] < 192: -+ length = int64(buf[0]) -+ case buf[0] < 224: -+ length = int64(buf[0]-192) << 8 -+ _, err = readFull(r, buf[0:1]) -+ if err != nil { -+ return -+ } -+ length += int64(buf[0]) + 192 -+ case buf[0] < 255: -+ length = int64(1) << (buf[0] & 0x1f) -+ isPartial = true -+ default: -+ _, err = readFull(r, buf[0:4]) -+ if err != nil { -+ return -+ } -+ length = int64(buf[0])<<24 | -+ int64(buf[1])<<16 | -+ int64(buf[2])<<8 | -+ int64(buf[3]) -+ } -+ return -+} -+ -+// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. -+// The continuation lengths are parsed and removed from the stream and EOF is -+// returned at the end of the packet. See RFC 4880, section 4.2.2.4. -+type partialLengthReader struct { -+ r io.Reader -+ remaining int64 -+ isPartial bool -+} -+ -+func (r *partialLengthReader) Read(p []byte) (n int, err error) { -+ for r.remaining == 0 { -+ if !r.isPartial { -+ return 0, io.EOF -+ } -+ r.remaining, r.isPartial, err = readLength(r.r) -+ if err != nil { -+ return 0, err -+ } -+ } -+ -+ toRead := int64(len(p)) -+ if toRead > r.remaining { -+ toRead = r.remaining -+ } -+ -+ n, err = r.r.Read(p[:int(toRead)]) -+ r.remaining -= int64(n) -+ if n < int(toRead) && err == io.EOF { -+ err = io.ErrUnexpectedEOF -+ } -+ return -+} -+ -+// partialLengthWriter writes a stream of data using OpenPGP partial lengths. -+// See RFC 4880, section 4.2.2.4. -+type partialLengthWriter struct { -+ w io.WriteCloser -+ lengthByte [1]byte -+ sentFirst bool -+ buf []byte -+} -+ -+// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long. -+const minFirstPartialWrite = 512 -+ -+func (w *partialLengthWriter) Write(p []byte) (n int, err error) { -+ off := 0 -+ if !w.sentFirst { -+ if len(w.buf) > 0 || len(p) < minFirstPartialWrite { -+ off = len(w.buf) -+ w.buf = append(w.buf, p...) -+ if len(w.buf) < minFirstPartialWrite { -+ return len(p), nil -+ } -+ p = w.buf -+ w.buf = nil -+ } -+ w.sentFirst = true -+ } -+ -+ power := uint8(30) -+ for len(p) > 0 { -+ l := 1 << power -+ if len(p) < l { -+ power = uint8(bits.Len32(uint32(len(p)))) - 1 -+ l = 1 << power -+ } -+ w.lengthByte[0] = 224 + power -+ _, err = w.w.Write(w.lengthByte[:]) -+ if err == nil { -+ var m int -+ m, err = w.w.Write(p[:l]) -+ n += m -+ } -+ if err != nil { -+ if n < off { -+ return 0, err -+ } -+ return n - off, err -+ } -+ p = p[l:] -+ } -+ return n - off, nil -+} -+ -+func (w *partialLengthWriter) Close() error { -+ if len(w.buf) > 0 { -+ // In this case we can't send a 512 byte packet. -+ // Just send what we have. -+ p := w.buf -+ w.sentFirst = true -+ w.buf = nil -+ if _, err := w.Write(p); err != nil { -+ return err -+ } -+ } -+ -+ w.lengthByte[0] = 0 -+ _, err := w.w.Write(w.lengthByte[:]) -+ if err != nil { -+ return err -+ } -+ return w.w.Close() -+} -+ -+// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the -+// underlying Reader returns EOF before the limit has been reached. -+type spanReader struct { -+ r io.Reader -+ n int64 -+} -+ -+func (l *spanReader) Read(p []byte) (n int, err error) { -+ if l.n <= 0 { -+ return 0, io.EOF -+ } -+ if int64(len(p)) > l.n { -+ p = p[0:l.n] -+ } -+ n, err = l.r.Read(p) -+ l.n -= int64(n) -+ if l.n > 0 && err == io.EOF { -+ err = io.ErrUnexpectedEOF -+ } -+ return -+} -+ -+// readHeader parses a packet header and returns an io.Reader which will return -+// the contents of the packet. See RFC 4880, section 4.2. -+func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { -+ var buf [4]byte -+ _, err = io.ReadFull(r, buf[:1]) -+ if err != nil { -+ return -+ } -+ if buf[0]&0x80 == 0 { -+ err = errors.StructuralError("tag byte does not have MSB set") -+ return -+ } -+ if buf[0]&0x40 == 0 { -+ // Old format packet -+ tag = packetType((buf[0] & 0x3f) >> 2) -+ lengthType := buf[0] & 3 -+ if lengthType == 3 { -+ length = -1 -+ contents = r -+ return -+ } -+ lengthBytes := 1 << lengthType -+ _, err = readFull(r, buf[0:lengthBytes]) -+ if err != nil { -+ return -+ } -+ for i := 0; i < lengthBytes; i++ { -+ length <<= 8 -+ length |= int64(buf[i]) -+ } -+ contents = &spanReader{r, length} -+ return -+ } -+ -+ // New format packet -+ tag = packetType(buf[0] & 0x3f) -+ length, isPartial, err := readLength(r) -+ if err != nil { -+ return -+ } -+ if isPartial { -+ contents = &partialLengthReader{ -+ remaining: length, -+ isPartial: true, -+ r: r, -+ } -+ length = -1 -+ } else { -+ contents = &spanReader{r, length} -+ } -+ return -+} -+ -+// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section -+// 4.2. -+func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { -+ var buf [6]byte -+ var n int -+ -+ buf[0] = 0x80 | 0x40 | byte(ptype) -+ if length < 192 { -+ buf[1] = byte(length) -+ n = 2 -+ } else if length < 8384 { -+ length -= 192 -+ buf[1] = 192 + byte(length>>8) -+ buf[2] = byte(length) -+ n = 3 -+ } else { -+ buf[1] = 255 -+ buf[2] = byte(length >> 24) -+ buf[3] = byte(length >> 16) -+ buf[4] = byte(length >> 8) -+ buf[5] = byte(length) -+ n = 6 -+ } -+ -+ _, err = w.Write(buf[:n]) -+ return -+} -+ -+// serializeStreamHeader writes an OpenPGP packet header to w where the -+// length of the packet is unknown. It returns a io.WriteCloser which can be -+// used to write the contents of the packet. See RFC 4880, section 4.2. -+func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { -+ var buf [1]byte -+ buf[0] = 0x80 | 0x40 | byte(ptype) -+ _, err = w.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ out = &partialLengthWriter{w: w} -+ return -+} -+ -+// Packet represents an OpenPGP packet. Users are expected to try casting -+// instances of this interface to specific packet types. -+type Packet interface { -+ parse(io.Reader) error -+} -+ -+// consumeAll reads from the given Reader until error, returning the number of -+// bytes read. -+func consumeAll(r io.Reader) (n int64, err error) { -+ var m int -+ var buf [1024]byte -+ -+ for { -+ m, err = r.Read(buf[:]) -+ n += int64(m) -+ if err == io.EOF { -+ err = nil -+ return -+ } -+ if err != nil { -+ return -+ } -+ } -+} -+ -+// packetType represents the numeric ids of the different OpenPGP packet types. See -+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 -+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 -+) -+ -+// peekVersion detects the version of a public key packet about to -+// be read. A bufio.Reader at the original position of the io.Reader -+// is returned. -+func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { -+ bufr = bufio.NewReader(r) -+ var verBuf []byte -+ if verBuf, err = bufr.Peek(1); err != nil { -+ return -+ } -+ ver = verBuf[0] -+ return -+} -+ -+// Read reads a single OpenPGP packet from the given io.Reader. If there is an -+// error parsing a packet, the whole packet is consumed from the input. -+func Read(r io.Reader) (p Packet, err error) { -+ tag, _, contents, err := readHeader(r) -+ if err != nil { -+ return -+ } -+ -+ switch tag { -+ case packetTypeEncryptedKey: -+ p = new(EncryptedKey) -+ case packetTypeSignature: -+ var version byte -+ // Detect signature version -+ if contents, version, err = peekVersion(contents); err != nil { -+ return -+ } -+ if version < 4 { -+ p = new(SignatureV3) -+ } else { -+ p = new(Signature) -+ } -+ case packetTypeSymmetricKeyEncrypted: -+ p = new(SymmetricKeyEncrypted) -+ case packetTypeOnePassSignature: -+ p = new(OnePassSignature) -+ case packetTypePrivateKey, packetTypePrivateSubkey: -+ pk := new(PrivateKey) -+ if tag == packetTypePrivateSubkey { -+ pk.IsSubkey = true -+ } -+ p = pk -+ case packetTypePublicKey, packetTypePublicSubkey: -+ var version byte -+ if contents, version, err = peekVersion(contents); err != nil { -+ return -+ } -+ isSubkey := tag == packetTypePublicSubkey -+ if version < 4 { -+ p = &PublicKeyV3{IsSubkey: isSubkey} -+ } else { -+ p = &PublicKey{IsSubkey: isSubkey} -+ } -+ case packetTypeCompressed: -+ p = new(Compressed) -+ case packetTypeSymmetricallyEncrypted: -+ p = new(SymmetricallyEncrypted) -+ case packetTypeLiteralData: -+ p = new(LiteralData) -+ case packetTypeUserId: -+ p = new(UserId) -+ case packetTypeUserAttribute: -+ p = new(UserAttribute) -+ case packetTypeSymmetricallyEncryptedMDC: -+ se := new(SymmetricallyEncrypted) -+ se.MDC = true -+ p = se -+ default: -+ err = errors.UnknownPacketTypeError(tag) -+ } -+ if p != nil { -+ err = p.parse(contents) -+ } -+ if err != nil { -+ consumeAll(contents) -+ } -+ return -+} -+ -+// SignatureType represents the different semantic meanings of an OpenPGP -+// signature. See RFC 4880, section 5.2.1. -+type SignatureType uint8 -+ -+const ( -+ SigTypeBinary SignatureType = 0 -+ SigTypeText = 1 -+ SigTypeGenericCert = 0x10 -+ SigTypePersonaCert = 0x11 -+ SigTypeCasualCert = 0x12 -+ SigTypePositiveCert = 0x13 -+ SigTypeSubkeyBinding = 0x18 -+ SigTypePrimaryKeyBinding = 0x19 -+ SigTypeDirectSignature = 0x1F -+ SigTypeKeyRevocation = 0x20 -+ SigTypeSubkeyRevocation = 0x28 -+) -+ -+// PublicKeyAlgorithm represents the different public key system specified for -+// OpenPGP. See -+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 -+type PublicKeyAlgorithm uint8 -+ -+const ( -+ PubKeyAlgoRSA PublicKeyAlgorithm = 1 -+ PubKeyAlgoElGamal PublicKeyAlgorithm = 16 -+ PubKeyAlgoDSA PublicKeyAlgorithm = 17 -+ // RFC 6637, Section 5. -+ PubKeyAlgoECDH PublicKeyAlgorithm = 18 -+ PubKeyAlgoECDSA PublicKeyAlgorithm = 19 -+ -+ // Deprecated in RFC 4880, Section 13.5. Use key flags instead. -+ PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 -+ PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 -+) -+ -+// CanEncrypt returns true if it's possible to encrypt a message to a public -+// key of the given type. -+func (pka PublicKeyAlgorithm) CanEncrypt() bool { -+ switch pka { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: -+ return true -+ } -+ return false -+} -+ -+// CanSign returns true if it's possible for a public key of the given type to -+// sign a message. -+func (pka PublicKeyAlgorithm) CanSign() bool { -+ switch pka { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: -+ return true -+ } -+ return false -+} -+ -+// CipherFunction represents the different block ciphers specified for OpenPGP. See -+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 -+type CipherFunction uint8 -+ -+const ( -+ Cipher3DES CipherFunction = 2 -+ CipherCAST5 CipherFunction = 3 -+ CipherAES128 CipherFunction = 7 -+ CipherAES192 CipherFunction = 8 -+ CipherAES256 CipherFunction = 9 -+) -+ -+// KeySize returns the key size, in bytes, of cipher. -+func (cipher CipherFunction) KeySize() int { -+ switch cipher { -+ case Cipher3DES: -+ return 24 -+ case CipherCAST5: -+ return cast5.KeySize -+ case CipherAES128: -+ return 16 -+ case CipherAES192: -+ return 24 -+ case CipherAES256: -+ return 32 -+ } -+ return 0 -+} -+ -+// blockSize returns the block size, in bytes, of cipher. -+func (cipher CipherFunction) blockSize() int { -+ switch cipher { -+ case Cipher3DES: -+ return des.BlockSize -+ case CipherCAST5: -+ return 8 -+ case CipherAES128, CipherAES192, CipherAES256: -+ return 16 -+ } -+ return 0 -+} -+ -+// new returns a fresh instance of the given cipher. -+func (cipher CipherFunction) new(key []byte) (block cipher.Block) { -+ switch cipher { -+ case Cipher3DES: -+ block, _ = des.NewTripleDESCipher(key) -+ case CipherCAST5: -+ block, _ = cast5.NewCipher(key) -+ case CipherAES128, CipherAES192, CipherAES256: -+ block, _ = aes.NewCipher(key) -+ } -+ return -+} -+ -+// readMPI reads a big integer from r. The bit length returned is the bit -+// length that was specified in r. This is preserved so that the integer can be -+// reserialized exactly. -+func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { -+ var buf [2]byte -+ _, err = readFull(r, buf[0:]) -+ if err != nil { -+ return -+ } -+ bitLength = uint16(buf[0])<<8 | uint16(buf[1]) -+ numBytes := (int(bitLength) + 7) / 8 -+ mpi = make([]byte, numBytes) -+ _, err = readFull(r, mpi) -+ // According to RFC 4880 3.2. we should check that the MPI has no leading -+ // zeroes (at least when not an encrypted MPI?), but this implementation -+ // does generate leading zeroes, so we keep accepting them. -+ return -+} -+ -+// writeMPI serializes a big integer to w. -+func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { -+ // Note that we can produce leading zeroes, in violation of RFC 4880 3.2. -+ // Implementations seem to be tolerant of them, and stripping them would -+ // make it complex to guarantee matching re-serialization. -+ _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) -+ if err == nil { -+ _, err = w.Write(mpiBytes) -+ } -+ return -+} -+ -+// writeBig serializes a *big.Int to w. -+func writeBig(w io.Writer, i *big.Int) error { -+ return writeMPI(w, uint16(i.BitLen()), i.Bytes()) -+} -+ -+// padToKeySize left-pads a MPI with zeroes to match the length of the -+// specified RSA public. -+func padToKeySize(pub *rsa.PublicKey, b []byte) []byte { -+ k := (pub.N.BitLen() + 7) / 8 -+ if len(b) >= k { -+ return b -+ } -+ bb := make([]byte, k) -+ copy(bb[len(bb)-len(b):], b) -+ return bb -+} -+ -+// CompressionAlgo Represents the different compression algorithms -+// supported by OpenPGP (except for BZIP2, which is not currently -+// supported). See Section 9.3 of RFC 4880. -+type CompressionAlgo uint8 -+ -+const ( -+ CompressionNone CompressionAlgo = 0 -+ CompressionZIP CompressionAlgo = 1 -+ CompressionZLIB CompressionAlgo = 2 -+) -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go -new file mode 100644 -index 000000000000..81abb7cef98f ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go -@@ -0,0 +1,385 @@ -+// 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 ( -+ "bytes" -+ "crypto" -+ "crypto/cipher" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/rsa" -+ "crypto/sha1" -+ "io" -+ "io/ioutil" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/elgamal" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+// PrivateKey represents a possibly encrypted private key. See RFC 4880, -+// section 5.5.3. -+type PrivateKey struct { -+ PublicKey -+ Encrypted bool // if true then the private key is unavailable until Decrypt has been called. -+ encryptedData []byte -+ cipher CipherFunction -+ s2k func(out, in []byte) -+ PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). -+ sha1Checksum bool -+ iv []byte -+} -+ -+func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that -+// implements RSA or ECDSA. -+func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *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) -+ default: -+ panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") -+ } -+ pk.PrivateKey = signer -+ return pk -+} -+ -+func (pk *PrivateKey) parse(r io.Reader) (err error) { -+ err = (&pk.PublicKey).parse(r) -+ if err != nil { -+ return -+ } -+ var buf [1]byte -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ -+ s2kType := buf[0] -+ -+ switch s2kType { -+ case 0: -+ pk.s2k = nil -+ pk.Encrypted = false -+ case 254, 255: -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ pk.cipher = CipherFunction(buf[0]) -+ pk.Encrypted = true -+ pk.s2k, err = s2k.Parse(r) -+ if err != nil { -+ return -+ } -+ if s2kType == 254 { -+ pk.sha1Checksum = true -+ } -+ default: -+ return errors.UnsupportedError("deprecated s2k function in private key") -+ } -+ -+ if pk.Encrypted { -+ blockSize := pk.cipher.blockSize() -+ if blockSize == 0 { -+ return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) -+ } -+ pk.iv = make([]byte, blockSize) -+ _, err = readFull(r, pk.iv) -+ if err != nil { -+ return -+ } -+ } -+ -+ pk.encryptedData, err = ioutil.ReadAll(r) -+ if err != nil { -+ return -+ } -+ -+ if !pk.Encrypted { -+ return pk.parsePrivateKey(pk.encryptedData) -+ } -+ -+ return -+} -+ -+func mod64kHash(d []byte) uint16 { -+ var h uint16 -+ for _, b := range d { -+ h += uint16(b) -+ } -+ return h -+} -+ -+func (pk *PrivateKey) Serialize(w io.Writer) (err error) { -+ // TODO(agl): support encrypted private keys -+ buf := bytes.NewBuffer(nil) -+ err = pk.PublicKey.serializeWithoutHeaders(buf) -+ if err != nil { -+ return -+ } -+ buf.WriteByte(0 /* no encryption */) -+ -+ privateKeyBuf := bytes.NewBuffer(nil) -+ -+ switch priv := pk.PrivateKey.(type) { -+ case *rsa.PrivateKey: -+ err = serializeRSAPrivateKey(privateKeyBuf, priv) -+ case *dsa.PrivateKey: -+ err = serializeDSAPrivateKey(privateKeyBuf, priv) -+ case *elgamal.PrivateKey: -+ err = serializeElGamalPrivateKey(privateKeyBuf, priv) -+ case *ecdsa.PrivateKey: -+ err = serializeECDSAPrivateKey(privateKeyBuf, priv) -+ default: -+ err = errors.InvalidArgumentError("unknown private key type") -+ } -+ if err != nil { -+ return -+ } -+ -+ ptype := packetTypePrivateKey -+ contents := buf.Bytes() -+ privateKeyBytes := privateKeyBuf.Bytes() -+ if pk.IsSubkey { -+ ptype = packetTypePrivateSubkey -+ } -+ err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(contents) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(privateKeyBytes) -+ if err != nil { -+ return -+ } -+ -+ checksum := mod64kHash(privateKeyBytes) -+ var checksumBytes [2]byte -+ checksumBytes[0] = byte(checksum >> 8) -+ checksumBytes[1] = byte(checksum) -+ _, err = w.Write(checksumBytes[:]) -+ -+ return -+} -+ -+func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { -+ err := writeBig(w, priv.D) -+ if err != nil { -+ return err -+ } -+ err = writeBig(w, priv.Primes[1]) -+ if err != nil { -+ return err -+ } -+ err = writeBig(w, priv.Primes[0]) -+ if err != nil { -+ return err -+ } -+ return writeBig(w, priv.Precomputed.Qinv) -+} -+ -+func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { -+ return writeBig(w, priv.X) -+} -+ -+func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { -+ return writeBig(w, priv.X) -+} -+ -+func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { -+ return writeBig(w, priv.D) -+} -+ -+// Decrypt decrypts an encrypted private key using a passphrase. -+func (pk *PrivateKey) Decrypt(passphrase []byte) error { -+ if !pk.Encrypted { -+ return nil -+ } -+ -+ key := make([]byte, pk.cipher.KeySize()) -+ pk.s2k(key, passphrase) -+ block := pk.cipher.new(key) -+ cfb := cipher.NewCFBDecrypter(block, pk.iv) -+ -+ data := make([]byte, len(pk.encryptedData)) -+ cfb.XORKeyStream(data, pk.encryptedData) -+ -+ if pk.sha1Checksum { -+ if len(data) < sha1.Size { -+ return errors.StructuralError("truncated private key data") -+ } -+ h := sha1.New() -+ h.Write(data[:len(data)-sha1.Size]) -+ sum := h.Sum(nil) -+ if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { -+ return errors.StructuralError("private key checksum failure") -+ } -+ data = data[:len(data)-sha1.Size] -+ } else { -+ if len(data) < 2 { -+ return errors.StructuralError("truncated private key data") -+ } -+ var sum uint16 -+ for i := 0; i < len(data)-2; i++ { -+ sum += uint16(data[i]) -+ } -+ if data[len(data)-2] != uint8(sum>>8) || -+ data[len(data)-1] != uint8(sum) { -+ return errors.StructuralError("private key checksum failure") -+ } -+ data = data[:len(data)-2] -+ } -+ -+ return pk.parsePrivateKey(data) -+} -+ -+func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { -+ switch pk.PublicKey.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: -+ return pk.parseRSAPrivateKey(data) -+ case PubKeyAlgoDSA: -+ return pk.parseDSAPrivateKey(data) -+ case PubKeyAlgoElGamal: -+ return pk.parseElGamalPrivateKey(data) -+ case PubKeyAlgoECDSA: -+ return pk.parseECDSAPrivateKey(data) -+ } -+ panic("impossible") -+} -+ -+func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { -+ rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) -+ rsaPriv := new(rsa.PrivateKey) -+ rsaPriv.PublicKey = *rsaPub -+ -+ buf := bytes.NewBuffer(data) -+ d, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ p, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ q, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ rsaPriv.D = new(big.Int).SetBytes(d) -+ rsaPriv.Primes = make([]*big.Int, 2) -+ rsaPriv.Primes[0] = new(big.Int).SetBytes(p) -+ rsaPriv.Primes[1] = new(big.Int).SetBytes(q) -+ if err := rsaPriv.Validate(); err != nil { -+ return err -+ } -+ rsaPriv.Precompute() -+ pk.PrivateKey = rsaPriv -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -+ -+func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { -+ dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) -+ dsaPriv := new(dsa.PrivateKey) -+ dsaPriv.PublicKey = *dsaPub -+ -+ buf := bytes.NewBuffer(data) -+ x, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ dsaPriv.X = new(big.Int).SetBytes(x) -+ pk.PrivateKey = dsaPriv -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -+ -+func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { -+ pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) -+ priv := new(elgamal.PrivateKey) -+ priv.PublicKey = *pub -+ -+ buf := bytes.NewBuffer(data) -+ x, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ priv.X = new(big.Int).SetBytes(x) -+ pk.PrivateKey = priv -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -+ -+func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { -+ ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) -+ -+ buf := bytes.NewBuffer(data) -+ d, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ pk.PrivateKey = &ecdsa.PrivateKey{ -+ PublicKey: *ecdsaPub, -+ D: new(big.Int).SetBytes(d), -+ } -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go -new file mode 100644 -index 000000000000..fcd5f5251963 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go -@@ -0,0 +1,753 @@ -+// 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 ( -+ "bytes" -+ "crypto" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "crypto/sha1" -+ _ "crypto/sha256" -+ _ "crypto/sha512" -+ "encoding/binary" -+ "fmt" -+ "hash" -+ "io" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/elgamal" -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+var ( -+ // NIST curve P-256 -+ oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} -+ // NIST curve P-384 -+ oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} -+ // NIST curve P-521 -+ oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} -+) -+ -+const maxOIDLength = 8 -+ -+// ecdsaKey stores the algorithm-specific fields for ECDSA keys. -+// as defined in RFC 6637, Section 9. -+type ecdsaKey struct { -+ // oid contains the OID byte sequence identifying the elliptic curve used -+ oid []byte -+ // p contains the elliptic curve point that represents the public key -+ p parsedMPI -+} -+ -+// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. -+func parseOID(r io.Reader) (oid []byte, err error) { -+ buf := make([]byte, maxOIDLength) -+ if _, err = readFull(r, buf[:1]); err != nil { -+ return -+ } -+ oidLen := buf[0] -+ if int(oidLen) > len(buf) { -+ err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) -+ return -+ } -+ oid = buf[:oidLen] -+ _, err = readFull(r, oid) -+ return -+} -+ -+func (f *ecdsaKey) parse(r io.Reader) (err error) { -+ if f.oid, err = parseOID(r); err != nil { -+ return err -+ } -+ f.p.bytes, f.p.bitLength, err = readMPI(r) -+ return -+} -+ -+func (f *ecdsaKey) serialize(w io.Writer) (err error) { -+ buf := make([]byte, maxOIDLength+1) -+ buf[0] = byte(len(f.oid)) -+ copy(buf[1:], f.oid) -+ if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { -+ return -+ } -+ return writeMPIs(w, f.p) -+} -+ -+func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { -+ var c elliptic.Curve -+ if bytes.Equal(f.oid, oidCurveP256) { -+ c = elliptic.P256() -+ } else if bytes.Equal(f.oid, oidCurveP384) { -+ c = elliptic.P384() -+ } else if bytes.Equal(f.oid, oidCurveP521) { -+ c = elliptic.P521() -+ } else { -+ return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) -+ } -+ x, y := elliptic.Unmarshal(c, f.p.bytes) -+ if x == nil { -+ return nil, errors.UnsupportedError("failed to parse EC point") -+ } -+ return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil -+} -+ -+func (f *ecdsaKey) byteLen() int { -+ return 1 + len(f.oid) + 2 + len(f.p.bytes) -+} -+ -+type kdfHashFunction byte -+type kdfAlgorithm byte -+ -+// ecdhKdf stores key derivation function parameters -+// used for ECDH encryption. See RFC 6637, Section 9. -+type ecdhKdf struct { -+ KdfHash kdfHashFunction -+ KdfAlgo kdfAlgorithm -+} -+ -+func (f *ecdhKdf) parse(r io.Reader) (err error) { -+ buf := make([]byte, 1) -+ if _, err = readFull(r, buf); err != nil { -+ return -+ } -+ kdfLen := int(buf[0]) -+ if kdfLen < 3 { -+ return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) -+ } -+ buf = make([]byte, kdfLen) -+ if _, err = readFull(r, buf); err != nil { -+ return -+ } -+ reserved := int(buf[0]) -+ f.KdfHash = kdfHashFunction(buf[1]) -+ f.KdfAlgo = kdfAlgorithm(buf[2]) -+ if reserved != 0x01 { -+ return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) -+ } -+ return -+} -+ -+func (f *ecdhKdf) serialize(w io.Writer) (err error) { -+ buf := make([]byte, 4) -+ // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. -+ buf[0] = byte(0x03) // Length of the following fields -+ buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now -+ buf[2] = byte(f.KdfHash) -+ buf[3] = byte(f.KdfAlgo) -+ _, err = w.Write(buf[:]) -+ return -+} -+ -+func (f *ecdhKdf) byteLen() int { -+ return 4 -+} -+ -+// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. -+type PublicKey struct { -+ CreationTime time.Time -+ PubKeyAlgo PublicKeyAlgorithm -+ PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey -+ Fingerprint [20]byte -+ KeyId uint64 -+ IsSubkey bool -+ -+ n, e, p, q, g, y parsedMPI -+ -+ // RFC 6637 fields -+ ec *ecdsaKey -+ ecdh *ecdhKdf -+} -+ -+// signingKey provides a convenient abstraction over signature verification -+// for v3 and v4 public keys. -+type signingKey interface { -+ SerializeSignaturePrefix(io.Writer) -+ serializeWithoutHeaders(io.Writer) error -+} -+ -+func fromBig(n *big.Int) parsedMPI { -+ return parsedMPI{ -+ bytes: n.Bytes(), -+ bitLength: uint16(n.BitLen()), -+ } -+} -+ -+// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. -+func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoRSA, -+ PublicKey: pub, -+ n: fromBig(pub.N), -+ e: fromBig(big.NewInt(int64(pub.E))), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. -+func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoDSA, -+ PublicKey: pub, -+ p: fromBig(pub.P), -+ q: fromBig(pub.Q), -+ g: fromBig(pub.G), -+ y: fromBig(pub.Y), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. -+func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoElGamal, -+ PublicKey: pub, -+ p: fromBig(pub.P), -+ g: fromBig(pub.G), -+ y: fromBig(pub.Y), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoECDSA, -+ PublicKey: pub, -+ ec: new(ecdsaKey), -+ } -+ -+ switch pub.Curve { -+ case elliptic.P256(): -+ pk.ec.oid = oidCurveP256 -+ case elliptic.P384(): -+ pk.ec.oid = oidCurveP384 -+ case elliptic.P521(): -+ pk.ec.oid = oidCurveP521 -+ default: -+ panic("unknown elliptic curve") -+ } -+ -+ pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) -+ -+ // The bit length is 3 (for the 0x04 specifying an uncompressed key) -+ // plus two field elements (for x and y), which are rounded up to the -+ // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6 -+ fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7 -+ pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes) -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+func (pk *PublicKey) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.5.2 -+ var buf [6]byte -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ if buf[0] != 4 { -+ return errors.UnsupportedError("public key version") -+ } -+ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) -+ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ err = pk.parseRSA(r) -+ case PubKeyAlgoDSA: -+ err = pk.parseDSA(r) -+ case PubKeyAlgoElGamal: -+ err = pk.parseElGamal(r) -+ case PubKeyAlgoECDSA: -+ pk.ec = new(ecdsaKey) -+ if err = pk.ec.parse(r); err != nil { -+ return err -+ } -+ pk.PublicKey, err = pk.ec.newECDSA() -+ case PubKeyAlgoECDH: -+ pk.ec = new(ecdsaKey) -+ if err = pk.ec.parse(r); err != nil { -+ return -+ } -+ pk.ecdh = new(ecdhKdf) -+ if err = pk.ecdh.parse(r); err != nil { -+ return -+ } -+ // The ECDH key is stored in an ecdsa.PublicKey for convenience. -+ pk.PublicKey, err = pk.ec.newECDSA() -+ default: -+ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) -+ } -+ if err != nil { -+ return -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return -+} -+ -+func (pk *PublicKey) setFingerPrintAndKeyId() { -+ // RFC 4880, section 12.2 -+ fingerPrint := sha1.New() -+ pk.SerializeSignaturePrefix(fingerPrint) -+ pk.serializeWithoutHeaders(fingerPrint) -+ copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) -+ pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) -+} -+ -+// parseRSA parses RSA public key material from the given Reader. See RFC 4880, -+// section 5.5.2. -+func (pk *PublicKey) parseRSA(r io.Reader) (err error) { -+ pk.n.bytes, pk.n.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.e.bytes, pk.e.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ -+ if len(pk.e.bytes) > 3 { -+ err = errors.UnsupportedError("large public exponent") -+ return -+ } -+ rsa := &rsa.PublicKey{ -+ N: new(big.Int).SetBytes(pk.n.bytes), -+ E: 0, -+ } -+ for i := 0; i < len(pk.e.bytes); i++ { -+ rsa.E <<= 8 -+ rsa.E |= int(pk.e.bytes[i]) -+ } -+ pk.PublicKey = rsa -+ return -+} -+ -+// parseDSA parses DSA public key material from the given Reader. See RFC 4880, -+// section 5.5.2. -+func (pk *PublicKey) parseDSA(r io.Reader) (err error) { -+ pk.p.bytes, pk.p.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.q.bytes, pk.q.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.g.bytes, pk.g.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.y.bytes, pk.y.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ -+ dsa := new(dsa.PublicKey) -+ dsa.P = new(big.Int).SetBytes(pk.p.bytes) -+ dsa.Q = new(big.Int).SetBytes(pk.q.bytes) -+ dsa.G = new(big.Int).SetBytes(pk.g.bytes) -+ dsa.Y = new(big.Int).SetBytes(pk.y.bytes) -+ pk.PublicKey = dsa -+ return -+} -+ -+// parseElGamal parses ElGamal public key material from the given Reader. See -+// RFC 4880, section 5.5.2. -+func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { -+ pk.p.bytes, pk.p.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.g.bytes, pk.g.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.y.bytes, pk.y.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ -+ elgamal := new(elgamal.PublicKey) -+ elgamal.P = new(big.Int).SetBytes(pk.p.bytes) -+ elgamal.G = new(big.Int).SetBytes(pk.g.bytes) -+ elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) -+ pk.PublicKey = elgamal -+ return -+} -+ -+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. -+// The prefix is used when calculating a signature over this public key. See -+// RFC 4880, section 5.2.4. -+func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { -+ var pLength uint16 -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ pLength += 2 + uint16(len(pk.n.bytes)) -+ pLength += 2 + uint16(len(pk.e.bytes)) -+ case PubKeyAlgoDSA: -+ pLength += 2 + uint16(len(pk.p.bytes)) -+ pLength += 2 + uint16(len(pk.q.bytes)) -+ pLength += 2 + uint16(len(pk.g.bytes)) -+ pLength += 2 + uint16(len(pk.y.bytes)) -+ case PubKeyAlgoElGamal: -+ pLength += 2 + uint16(len(pk.p.bytes)) -+ pLength += 2 + uint16(len(pk.g.bytes)) -+ pLength += 2 + uint16(len(pk.y.bytes)) -+ case PubKeyAlgoECDSA: -+ pLength += uint16(pk.ec.byteLen()) -+ case PubKeyAlgoECDH: -+ pLength += uint16(pk.ec.byteLen()) -+ pLength += uint16(pk.ecdh.byteLen()) -+ default: -+ panic("unknown public key algorithm") -+ } -+ pLength += 6 -+ h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) -+ return -+} -+ -+func (pk *PublicKey) Serialize(w io.Writer) (err error) { -+ length := 6 // 6 byte header -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ length += 2 + len(pk.n.bytes) -+ length += 2 + len(pk.e.bytes) -+ case PubKeyAlgoDSA: -+ length += 2 + len(pk.p.bytes) -+ length += 2 + len(pk.q.bytes) -+ length += 2 + len(pk.g.bytes) -+ length += 2 + len(pk.y.bytes) -+ case PubKeyAlgoElGamal: -+ length += 2 + len(pk.p.bytes) -+ length += 2 + len(pk.g.bytes) -+ length += 2 + len(pk.y.bytes) -+ case PubKeyAlgoECDSA: -+ length += pk.ec.byteLen() -+ case PubKeyAlgoECDH: -+ length += pk.ec.byteLen() -+ length += pk.ecdh.byteLen() -+ default: -+ panic("unknown public key algorithm") -+ } -+ -+ packetType := packetTypePublicKey -+ if pk.IsSubkey { -+ packetType = packetTypePublicSubkey -+ } -+ err = serializeHeader(w, packetType, length) -+ if err != nil { -+ return -+ } -+ return pk.serializeWithoutHeaders(w) -+} -+ -+// serializeWithoutHeaders marshals the PublicKey to w in the form of an -+// OpenPGP public key packet, not including the packet header. -+func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { -+ var buf [6]byte -+ buf[0] = 4 -+ t := uint32(pk.CreationTime.Unix()) -+ buf[1] = byte(t >> 24) -+ buf[2] = byte(t >> 16) -+ buf[3] = byte(t >> 8) -+ buf[4] = byte(t) -+ buf[5] = byte(pk.PubKeyAlgo) -+ -+ _, err = w.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ return writeMPIs(w, pk.n, pk.e) -+ case PubKeyAlgoDSA: -+ return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) -+ case PubKeyAlgoElGamal: -+ return writeMPIs(w, pk.p, pk.g, pk.y) -+ case PubKeyAlgoECDSA: -+ return pk.ec.serialize(w) -+ case PubKeyAlgoECDH: -+ if err = pk.ec.serialize(w); err != nil { -+ return -+ } -+ return pk.ecdh.serialize(w) -+ } -+ return errors.InvalidArgumentError("bad public-key algorithm") -+} -+ -+// CanSign returns true iff this public key can generate signatures -+func (pk *PublicKey) CanSign() bool { -+ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal -+} -+ -+// VerifySignature returns nil iff sig is a valid signature, made by this -+// public key, of the data hashed into signed. signed is mutated by this call. -+func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { -+ if !pk.CanSign() { -+ return errors.InvalidArgumentError("public key cannot generate signatures") -+ } -+ -+ signed.Write(sig.HashSuffix) -+ hashBytes := signed.Sum(nil) -+ -+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { -+ return errors.SignatureError("hash tag doesn't match") -+ } -+ -+ if pk.PubKeyAlgo != sig.PubKeyAlgo { -+ return errors.InvalidArgumentError("public key and signature use different algorithms") -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) -+ err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)) -+ if err != nil { -+ return errors.SignatureError("RSA verification failure") -+ } -+ return nil -+ case PubKeyAlgoDSA: -+ dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) -+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. -+ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 -+ if len(hashBytes) > subgroupSize { -+ hashBytes = hashBytes[:subgroupSize] -+ } -+ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { -+ return errors.SignatureError("DSA verification failure") -+ } -+ return nil -+ case PubKeyAlgoECDSA: -+ ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) -+ if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { -+ return errors.SignatureError("ECDSA verification failure") -+ } -+ return nil -+ default: -+ return errors.SignatureError("Unsupported public key algorithm used in signature") -+ } -+} -+ -+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, of the data hashed into signed. signed is mutated by this call. -+func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { -+ if !pk.CanSign() { -+ return errors.InvalidArgumentError("public key cannot generate signatures") -+ } -+ -+ suffix := make([]byte, 5) -+ suffix[0] = byte(sig.SigType) -+ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) -+ signed.Write(suffix) -+ hashBytes := signed.Sum(nil) -+ -+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { -+ return errors.SignatureError("hash tag doesn't match") -+ } -+ -+ if pk.PubKeyAlgo != sig.PubKeyAlgo { -+ return errors.InvalidArgumentError("public key and signature use different algorithms") -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) -+ if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil { -+ return errors.SignatureError("RSA verification failure") -+ } -+ return -+ case PubKeyAlgoDSA: -+ dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) -+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. -+ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 -+ if len(hashBytes) > subgroupSize { -+ hashBytes = hashBytes[:subgroupSize] -+ } -+ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { -+ return errors.SignatureError("DSA verification failure") -+ } -+ return nil -+ default: -+ panic("shouldn't happen") -+ } -+} -+ -+// keySignatureHash returns a Hash of the message that needs to be signed for -+// pk to assert a subkey relationship to signed. -+func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { -+ if !hashFunc.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hashFunc.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ signed.SerializeSignaturePrefix(h) -+ signed.serializeWithoutHeaders(h) -+ return -+} -+ -+// VerifyKeySignature returns nil iff sig is a valid signature, made by this -+// public key, of signed. -+func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { -+ h, err := keySignatureHash(pk, signed, sig.Hash) -+ if err != nil { -+ return err -+ } -+ if err = pk.VerifySignature(h, sig); err != nil { -+ return err -+ } -+ -+ if sig.FlagSign { -+ // Signing subkeys must be cross-signed. See -+ // https://www.gnupg.org/faq/subkey-cross-certify.html. -+ if sig.EmbeddedSignature == nil { -+ return errors.StructuralError("signing subkey is missing cross-signature") -+ } -+ // Verify the cross-signature. This is calculated over the same -+ // data as the main signature, so we cannot just recursively -+ // call signed.VerifyKeySignature(...) -+ if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { -+ return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) -+ } -+ if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { -+ return errors.StructuralError("error while verifying cross-signature: " + err.Error()) -+ } -+ } -+ -+ return nil -+} -+ -+func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { -+ if !hashFunc.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hashFunc.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ -+ return -+} -+ -+// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this -+// public key. -+func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { -+ h, err := keyRevocationHash(pk, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignature(h, sig) -+} -+ -+// userIdSignatureHash returns a Hash of the message that needs to be signed -+// to assert that pk is a valid key for id. -+func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { -+ if !hashFunc.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hashFunc.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ -+ var buf [5]byte -+ buf[0] = 0xb4 -+ buf[1] = byte(len(id) >> 24) -+ buf[2] = byte(len(id) >> 16) -+ buf[3] = byte(len(id) >> 8) -+ buf[4] = byte(len(id)) -+ h.Write(buf[:]) -+ h.Write([]byte(id)) -+ -+ return -+} -+ -+// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this -+// public key, that id is the identity of pub. -+func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { -+ h, err := userIdSignatureHash(id, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignature(h, sig) -+} -+ -+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, that id is the identity of pub. -+func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { -+ h, err := userIdSignatureV3Hash(id, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignatureV3(h, sig) -+} -+ -+// KeyIdString returns the public key's fingerprint in capital hex -+// (e.g. "6C7EE1B8621CC013"). -+func (pk *PublicKey) KeyIdString() string { -+ return fmt.Sprintf("%X", pk.Fingerprint[12:20]) -+} -+ -+// KeyIdShortString returns the short form of public key's fingerprint -+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). -+func (pk *PublicKey) KeyIdShortString() string { -+ return fmt.Sprintf("%X", pk.Fingerprint[16:20]) -+} -+ -+// A parsedMPI is used to store the contents of a big integer, along with the -+// bit length that was specified in the original input. This allows the MPI to -+// be reserialized exactly. -+type parsedMPI struct { -+ bytes []byte -+ bitLength uint16 -+} -+ -+// writeMPIs is a utility function for serializing several big integers to the -+// given Writer. -+func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { -+ for _, mpi := range mpis { -+ err = writeMPI(w, mpi.bitLength, mpi.bytes) -+ if err != nil { -+ return -+ } -+ } -+ return -+} -+ -+// BitLength returns the bit length for the given public key. -+func (pk *PublicKey) BitLength() (bitLength uint16, err error) { -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ bitLength = pk.n.bitLength -+ case PubKeyAlgoDSA: -+ bitLength = pk.p.bitLength -+ case PubKeyAlgoElGamal: -+ bitLength = pk.p.bitLength -+ default: -+ err = errors.InvalidArgumentError("bad public-key algorithm") -+ } -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go -new file mode 100644 -index 000000000000..5daf7b6cfd4a ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go -@@ -0,0 +1,279 @@ -+// Copyright 2013 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" -+ "crypto/md5" -+ "crypto/rsa" -+ "encoding/binary" -+ "fmt" -+ "hash" -+ "io" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and -+// should not be used for signing or encrypting. They are supported here only for -+// parsing version 3 key material and validating signatures. -+// See RFC 4880, section 5.5.2. -+type PublicKeyV3 struct { -+ CreationTime time.Time -+ DaysToExpire uint16 -+ PubKeyAlgo PublicKeyAlgorithm -+ PublicKey *rsa.PublicKey -+ Fingerprint [16]byte -+ KeyId uint64 -+ IsSubkey bool -+ -+ n, e parsedMPI -+} -+ -+// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. -+// Included here for testing purposes only. RFC 4880, section 5.5.2: -+// "an implementation MUST NOT generate a V3 key, but MAY accept it." -+func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { -+ pk := &PublicKeyV3{ -+ CreationTime: creationTime, -+ PublicKey: pub, -+ n: fromBig(pub.N), -+ e: fromBig(big.NewInt(int64(pub.E))), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+func (pk *PublicKeyV3) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.5.2 -+ var buf [8]byte -+ if _, err = readFull(r, buf[:]); err != nil { -+ return -+ } -+ if buf[0] < 2 || buf[0] > 3 { -+ return errors.UnsupportedError("public key version") -+ } -+ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) -+ pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) -+ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ err = pk.parseRSA(r) -+ default: -+ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) -+ } -+ if err != nil { -+ return -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return -+} -+ -+func (pk *PublicKeyV3) setFingerPrintAndKeyId() { -+ // RFC 4880, section 12.2 -+ fingerPrint := md5.New() -+ fingerPrint.Write(pk.n.bytes) -+ fingerPrint.Write(pk.e.bytes) -+ fingerPrint.Sum(pk.Fingerprint[:0]) -+ pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) -+} -+ -+// parseRSA parses RSA public key material from the given Reader. See RFC 4880, -+// section 5.5.2. -+func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { -+ if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { -+ return -+ } -+ if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { -+ return -+ } -+ -+ // RFC 4880 Section 12.2 requires the low 8 bytes of the -+ // modulus to form the key id. -+ if len(pk.n.bytes) < 8 { -+ return errors.StructuralError("v3 public key modulus is too short") -+ } -+ if len(pk.e.bytes) > 3 { -+ err = errors.UnsupportedError("large public exponent") -+ return -+ } -+ rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} -+ for i := 0; i < len(pk.e.bytes); i++ { -+ rsa.E <<= 8 -+ rsa.E |= int(pk.e.bytes[i]) -+ } -+ pk.PublicKey = rsa -+ return -+} -+ -+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. -+// The prefix is used when calculating a signature over this public key. See -+// RFC 4880, section 5.2.4. -+func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { -+ var pLength uint16 -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ pLength += 2 + uint16(len(pk.n.bytes)) -+ pLength += 2 + uint16(len(pk.e.bytes)) -+ default: -+ panic("unknown public key algorithm") -+ } -+ pLength += 6 -+ w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) -+ return -+} -+ -+func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { -+ length := 8 // 8 byte header -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ length += 2 + len(pk.n.bytes) -+ length += 2 + len(pk.e.bytes) -+ default: -+ panic("unknown public key algorithm") -+ } -+ -+ packetType := packetTypePublicKey -+ if pk.IsSubkey { -+ packetType = packetTypePublicSubkey -+ } -+ if err = serializeHeader(w, packetType, length); err != nil { -+ return -+ } -+ return pk.serializeWithoutHeaders(w) -+} -+ -+// serializeWithoutHeaders marshals the PublicKey to w in the form of an -+// OpenPGP public key packet, not including the packet header. -+func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { -+ var buf [8]byte -+ // Version 3 -+ buf[0] = 3 -+ // Creation time -+ t := uint32(pk.CreationTime.Unix()) -+ buf[1] = byte(t >> 24) -+ buf[2] = byte(t >> 16) -+ buf[3] = byte(t >> 8) -+ buf[4] = byte(t) -+ // Days to expire -+ buf[5] = byte(pk.DaysToExpire >> 8) -+ buf[6] = byte(pk.DaysToExpire) -+ // Public key algorithm -+ buf[7] = byte(pk.PubKeyAlgo) -+ -+ if _, err = w.Write(buf[:]); err != nil { -+ return -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ return writeMPIs(w, pk.n, pk.e) -+ } -+ return errors.InvalidArgumentError("bad public-key algorithm") -+} -+ -+// CanSign returns true iff this public key can generate signatures -+func (pk *PublicKeyV3) CanSign() bool { -+ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly -+} -+ -+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, of the data hashed into signed. signed is mutated by this call. -+func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { -+ if !pk.CanSign() { -+ return errors.InvalidArgumentError("public key cannot generate signatures") -+ } -+ -+ suffix := make([]byte, 5) -+ suffix[0] = byte(sig.SigType) -+ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) -+ signed.Write(suffix) -+ hashBytes := signed.Sum(nil) -+ -+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { -+ return errors.SignatureError("hash tag doesn't match") -+ } -+ -+ if pk.PubKeyAlgo != sig.PubKeyAlgo { -+ return errors.InvalidArgumentError("public key and signature use different algorithms") -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { -+ return errors.SignatureError("RSA verification failure") -+ } -+ return -+ default: -+ // V3 public keys only support RSA. -+ panic("shouldn't happen") -+ } -+} -+ -+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, that id is the identity of pub. -+func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { -+ h, err := userIdSignatureV3Hash(id, pk, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignatureV3(h, sig) -+} -+ -+// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, of signed. -+func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { -+ h, err := keySignatureHash(pk, signed, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignatureV3(h, sig) -+} -+ -+// userIdSignatureV3Hash returns a Hash of the message that needs to be signed -+// to assert that pk is a valid key for id. -+func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { -+ if !hfn.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hfn.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ -+ h.Write([]byte(id)) -+ -+ return -+} -+ -+// KeyIdString returns the public key's fingerprint in capital hex -+// (e.g. "6C7EE1B8621CC013"). -+func (pk *PublicKeyV3) KeyIdString() string { -+ return fmt.Sprintf("%X", pk.KeyId) -+} -+ -+// KeyIdShortString returns the short form of public key's fingerprint -+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). -+func (pk *PublicKeyV3) KeyIdShortString() string { -+ return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) -+} -+ -+// BitLength returns the bit length for the given public key. -+func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ bitLength = pk.n.bitLength -+ default: -+ err = errors.InvalidArgumentError("bad public-key algorithm") -+ } -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/golang.org/x/crypto/openpgp/packet/reader.go -new file mode 100644 -index 000000000000..34bc7c613e6e ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/reader.go -@@ -0,0 +1,76 @@ -+// 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 ( -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+) -+ -+// Reader reads packets from an io.Reader and allows packets to be 'unread' so -+// that they result from the next call to Next. -+type Reader struct { -+ q []Packet -+ readers []io.Reader -+} -+ -+// New io.Readers are pushed when a compressed or encrypted packet is processed -+// and recursively treated as a new source of packets. However, a carefully -+// crafted packet can trigger an infinite recursive sequence of packets. See -+// http://mumble.net/~campbell/misc/pgp-quine -+// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 -+// This constant limits the number of recursive packets that may be pushed. -+const maxReaders = 32 -+ -+// Next returns the most recently unread Packet, or reads another packet from -+// the top-most io.Reader. Unknown packet types are skipped. -+func (r *Reader) Next() (p Packet, err error) { -+ if len(r.q) > 0 { -+ p = r.q[len(r.q)-1] -+ r.q = r.q[:len(r.q)-1] -+ return -+ } -+ -+ for len(r.readers) > 0 { -+ p, err = Read(r.readers[len(r.readers)-1]) -+ if err == nil { -+ return -+ } -+ if err == io.EOF { -+ r.readers = r.readers[:len(r.readers)-1] -+ continue -+ } -+ if _, ok := err.(errors.UnknownPacketTypeError); !ok { -+ return nil, err -+ } -+ } -+ -+ return nil, io.EOF -+} -+ -+// Push causes the Reader to start reading from a new io.Reader. When an EOF -+// error is seen from the new io.Reader, it is popped and the Reader continues -+// to read from the next most recent io.Reader. Push returns a StructuralError -+// if pushing the reader would exceed the maximum recursion level, otherwise it -+// returns nil. -+func (r *Reader) Push(reader io.Reader) (err error) { -+ if len(r.readers) >= maxReaders { -+ return errors.StructuralError("too many layers of packets") -+ } -+ r.readers = append(r.readers, reader) -+ return nil -+} -+ -+// Unread causes the given Packet to be returned from the next call to Next. -+func (r *Reader) Unread(p Packet) { -+ r.q = append(r.q, p) -+} -+ -+func NewReader(r io.Reader) *Reader { -+ return &Reader{ -+ q: nil, -+ readers: []io.Reader{r}, -+ } -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go -new file mode 100644 -index 000000000000..b2a24a532327 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature.go -@@ -0,0 +1,731 @@ -+// 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 ( -+ "bytes" -+ "crypto" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "encoding/asn1" -+ "encoding/binary" -+ "hash" -+ "io" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+const ( -+ // See RFC 4880, section 5.2.3.21 for details. -+ KeyFlagCertify = 1 << iota -+ KeyFlagSign -+ KeyFlagEncryptCommunications -+ KeyFlagEncryptStorage -+) -+ -+// Signature represents a signature. See RFC 4880, section 5.2. -+type Signature struct { -+ SigType SignatureType -+ PubKeyAlgo PublicKeyAlgorithm -+ Hash crypto.Hash -+ -+ // HashSuffix is extra data that is hashed in after the signed data. -+ HashSuffix []byte -+ // HashTag contains the first two bytes of the hash for fast rejection -+ // of bad signed data. -+ HashTag [2]byte -+ CreationTime time.Time -+ -+ RSASignature parsedMPI -+ DSASigR, DSASigS parsedMPI -+ ECDSASigR, ECDSASigS parsedMPI -+ -+ // rawSubpackets contains the unparsed subpackets, in order. -+ rawSubpackets []outputSubpacket -+ -+ // The following are optional so are nil when not included in the -+ // signature. -+ -+ SigLifetimeSecs, KeyLifetimeSecs *uint32 -+ PreferredSymmetric, PreferredHash, PreferredCompression []uint8 -+ IssuerKeyId *uint64 -+ IsPrimaryId *bool -+ -+ // FlagsValid is set if any flags were given. See RFC 4880, section -+ // 5.2.3.21 for details. -+ FlagsValid bool -+ FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool -+ -+ // RevocationReason is set if this signature has been revoked. -+ // See RFC 4880, section 5.2.3.23 for details. -+ RevocationReason *uint8 -+ RevocationReasonText string -+ -+ // MDC is set if this signature has a feature packet that indicates -+ // support for MDC subpackets. -+ MDC bool -+ -+ // EmbeddedSignature, if non-nil, is a signature of the parent key, by -+ // this key. This prevents an attacker from claiming another's signing -+ // subkey as their own. -+ EmbeddedSignature *Signature -+ -+ outSubpackets []outputSubpacket -+} -+ -+func (sig *Signature) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.2.3 -+ var buf [5]byte -+ _, err = readFull(r, buf[:1]) -+ if err != nil { -+ return -+ } -+ if buf[0] != 4 { -+ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) -+ return -+ } -+ -+ _, err = readFull(r, buf[:5]) -+ if err != nil { -+ return -+ } -+ sig.SigType = SignatureType(buf[0]) -+ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: -+ default: -+ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) -+ return -+ } -+ -+ var ok bool -+ sig.Hash, ok = s2k.HashIdToHash(buf[2]) -+ if !ok { -+ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) -+ } -+ -+ hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) -+ l := 6 + hashedSubpacketsLength -+ sig.HashSuffix = make([]byte, l+6) -+ sig.HashSuffix[0] = 4 -+ copy(sig.HashSuffix[1:], buf[:5]) -+ hashedSubpackets := sig.HashSuffix[6:l] -+ _, err = readFull(r, hashedSubpackets) -+ if err != nil { -+ return -+ } -+ // See RFC 4880, section 5.2.4 -+ trailer := sig.HashSuffix[l:] -+ trailer[0] = 4 -+ trailer[1] = 0xff -+ trailer[2] = uint8(l >> 24) -+ trailer[3] = uint8(l >> 16) -+ trailer[4] = uint8(l >> 8) -+ trailer[5] = uint8(l) -+ -+ err = parseSignatureSubpackets(sig, hashedSubpackets, true) -+ if err != nil { -+ return -+ } -+ -+ _, err = readFull(r, buf[:2]) -+ if err != nil { -+ return -+ } -+ unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) -+ unhashedSubpackets := make([]byte, unhashedSubpacketsLength) -+ _, err = readFull(r, unhashedSubpackets) -+ if err != nil { -+ return -+ } -+ err = parseSignatureSubpackets(sig, unhashedSubpackets, false) -+ if err != nil { -+ return -+ } -+ -+ _, err = readFull(r, sig.HashTag[:2]) -+ if err != nil { -+ return -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) -+ case PubKeyAlgoDSA: -+ sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) -+ if err == nil { -+ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) -+ } -+ case PubKeyAlgoECDSA: -+ sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) -+ if err == nil { -+ sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) -+ } -+ default: -+ panic("unreachable") -+ } -+ return -+} -+ -+// parseSignatureSubpackets parses subpackets of the main signature packet. See -+// RFC 4880, section 5.2.3.1. -+func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { -+ for len(subpackets) > 0 { -+ subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) -+ if err != nil { -+ return -+ } -+ } -+ -+ if sig.CreationTime.IsZero() { -+ err = errors.StructuralError("no creation time in signature") -+ } -+ -+ return -+} -+ -+type signatureSubpacketType uint8 -+ -+const ( -+ creationTimeSubpacket signatureSubpacketType = 2 -+ signatureExpirationSubpacket signatureSubpacketType = 3 -+ keyExpirationSubpacket signatureSubpacketType = 9 -+ prefSymmetricAlgosSubpacket signatureSubpacketType = 11 -+ issuerSubpacket signatureSubpacketType = 16 -+ prefHashAlgosSubpacket signatureSubpacketType = 21 -+ prefCompressionSubpacket signatureSubpacketType = 22 -+ primaryUserIdSubpacket signatureSubpacketType = 25 -+ keyFlagsSubpacket signatureSubpacketType = 27 -+ reasonForRevocationSubpacket signatureSubpacketType = 29 -+ featuresSubpacket signatureSubpacketType = 30 -+ embeddedSignatureSubpacket signatureSubpacketType = 32 -+) -+ -+// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. -+func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { -+ // RFC 4880, section 5.2.3.1 -+ var ( -+ length uint32 -+ packetType signatureSubpacketType -+ isCritical bool -+ ) -+ switch { -+ case subpacket[0] < 192: -+ length = uint32(subpacket[0]) -+ subpacket = subpacket[1:] -+ case subpacket[0] < 255: -+ if len(subpacket) < 2 { -+ goto Truncated -+ } -+ length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 -+ subpacket = subpacket[2:] -+ default: -+ if len(subpacket) < 5 { -+ goto Truncated -+ } -+ length = uint32(subpacket[1])<<24 | -+ uint32(subpacket[2])<<16 | -+ uint32(subpacket[3])<<8 | -+ uint32(subpacket[4]) -+ subpacket = subpacket[5:] -+ } -+ if length > uint32(len(subpacket)) { -+ goto Truncated -+ } -+ rest = subpacket[length:] -+ subpacket = subpacket[:length] -+ if len(subpacket) == 0 { -+ err = errors.StructuralError("zero length signature subpacket") -+ return -+ } -+ packetType = signatureSubpacketType(subpacket[0] & 0x7f) -+ isCritical = subpacket[0]&0x80 == 0x80 -+ subpacket = subpacket[1:] -+ sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) -+ 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 -+ } -+ t := binary.BigEndian.Uint32(subpacket) -+ 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 { -+ return -+ } -+ if len(subpacket) != 4 { -+ err = errors.StructuralError("key expiration subpacket with bad length") -+ return -+ } -+ sig.KeyLifetimeSecs = new(uint32) -+ *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 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 { -+ return -+ } -+ 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 -+ } -+ sig.IsPrimaryId = new(bool) -+ if subpacket[0] > 0 { -+ *sig.IsPrimaryId = true -+ } -+ case keyFlagsSubpacket: -+ // Key flags, section 5.2.3.21 -+ if !isHashed { -+ return -+ } -+ if len(subpacket) == 0 { -+ err = errors.StructuralError("empty key flags subpacket") -+ return -+ } -+ sig.FlagsValid = true -+ if subpacket[0]&KeyFlagCertify != 0 { -+ sig.FlagCertify = true -+ } -+ if subpacket[0]&KeyFlagSign != 0 { -+ sig.FlagSign = true -+ } -+ if subpacket[0]&KeyFlagEncryptCommunications != 0 { -+ sig.FlagEncryptCommunications = true -+ } -+ if subpacket[0]&KeyFlagEncryptStorage != 0 { -+ sig.FlagEncryptStorage = true -+ } -+ 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 -+ } -+ sig.RevocationReason = new(uint8) -+ *sig.RevocationReason = subpacket[0] -+ sig.RevocationReasonText = string(subpacket[1:]) -+ case featuresSubpacket: -+ // Features subpacket, section 5.2.3.24 specifies a very general -+ // mechanism for OpenPGP implementations to signal support for new -+ // features. In practice, the subpacket is used exclusively to -+ // indicate support for MDC-protected encryption. -+ sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 -+ case embeddedSignatureSubpacket: -+ // Only usage is in signatures that cross-certify -+ // signing subkeys. section 5.2.3.26 describes the -+ // format, with its usage described in section 11.1 -+ if sig.EmbeddedSignature != nil { -+ err = errors.StructuralError("Cannot have multiple embedded signatures") -+ return -+ } -+ sig.EmbeddedSignature = new(Signature) -+ // Embedded signatures are required to be v4 signatures see -+ // section 12.1. However, we only parse v4 signatures in this -+ // file anyway. -+ if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { -+ return nil, err -+ } -+ if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { -+ return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) -+ } -+ default: -+ if isCritical { -+ err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) -+ return -+ } -+ } -+ return -+ -+Truncated: -+ err = errors.StructuralError("signature subpacket truncated") -+ return -+} -+ -+// subpacketLengthLength returns the length, in bytes, of an encoded length value. -+func subpacketLengthLength(length int) int { -+ if length < 192 { -+ return 1 -+ } -+ if length < 16320 { -+ return 2 -+ } -+ return 5 -+} -+ -+// serializeSubpacketLength marshals the given length into to. -+func serializeSubpacketLength(to []byte, length int) int { -+ // RFC 4880, Section 4.2.2. -+ if length < 192 { -+ to[0] = byte(length) -+ return 1 -+ } -+ if length < 16320 { -+ length -= 192 -+ to[0] = byte((length >> 8) + 192) -+ to[1] = byte(length) -+ return 2 -+ } -+ to[0] = 255 -+ to[1] = byte(length >> 24) -+ to[2] = byte(length >> 16) -+ to[3] = byte(length >> 8) -+ to[4] = byte(length) -+ return 5 -+} -+ -+// subpacketsLength returns the serialized length, in bytes, of the given -+// subpackets. -+func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { -+ for _, subpacket := range subpackets { -+ if subpacket.hashed == hashed { -+ length += subpacketLengthLength(len(subpacket.contents) + 1) -+ length += 1 // type byte -+ length += len(subpacket.contents) -+ } -+ } -+ return -+} -+ -+// serializeSubpackets marshals the given subpackets into to. -+func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { -+ for _, subpacket := range subpackets { -+ if subpacket.hashed == hashed { -+ n := serializeSubpacketLength(to, len(subpacket.contents)+1) -+ to[n] = byte(subpacket.subpacketType) -+ to = to[1+n:] -+ n = copy(to, subpacket.contents) -+ to = to[n:] -+ } -+ } -+ return -+} -+ -+// KeyExpired returns whether sig is a self-signature of a key that has -+// expired. -+func (sig *Signature) KeyExpired(currentTime time.Time) bool { -+ if sig.KeyLifetimeSecs == nil { -+ return false -+ } -+ expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) -+ return currentTime.After(expiry) -+} -+ -+// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. -+func (sig *Signature) buildHashSuffix() (err error) { -+ hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) -+ -+ var ok bool -+ l := 6 + hashedSubpacketsLen -+ sig.HashSuffix = make([]byte, l+6) -+ sig.HashSuffix[0] = 4 -+ sig.HashSuffix[1] = uint8(sig.SigType) -+ sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) -+ sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) -+ if !ok { -+ sig.HashSuffix = nil -+ return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) -+ } -+ sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) -+ sig.HashSuffix[5] = byte(hashedSubpacketsLen) -+ serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) -+ trailer := sig.HashSuffix[l:] -+ trailer[0] = 4 -+ trailer[1] = 0xff -+ trailer[2] = byte(l >> 24) -+ trailer[3] = byte(l >> 16) -+ trailer[4] = byte(l >> 8) -+ trailer[5] = byte(l) -+ return -+} -+ -+func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { -+ err = sig.buildHashSuffix() -+ if err != nil { -+ return -+ } -+ -+ h.Write(sig.HashSuffix) -+ digest = h.Sum(nil) -+ copy(sig.HashTag[:], digest) -+ return -+} -+ -+// Sign signs a message with a private key. The hash, h, must contain -+// the hash of the message to be signed and will be mutated by this function. -+// On success, the signature is stored in sig. Call Serialize to write it out. -+// If config is nil, sensible defaults will be used. -+func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { -+ sig.outSubpackets = sig.buildSubpackets() -+ digest, err := sig.signPrepareHash(h) -+ if err != nil { -+ return -+ } -+ -+ switch priv.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ // supports both *rsa.PrivateKey and crypto.Signer -+ sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) -+ sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) -+ case PubKeyAlgoDSA: -+ dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) -+ -+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. -+ subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 -+ if len(digest) > subgroupSize { -+ digest = digest[:subgroupSize] -+ } -+ r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) -+ if err == nil { -+ sig.DSASigR.bytes = r.Bytes() -+ sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) -+ sig.DSASigS.bytes = s.Bytes() -+ sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) -+ } -+ 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) -+ } -+ } -+ if err == nil { -+ sig.ECDSASigR = fromBig(r) -+ sig.ECDSASigS = fromBig(s) -+ } -+ default: -+ err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) -+ } -+ -+ 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. -+// If config is nil, sensible defaults will be used. -+func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { -+ h, err := userIdSignatureHash(id, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return sig.Sign(h, priv, config) -+} -+ -+// SignKey computes a signature from priv, asserting that pub is a subkey. On -+// success, the signature is stored in sig. Call Serialize to write it out. -+// If config is nil, sensible defaults will be used. -+func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { -+ h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return sig.Sign(h, priv, config) -+} -+ -+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been -+// called first. -+func (sig *Signature) Serialize(w io.Writer) (err error) { -+ if len(sig.outSubpackets) == 0 { -+ sig.outSubpackets = sig.rawSubpackets -+ } -+ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { -+ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") -+ } -+ -+ sigLength := 0 -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ sigLength = 2 + len(sig.RSASignature.bytes) -+ case PubKeyAlgoDSA: -+ sigLength = 2 + len(sig.DSASigR.bytes) -+ sigLength += 2 + len(sig.DSASigS.bytes) -+ case PubKeyAlgoECDSA: -+ sigLength = 2 + len(sig.ECDSASigR.bytes) -+ sigLength += 2 + len(sig.ECDSASigS.bytes) -+ default: -+ panic("impossible") -+ } -+ -+ unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) -+ length := len(sig.HashSuffix) - 6 /* trailer not included */ + -+ 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + -+ 2 /* hash tag */ + sigLength -+ err = serializeHeader(w, packetTypeSignature, length) -+ if err != nil { -+ return -+ } -+ -+ _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) -+ if err != nil { -+ return -+ } -+ -+ unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) -+ unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) -+ unhashedSubpackets[1] = byte(unhashedSubpacketsLen) -+ serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) -+ -+ _, err = w.Write(unhashedSubpackets) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(sig.HashTag[:]) -+ if err != nil { -+ return -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ err = writeMPIs(w, sig.RSASignature) -+ case PubKeyAlgoDSA: -+ err = writeMPIs(w, sig.DSASigR, sig.DSASigS) -+ case PubKeyAlgoECDSA: -+ err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) -+ default: -+ panic("impossible") -+ } -+ return -+} -+ -+// outputSubpacket represents a subpacket to be marshaled. -+type outputSubpacket struct { -+ hashed bool // true if this subpacket is in the hashed area. -+ subpacketType signatureSubpacketType -+ isCritical bool -+ contents []byte -+} -+ -+func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { -+ creationTime := make([]byte, 4) -+ binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) -+ subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) -+ -+ if sig.IssuerKeyId != nil { -+ keyId := make([]byte, 8) -+ binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) -+ subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) -+ } -+ -+ if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { -+ sigLifetime := make([]byte, 4) -+ binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) -+ subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) -+ } -+ -+ // Key flags may only appear in self-signatures or certification signatures. -+ -+ if sig.FlagsValid { -+ var flags byte -+ if sig.FlagCertify { -+ flags |= KeyFlagCertify -+ } -+ if sig.FlagSign { -+ flags |= KeyFlagSign -+ } -+ if sig.FlagEncryptCommunications { -+ flags |= KeyFlagEncryptCommunications -+ } -+ if sig.FlagEncryptStorage { -+ flags |= KeyFlagEncryptStorage -+ } -+ subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) -+ } -+ -+ // The following subpackets may only appear in self-signatures -+ -+ if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { -+ keyLifetime := make([]byte, 4) -+ binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) -+ subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) -+ } -+ -+ if sig.IsPrimaryId != nil && *sig.IsPrimaryId { -+ subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) -+ } -+ -+ if len(sig.PreferredSymmetric) > 0 { -+ subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) -+ } -+ -+ if len(sig.PreferredHash) > 0 { -+ subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) -+ } -+ -+ if len(sig.PreferredCompression) > 0 { -+ subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) -+ } -+ -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go -new file mode 100644 -index 000000000000..6edff889349b ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go -@@ -0,0 +1,146 @@ -+// Copyright 2013 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" -+ "encoding/binary" -+ "fmt" -+ "io" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+// SignatureV3 represents older version 3 signatures. These signatures are less secure -+// than version 4 and should not be used to create new signatures. They are included -+// here for backwards compatibility to read and validate with older key material. -+// See RFC 4880, section 5.2.2. -+type SignatureV3 struct { -+ SigType SignatureType -+ CreationTime time.Time -+ IssuerKeyId uint64 -+ PubKeyAlgo PublicKeyAlgorithm -+ Hash crypto.Hash -+ HashTag [2]byte -+ -+ RSASignature parsedMPI -+ DSASigR, DSASigS parsedMPI -+} -+ -+func (sig *SignatureV3) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.2.2 -+ var buf [8]byte -+ if _, err = readFull(r, buf[:1]); err != nil { -+ return -+ } -+ if buf[0] < 2 || buf[0] > 3 { -+ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) -+ return -+ } -+ if _, err = readFull(r, buf[:1]); err != nil { -+ return -+ } -+ if buf[0] != 5 { -+ err = errors.UnsupportedError( -+ "invalid hashed material length " + strconv.Itoa(int(buf[0]))) -+ return -+ } -+ -+ // Read hashed material: signature type + creation time -+ if _, err = readFull(r, buf[:5]); err != nil { -+ return -+ } -+ sig.SigType = SignatureType(buf[0]) -+ t := binary.BigEndian.Uint32(buf[1:5]) -+ sig.CreationTime = time.Unix(int64(t), 0) -+ -+ // Eight-octet Key ID of signer. -+ if _, err = readFull(r, buf[:8]); err != nil { -+ return -+ } -+ sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) -+ -+ // Public-key and hash algorithm -+ if _, err = readFull(r, buf[:2]); err != nil { -+ return -+ } -+ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: -+ default: -+ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) -+ return -+ } -+ var ok bool -+ if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { -+ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) -+ } -+ -+ // Two-octet field holding left 16 bits of signed hash value. -+ if _, err = readFull(r, sig.HashTag[:2]); err != nil { -+ return -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) -+ case PubKeyAlgoDSA: -+ if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { -+ return -+ } -+ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) -+ default: -+ panic("unreachable") -+ } -+ return -+} -+ -+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been -+// called first. -+func (sig *SignatureV3) Serialize(w io.Writer) (err error) { -+ buf := make([]byte, 8) -+ -+ // Write the sig type and creation time -+ buf[0] = byte(sig.SigType) -+ binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) -+ if _, err = w.Write(buf[:5]); err != nil { -+ return -+ } -+ -+ // Write the issuer long key ID -+ binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) -+ if _, err = w.Write(buf[:8]); err != nil { -+ return -+ } -+ -+ // Write public key algorithm, hash ID, and hash value -+ buf[0] = byte(sig.PubKeyAlgo) -+ hashId, ok := s2k.HashToHashId(sig.Hash) -+ if !ok { -+ return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) -+ } -+ buf[1] = hashId -+ copy(buf[2:4], sig.HashTag[:]) -+ if _, err = w.Write(buf[:4]); err != nil { -+ return -+ } -+ -+ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { -+ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ err = writeMPIs(w, sig.RSASignature) -+ case PubKeyAlgoDSA: -+ err = writeMPIs(w, sig.DSASigR, sig.DSASigS) -+ default: -+ panic("impossible") -+ } -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go -new file mode 100644 -index 000000000000..744c2d2c42dc ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go -@@ -0,0 +1,155 @@ -+// 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 ( -+ "bytes" -+ "crypto/cipher" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/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. -+const maxSessionKeySizeInBytes = 64 -+ -+// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC -+// 4880, section 5.3. -+type SymmetricKeyEncrypted struct { -+ CipherFunc CipherFunction -+ s2k func(out, in []byte) -+ encryptedKey []byte -+} -+ -+const symmetricKeyEncryptedVersion = 4 -+ -+func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { -+ // RFC 4880, section 5.3. -+ var buf [2]byte -+ if _, err := readFull(r, buf[:]); err != nil { -+ return err -+ } -+ if buf[0] != symmetricKeyEncryptedVersion { -+ return errors.UnsupportedError("SymmetricKeyEncrypted version") -+ } -+ ske.CipherFunc = CipherFunction(buf[1]) -+ -+ if ske.CipherFunc.KeySize() == 0 { -+ return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) -+ } -+ -+ var err error -+ ske.s2k, err = s2k.Parse(r) -+ if err != nil { -+ return err -+ } -+ -+ encryptedKey := make([]byte, maxSessionKeySizeInBytes) -+ // The session key may follow. We just have to try and read to find -+ // out. If it exists then we limit it to maxSessionKeySizeInBytes. -+ n, err := readFull(r, encryptedKey) -+ if err != nil && err != io.ErrUnexpectedEOF { -+ return err -+ } -+ -+ if n != 0 { -+ if n == maxSessionKeySizeInBytes { -+ return errors.UnsupportedError("oversized encrypted session key") -+ } -+ ske.encryptedKey = encryptedKey[:n] -+ } -+ -+ return nil -+} -+ -+// Decrypt attempts to decrypt an encrypted session key and returns the key and -+// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data -+// packet. -+func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { -+ key := make([]byte, ske.CipherFunc.KeySize()) -+ ske.s2k(key, passphrase) -+ -+ if len(ske.encryptedKey) == 0 { -+ return key, ske.CipherFunc, nil -+ } -+ -+ // the IV is all zeros -+ iv := make([]byte, ske.CipherFunc.blockSize()) -+ c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) -+ plaintextKey := make([]byte, len(ske.encryptedKey)) -+ c.XORKeyStream(plaintextKey, ske.encryptedKey) -+ cipherFunc := CipherFunction(plaintextKey[0]) -+ if cipherFunc.blockSize() == 0 { -+ return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) -+ } -+ plaintextKey = plaintextKey[1:] -+ if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() { -+ return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " + -+ "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")") -+ } -+ return plaintextKey, cipherFunc, nil -+} -+ -+// 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. -+// 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))) -+ } -+ -+ 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()}) -+ if err != nil { -+ return -+ } -+ s2kBytes := s2kBuf.Bytes() -+ -+ packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize -+ err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) -+ if err != nil { -+ return -+ } -+ -+ var buf [2]byte -+ buf[0] = symmetricKeyEncryptedVersion -+ buf[1] = byte(cipherFunc) -+ _, err = w.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(s2kBytes) -+ if err != nil { -+ return -+ } -+ -+ sessionKey := make([]byte, keySize) -+ _, err = io.ReadFull(config.Random(), sessionKey) -+ if err != nil { -+ return -+ } -+ iv := make([]byte, cipherFunc.blockSize()) -+ c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) -+ encryptedCipherAndKey := make([]byte, keySize+1) -+ c.XORKeyStream(encryptedCipherAndKey, buf[1:]) -+ c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) -+ _, err = w.Write(encryptedCipherAndKey) -+ if err != nil { -+ return -+ } -+ -+ key = sessionKey -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go -new file mode 100644 -index 000000000000..6126030eb903 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go -@@ -0,0 +1,290 @@ -+// 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" -+ "golang.org/x/crypto/openpgp/errors" -+ "hash" -+ "io" -+ "strconv" -+) -+ -+// 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 -+} -+ -+const symmetricallyEncryptedVersion = 1 -+ -+func (se *SymmetricallyEncrypted) parse(r io.Reader) error { -+ if se.MDC { -+ // See RFC 4880, section 5.13. -+ var buf [1]byte -+ _, err := readFull(r, buf[:]) -+ if err != nil { -+ return err -+ } -+ if buf[0] != symmetricallyEncryptedVersion { -+ return errors.UnsupportedError("unknown SymmetricallyEncrypted version") -+ } -+ } -+ se.contents = r -+ return nil -+} -+ -+// Decrypt returns a ReadCloser, from which the decrypted contents of the -+// packet can be read. An incorrect key can, with high probability, be detected -+// immediately and this will result in a KeyIncorrect error being returned. -+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.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) -+ if s == nil { -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ 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.SignatureError("error during reading") -+ } -+ -+ 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.SignatureError("error during reading") -+ } -+ } -+ -+ if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { -+ return errors.SignatureError("MDC packet not found") -+ } -+ ser.h.Write(ser.trailer[:2]) -+ -+ final := ser.h.Sum(nil) -+ if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { -+ return errors.SignatureError("hash mismatch") -+ } -+ 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 -+} -+ -+// 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") -+ } -+ writeCloser := noOpCloser{w} -+ ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) -+ if err != nil { -+ return -+ } -+ -+ _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) -+ 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 -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go -new file mode 100644 -index 000000000000..d19ffbc78671 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go -@@ -0,0 +1,91 @@ -+// Copyright 2013 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 ( -+ "bytes" -+ "image" -+ "image/jpeg" -+ "io" -+ "io/ioutil" -+) -+ -+const UserAttrImageSubpacket = 1 -+ -+// UserAttribute is capable of storing other types of data about a user -+// beyond name, email and a text comment. In practice, user attributes are typically used -+// to store a signed thumbnail photo JPEG image of the user. -+// See RFC 4880, section 5.12. -+type UserAttribute struct { -+ Contents []*OpaqueSubpacket -+} -+ -+// NewUserAttributePhoto creates a user attribute packet -+// containing the given images. -+func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { -+ uat = new(UserAttribute) -+ for _, photo := range photos { -+ var buf bytes.Buffer -+ // RFC 4880, Section 5.12.1. -+ data := []byte{ -+ 0x10, 0x00, // Little-endian image header length (16 bytes) -+ 0x01, // Image header version 1 -+ 0x01, // JPEG -+ 0, 0, 0, 0, // 12 reserved octets, must be all zero. -+ 0, 0, 0, 0, -+ 0, 0, 0, 0} -+ if _, err = buf.Write(data); err != nil { -+ return -+ } -+ if err = jpeg.Encode(&buf, photo, nil); err != nil { -+ return -+ } -+ uat.Contents = append(uat.Contents, &OpaqueSubpacket{ -+ SubType: UserAttrImageSubpacket, -+ Contents: buf.Bytes()}) -+ } -+ return -+} -+ -+// NewUserAttribute creates a new user attribute packet containing the given subpackets. -+func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { -+ return &UserAttribute{Contents: contents} -+} -+ -+func (uat *UserAttribute) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.13 -+ b, err := ioutil.ReadAll(r) -+ if err != nil { -+ return -+ } -+ uat.Contents, err = OpaqueSubpackets(b) -+ return -+} -+ -+// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including -+// header. -+func (uat *UserAttribute) Serialize(w io.Writer) (err error) { -+ var buf bytes.Buffer -+ for _, sp := range uat.Contents { -+ sp.Serialize(&buf) -+ } -+ if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { -+ return err -+ } -+ _, err = w.Write(buf.Bytes()) -+ return -+} -+ -+// ImageData returns zero or more byte slices, each containing -+// JPEG File Interchange Format (JFIF), for each photo in the -+// user attribute packet. -+func (uat *UserAttribute) ImageData() (imageData [][]byte) { -+ for _, sp := range uat.Contents { -+ if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { -+ imageData = append(imageData, sp.Contents[16:]) -+ } -+ } -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/golang.org/x/crypto/openpgp/packet/userid.go -new file mode 100644 -index 000000000000..d6bea7d4acc0 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/packet/userid.go -@@ -0,0 +1,160 @@ -+// 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 ( -+ "io" -+ "io/ioutil" -+ "strings" -+) -+ -+// UserId contains text that is intended to represent the name and email -+// address of the key holder. See RFC 4880, section 5.11. By convention, this -+// takes the form "Full Name (Comment) " -+type UserId struct { -+ Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. -+ -+ Name, Comment, Email string -+} -+ -+func hasInvalidCharacters(s string) bool { -+ for _, c := range s { -+ switch c { -+ case '(', ')', '<', '>', 0: -+ return true -+ } -+ } -+ return false -+} -+ -+// NewUserId returns a UserId or nil if any of the arguments contain invalid -+// characters. The invalid characters are '\x00', '(', ')', '<' and '>' -+func NewUserId(name, comment, email string) *UserId { -+ // RFC 4880 doesn't deal with the structure of userid strings; the -+ // name, comment and email form is just a convention. However, there's -+ // no convention about escaping the metacharacters and GPG just refuses -+ // to create user ids where, say, the name contains a '('. We mirror -+ // this behaviour. -+ -+ if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { -+ return nil -+ } -+ -+ uid := new(UserId) -+ uid.Name, uid.Comment, uid.Email = name, comment, email -+ uid.Id = name -+ if len(comment) > 0 { -+ if len(uid.Id) > 0 { -+ uid.Id += " " -+ } -+ uid.Id += "(" -+ uid.Id += comment -+ uid.Id += ")" -+ } -+ if len(email) > 0 { -+ if len(uid.Id) > 0 { -+ uid.Id += " " -+ } -+ uid.Id += "<" -+ uid.Id += email -+ uid.Id += ">" -+ } -+ return uid -+} -+ -+func (uid *UserId) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.11 -+ b, err := ioutil.ReadAll(r) -+ if err != nil { -+ return -+ } -+ uid.Id = string(b) -+ uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) -+ return -+} -+ -+// Serialize marshals uid to w in the form of an OpenPGP packet, including -+// header. -+func (uid *UserId) Serialize(w io.Writer) error { -+ err := serializeHeader(w, packetTypeUserId, len(uid.Id)) -+ if err != nil { -+ return err -+ } -+ _, err = w.Write([]byte(uid.Id)) -+ return err -+} -+ -+// parseUserId extracts the name, comment and email from a user id string that -+// is formatted as "Full Name (Comment) ". -+func parseUserId(id string) (name, comment, email string) { -+ var n, c, e struct { -+ start, end int -+ } -+ var state int -+ -+ for offset, rune := range id { -+ switch state { -+ case 0: -+ // Entering name -+ n.start = offset -+ state = 1 -+ fallthrough -+ case 1: -+ // In name -+ if rune == '(' { -+ state = 2 -+ n.end = offset -+ } else if rune == '<' { -+ state = 5 -+ n.end = offset -+ } -+ case 2: -+ // Entering comment -+ c.start = offset -+ state = 3 -+ fallthrough -+ case 3: -+ // In comment -+ if rune == ')' { -+ state = 4 -+ c.end = offset -+ } -+ case 4: -+ // Between comment and email -+ if rune == '<' { -+ state = 5 -+ } -+ case 5: -+ // Entering email -+ e.start = offset -+ state = 6 -+ fallthrough -+ case 6: -+ // In email -+ if rune == '>' { -+ state = 7 -+ e.end = offset -+ } -+ default: -+ // After email -+ } -+ } -+ switch state { -+ case 1: -+ // ended in the name -+ n.end = len(id) -+ case 3: -+ // ended in comment -+ c.end = len(id) -+ case 6: -+ // ended in email -+ e.end = len(id) -+ } -+ -+ name = strings.TrimSpace(id[n.start:n.end]) -+ comment = strings.TrimSpace(id[c.start:c.end]) -+ email = strings.TrimSpace(id[e.start:e.end]) -+ return -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go -new file mode 100644 -index 000000000000..48a893146858 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/read.go -@@ -0,0 +1,448 @@ -+// 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 openpgp implements high level operations on OpenPGP messages. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package openpgp // import "golang.org/x/crypto/openpgp" -+ -+import ( -+ "crypto" -+ _ "crypto/sha256" -+ "hash" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+// SignatureType is the armor type for a PGP signature. -+var SignatureType = "PGP SIGNATURE" -+ -+// readArmored reads an armored block with the given type. -+func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { -+ block, err := armor.Decode(r) -+ if err != nil { -+ return -+ } -+ -+ if block.Type != expectedType { -+ return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) -+ } -+ -+ return block.Body, nil -+} -+ -+// MessageDetails contains the result of parsing an OpenPGP encrypted and/or -+// signed message. -+type MessageDetails struct { -+ IsEncrypted bool // true if the message was encrypted. -+ EncryptedToKeyIds []uint64 // the list of recipient key ids. -+ IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. -+ DecryptedWith Key // the private key used to decrypt the message, if any. -+ IsSigned bool // true if the message is signed. -+ SignedByKeyId uint64 // the key id of the signer, if any. -+ SignedBy *Key // the key of the signer, if available. -+ LiteralData *packet.LiteralData // the metadata of the contents -+ UnverifiedBody io.Reader // the contents of the message. -+ -+ // If IsSigned is true and SignedBy is non-zero then the signature will -+ // be verified as UnverifiedBody is read. The signature cannot be -+ // checked until the whole of UnverifiedBody is read so UnverifiedBody -+ // must be consumed until EOF before the data can be trusted. Even if a -+ // message isn't signed (or the signer is unknown) the data may contain -+ // an authentication code that is only checked once UnverifiedBody has -+ // been consumed. Once EOF has been seen, the following fields are -+ // valid. (An authentication code failure is reported as a -+ // SignatureError error when reading from UnverifiedBody.) -+ SignatureError error // nil if the signature is good. -+ Signature *packet.Signature // the signature packet itself, if v4 (default) -+ SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature -+ -+ decrypted io.ReadCloser -+} -+ -+// A PromptFunction is used as a callback by functions that may need to decrypt -+// a private key, or prompt for a passphrase. It is called with a list of -+// acceptable, encrypted private keys and a boolean that indicates whether a -+// passphrase is usable. It should either decrypt a private key or return a -+// passphrase to try. If the decrypted private key or given passphrase isn't -+// correct, the function will be called again, forever. Any error returned will -+// be passed up. -+type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) -+ -+// A keyEnvelopePair is used to store a private key with the envelope that -+// contains a symmetric key, encrypted with that key. -+type keyEnvelopePair struct { -+ key Key -+ encryptedKey *packet.EncryptedKey -+} -+ -+// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. -+// The given KeyRing should contain both public keys (for signature -+// verification) and, possibly encrypted, private keys for decrypting. -+// If config is nil, sensible defaults will be used. -+func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { -+ var p packet.Packet -+ -+ var symKeys []*packet.SymmetricKeyEncrypted -+ var pubKeys []keyEnvelopePair -+ var se *packet.SymmetricallyEncrypted -+ -+ packets := packet.NewReader(r) -+ md = new(MessageDetails) -+ md.IsEncrypted = true -+ -+ // The message, if encrypted, starts with a number of packets -+ // containing an encrypted decryption key. The decryption key is either -+ // encrypted to a public key, or with a passphrase. This loop -+ // collects these packets. -+ParsePackets: -+ for { -+ p, err = packets.Next() -+ if err != nil { -+ return nil, err -+ } -+ switch p := p.(type) { -+ case *packet.SymmetricKeyEncrypted: -+ // This packet contains the decryption key encrypted with a passphrase. -+ md.IsSymmetricallyEncrypted = true -+ symKeys = append(symKeys, p) -+ case *packet.EncryptedKey: -+ // This packet contains the decryption key encrypted to a public key. -+ md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) -+ switch p.Algo { -+ case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: -+ break -+ default: -+ continue -+ } -+ 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}) -+ } -+ case *packet.SymmetricallyEncrypted: -+ se = p -+ break ParsePackets -+ case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: -+ // This message isn't encrypted. -+ if len(symKeys) != 0 || len(pubKeys) != 0 { -+ return nil, errors.StructuralError("key material not followed by encrypted message") -+ } -+ packets.Unread(p) -+ return readSignedMessage(packets, nil, keyring) -+ } -+ } -+ -+ var candidates []Key -+ var decrypted io.ReadCloser -+ -+ // Now that we have the list of encrypted keys we need to decrypt at -+ // least one of them or, if we cannot, we need to call the prompt -+ // function so that it can decrypt a key or give us a passphrase. -+FindKey: -+ for { -+ // See if any of the keys already have a private key available -+ candidates = candidates[:0] -+ candidateFingerprints := make(map[string]bool) -+ -+ for _, pk := range pubKeys { -+ if pk.key.PrivateKey == nil { -+ continue -+ } -+ if !pk.key.PrivateKey.Encrypted { -+ if len(pk.encryptedKey.Key) == 0 { -+ pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) -+ } -+ if len(pk.encryptedKey.Key) == 0 { -+ continue -+ } -+ decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) -+ if err != nil && err != errors.ErrKeyIncorrect { -+ return nil, err -+ } -+ if decrypted != nil { -+ md.DecryptedWith = pk.key -+ break FindKey -+ } -+ } else { -+ fpr := string(pk.key.PublicKey.Fingerprint[:]) -+ if v := candidateFingerprints[fpr]; v { -+ continue -+ } -+ candidates = append(candidates, pk.key) -+ candidateFingerprints[fpr] = true -+ } -+ } -+ -+ if len(candidates) == 0 && len(symKeys) == 0 { -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ if prompt == nil { -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ passphrase, err := prompt(candidates, len(symKeys) != 0) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Try the symmetric passphrase first -+ if len(symKeys) != 0 && passphrase != nil { -+ for _, s := range symKeys { -+ key, cipherFunc, err := s.Decrypt(passphrase) -+ if err == nil { -+ decrypted, err = se.Decrypt(cipherFunc, key) -+ if err != nil && err != errors.ErrKeyIncorrect { -+ return nil, err -+ } -+ if decrypted != nil { -+ break FindKey -+ } -+ } -+ -+ } -+ } -+ } -+ -+ md.decrypted = decrypted -+ if err := packets.Push(decrypted); err != nil { -+ return nil, err -+ } -+ return readSignedMessage(packets, md, keyring) -+} -+ -+// readSignedMessage reads a possibly signed message if mdin is non-zero then -+// that structure is updated and returned. Otherwise a fresh MessageDetails is -+// used. -+func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { -+ if mdin == nil { -+ mdin = new(MessageDetails) -+ } -+ md = mdin -+ -+ var p packet.Packet -+ var h hash.Hash -+ var wrappedHash hash.Hash -+FindLiteralData: -+ for { -+ p, err = packets.Next() -+ if err != nil { -+ return nil, err -+ } -+ switch p := p.(type) { -+ case *packet.Compressed: -+ if err := packets.Push(p.Body); err != nil { -+ return nil, err -+ } -+ case *packet.OnePassSignature: -+ if !p.IsLast { -+ return nil, errors.UnsupportedError("nested signatures") -+ } -+ -+ h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) -+ if err != nil { -+ md = nil -+ return -+ } -+ -+ md.IsSigned = true -+ md.SignedByKeyId = p.KeyId -+ keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) -+ if len(keys) > 0 { -+ md.SignedBy = &keys[0] -+ } -+ case *packet.LiteralData: -+ md.LiteralData = p -+ break FindLiteralData -+ } -+ } -+ -+ if md.SignedBy != nil { -+ md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} -+ } else if md.decrypted != nil { -+ md.UnverifiedBody = checkReader{md} -+ } else { -+ md.UnverifiedBody = md.LiteralData.Body -+ } -+ -+ return md, nil -+} -+ -+// hashForSignature returns a pair of hashes that can be used to verify a -+// signature. The signature may specify that the contents of the signed message -+// 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.Available() { -+ return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) -+ } -+ h := hashId.New() -+ -+ switch sigType { -+ case packet.SigTypeBinary: -+ return h, h, nil -+ case packet.SigTypeText: -+ return h, NewCanonicalTextHash(h), nil -+ } -+ -+ return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) -+} -+ -+// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF -+// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger -+// MDC checks. -+type checkReader struct { -+ md *MessageDetails -+} -+ -+func (cr checkReader) Read(buf []byte) (n int, err error) { -+ n, err = cr.md.LiteralData.Body.Read(buf) -+ if err == io.EOF { -+ mdcErr := cr.md.decrypted.Close() -+ if mdcErr != nil { -+ err = mdcErr -+ } -+ } -+ return -+} -+ -+// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes -+// the data as it is read. When it sees an EOF from the underlying io.Reader -+// it parses and checks a trailing Signature packet and triggers any MDC checks. -+type signatureCheckReader struct { -+ packets *packet.Reader -+ h, wrappedHash hash.Hash -+ md *MessageDetails -+} -+ -+func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { -+ n, err = scr.md.LiteralData.Body.Read(buf) -+ scr.wrappedHash.Write(buf[:n]) -+ if err == io.EOF { -+ var p packet.Packet -+ p, scr.md.SignatureError = scr.packets.Next() -+ if scr.md.SignatureError != nil { -+ return -+ } -+ -+ var ok bool -+ if scr.md.Signature, ok = p.(*packet.Signature); ok { -+ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) -+ } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { -+ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) -+ } else { -+ scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") -+ return -+ } -+ -+ // The SymmetricallyEncrypted packet, if any, might have an -+ // unsigned hash of its own. In order to check this we need to -+ // close that Reader. -+ if scr.md.decrypted != nil { -+ mdcErr := scr.md.decrypted.Close() -+ if mdcErr != nil { -+ err = mdcErr -+ } -+ } -+ } -+ return -+} -+ -+// CheckDetachedSignature takes a signed file and a detached signature and -+// returns the signer if the signature is valid. If the signer isn't known, -+// ErrUnknownIssuer is returned. -+func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { -+ var issuerKeyId uint64 -+ var hashFunc crypto.Hash -+ var sigType packet.SignatureType -+ var keys []Key -+ var p packet.Packet -+ -+ packets := packet.NewReader(signature) -+ for { -+ p, err = packets.Next() -+ if err == io.EOF { -+ return nil, errors.ErrUnknownIssuer -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ switch sig := p.(type) { -+ case *packet.Signature: -+ if sig.IssuerKeyId == nil { -+ return nil, errors.StructuralError("signature doesn't have an issuer") -+ } -+ issuerKeyId = *sig.IssuerKeyId -+ hashFunc = sig.Hash -+ sigType = sig.SigType -+ case *packet.SignatureV3: -+ issuerKeyId = sig.IssuerKeyId -+ hashFunc = sig.Hash -+ sigType = sig.SigType -+ default: -+ return nil, errors.StructuralError("non signature packet found") -+ } -+ -+ keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) -+ if len(keys) > 0 { -+ break -+ } -+ } -+ -+ if len(keys) == 0 { -+ panic("unreachable") -+ } -+ -+ h, wrappedHash, err := hashForSignature(hashFunc, sigType) -+ if err != nil { -+ return nil, err -+ } -+ -+ if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { -+ return nil, err -+ } -+ -+ for _, key := range keys { -+ switch sig := p.(type) { -+ case *packet.Signature: -+ err = key.PublicKey.VerifySignature(h, sig) -+ case *packet.SignatureV3: -+ err = key.PublicKey.VerifySignatureV3(h, sig) -+ default: -+ panic("unreachable") -+ } -+ -+ if err == nil { -+ return key.Entity, nil -+ } -+ } -+ -+ return nil, err -+} -+ -+// CheckArmoredDetachedSignature performs the same actions as -+// CheckDetachedSignature but expects the signature to be armored. -+func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { -+ body, err := readArmored(signature, SignatureType) -+ if err != nil { -+ return -+ } -+ -+ return CheckDetachedSignature(keyring, signed, body) -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go -new file mode 100644 -index 000000000000..9de04958ead0 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go -@@ -0,0 +1,279 @@ -+// 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 s2k implements the various OpenPGP string-to-key transforms as -+// specified in RFC 4800 section 3.7.1. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package s2k // import "golang.org/x/crypto/openpgp/s2k" -+ -+import ( -+ "crypto" -+ "hash" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// Config collects configuration parameters for s2k key-stretching -+// transformatioms. 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 { -+ // Hash is the default hash function to be used. If -+ // nil, SHA1 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 1024 and 65011712, inclusive. If Config -+ // is nil or S2KCount is 0, the value 65536 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 -+} -+ -+func (c *Config) hash() crypto.Hash { -+ if c == nil || uint(c.Hash) == 0 { -+ // SHA1 is the historical default in this package. -+ return crypto.SHA1 -+ } -+ -+ return c.Hash -+} -+ -+func (c *Config) encodedCount() uint8 { -+ if c == nil || c.S2KCount == 0 { -+ return 96 // The common case. Correspoding to 65536 -+ } -+ -+ i := c.S2KCount -+ switch { -+ // Behave like GPG. Should we make 65536 the lowest value used? -+ case i < 1024: -+ i = 1024 -+ case i > 65011712: -+ i = 65011712 -+ } -+ -+ return encodeCount(i) -+} -+ -+// encodeCount converts an iterative "count" in the range 1024 to -+// 65011712, inclusive, to an encoded count. The return value is the -+// octet that is actually stored in the GPG file. encodeCount panics -+// if i is not in the above range (encodedCount above takes care to -+// pass i in the correct range). See RFC 4880 Section 3.7.7.1. -+func encodeCount(i int) uint8 { -+ if i < 1024 || i > 65011712 { -+ panic("count arg i outside the required range") -+ } -+ -+ for encoded := 0; encoded < 256; encoded++ { -+ count := decodeCount(uint8(encoded)) -+ if count >= i { -+ return uint8(encoded) -+ } -+ } -+ -+ return 255 -+} -+ -+// decodeCount returns the s2k mode 3 iterative "count" corresponding to -+// the encoded octet c. -+func decodeCount(c uint8) int { -+ return (16 + int(c&15)) << (uint32(c>>4) + 6) -+} -+ -+// 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) { -+ Salted(out, h, in, nil) -+} -+ -+var zero [1]byte -+ -+// Salted writes to out the result of computing the Salted S2K function (RFC -+// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. -+func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { -+ done := 0 -+ var digest []byte -+ -+ for i := 0; done < len(out); i++ { -+ h.Reset() -+ for j := 0; j < i; j++ { -+ h.Write(zero[:]) -+ } -+ h.Write(salt) -+ h.Write(in) -+ digest = h.Sum(digest[:0]) -+ n := copy(out[done:], digest) -+ done += n -+ } -+} -+ -+// Iterated writes to out the result of computing the Iterated and Salted S2K -+// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, -+// salt and iteration count. -+func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { -+ combined := make([]byte, len(in)+len(salt)) -+ copy(combined, salt) -+ copy(combined[len(salt):], in) -+ -+ if count < len(combined) { -+ count = len(combined) -+ } -+ -+ done := 0 -+ var digest []byte -+ for i := 0; done < len(out); i++ { -+ h.Reset() -+ for j := 0; j < i; j++ { -+ h.Write(zero[:]) -+ } -+ written := 0 -+ for written < count { -+ if written+len(combined) > count { -+ todo := count - written -+ h.Write(combined[:todo]) -+ written = count -+ } else { -+ h.Write(combined) -+ written += len(combined) -+ } -+ } -+ digest = h.Sum(digest[:0]) -+ n := copy(out[done:], digest) -+ done += n -+ } -+} -+ -+// Parse reads a binary specification for a string-to-key transformation from r -+// and returns a function which performs that transform. -+func Parse(r io.Reader) (f func(out, in []byte), err error) { -+ var buf [9]byte -+ -+ _, err = io.ReadFull(r, buf[:2]) -+ if err != nil { -+ return -+ } -+ -+ hash, ok := HashIdToHash(buf[1]) -+ if !ok { -+ return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) -+ } -+ if !hash.Available() { -+ return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) -+ } -+ h := hash.New() -+ -+ switch buf[0] { -+ case 0: -+ f := func(out, in []byte) { -+ Simple(out, h, in) -+ } -+ return f, nil -+ case 1: -+ _, err = io.ReadFull(r, buf[:8]) -+ if err != nil { -+ return -+ } -+ f := func(out, in []byte) { -+ Salted(out, h, in, buf[:8]) -+ } -+ return f, nil -+ case 3: -+ _, err = io.ReadFull(r, buf[:9]) -+ if err != nil { -+ return -+ } -+ count := decodeCount(buf[8]) -+ f := func(out, in []byte) { -+ Iterated(out, h, in, buf[:8], count) -+ } -+ return f, nil -+ } -+ -+ return nil, errors.UnsupportedError("S2K function") -+} -+ -+// Serialize salts and stretches the given passphrase and writes the -+// resulting key into key. It also serializes an S2K descriptor to -+// w. The key stretching can be configured with c, which may be -+// nil. In that case, sensible defaults will be used. -+func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { -+ var buf [11]byte -+ buf[0] = 3 /* iterated and salted */ -+ buf[1], _ = HashToHashId(c.hash()) -+ salt := buf[2:10] -+ if _, err := io.ReadFull(rand, salt); err != nil { -+ return err -+ } -+ encodedCount := c.encodedCount() -+ count := decodeCount(encodedCount) -+ buf[10] = encodedCount -+ if _, err := w.Write(buf[:]); err != nil { -+ return err -+ } -+ -+ Iterated(key, c.hash().New(), passphrase, salt, count) -+ return nil -+} -+ -+// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with -+// Go's crypto.Hash type. See RFC 4880, section 9.4. -+var hashToHashIdMapping = []struct { -+ id byte -+ hash crypto.Hash -+ name string -+}{ -+ {1, crypto.MD5, "MD5"}, -+ {2, crypto.SHA1, "SHA1"}, -+ {3, crypto.RIPEMD160, "RIPEMD160"}, -+ {8, crypto.SHA256, "SHA256"}, -+ {9, crypto.SHA384, "SHA384"}, -+ {10, crypto.SHA512, "SHA512"}, -+ {11, crypto.SHA224, "SHA224"}, -+} -+ -+// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP -+// hash id. -+func HashIdToHash(id byte) (h crypto.Hash, ok bool) { -+ for _, m := range hashToHashIdMapping { -+ if m.id == id { -+ return m.hash, 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) { -+ for _, m := range hashToHashIdMapping { -+ if m.id == id { -+ return m.name, true -+ } -+ } -+ -+ return "", false -+} -+ -+// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash. -+func HashToHashId(h crypto.Hash) (id byte, ok bool) { -+ for _, m := range hashToHashIdMapping { -+ if m.hash == h { -+ return m.id, true -+ } -+ } -+ return 0, false -+} -diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go -new file mode 100644 -index 000000000000..4ee71784ebe0 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/openpgp/write.go -@@ -0,0 +1,418 @@ -+// 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 openpgp -+ -+import ( -+ "crypto" -+ "hash" -+ "io" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+// DetachSign signs message with the private key from signer (which must -+// already have been decrypted) and writes the signature to w. -+// If config is nil, sensible defaults will be used. -+func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { -+ return detachSign(w, signer, message, packet.SigTypeBinary, config) -+} -+ -+// ArmoredDetachSign signs message with the private key from signer (which -+// must already have been decrypted) and writes an armored signature to w. -+// If config is nil, sensible defaults will be used. -+func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { -+ return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) -+} -+ -+// DetachSignText signs message (after canonicalising the line endings) with -+// the private key from signer (which must already have been decrypted) and -+// writes the signature to w. -+// If config is nil, sensible defaults will be used. -+func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { -+ return detachSign(w, signer, message, packet.SigTypeText, config) -+} -+ -+// ArmoredDetachSignText signs message (after canonicalising the line endings) -+// with the private key from signer (which must already have been decrypted) -+// and writes an armored signature to w. -+// If config is nil, sensible defaults will be used. -+func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { -+ return armoredDetachSign(w, signer, message, packet.SigTypeText, config) -+} -+ -+func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { -+ out, err := armor.Encode(w, SignatureType, nil) -+ if err != nil { -+ return -+ } -+ err = detachSign(out, signer, message, sigType, config) -+ if err != nil { -+ return -+ } -+ return out.Close() -+} -+ -+func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { -+ if signer.PrivateKey == nil { -+ return errors.InvalidArgumentError("signing key doesn't have a private key") -+ } -+ if signer.PrivateKey.Encrypted { -+ return errors.InvalidArgumentError("signing key is encrypted") -+ } -+ -+ sig := new(packet.Signature) -+ sig.SigType = sigType -+ sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo -+ sig.Hash = config.Hash() -+ sig.CreationTime = config.Now() -+ sig.IssuerKeyId = &signer.PrivateKey.KeyId -+ -+ h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) -+ if err != nil { -+ return -+ } -+ io.Copy(wrappedHash, message) -+ -+ err = sig.Sign(h, signer.PrivateKey, config) -+ if err != nil { -+ return -+ } -+ -+ return sig.Serialize(w) -+} -+ -+// FileHints contains metadata about encrypted files. This metadata is, itself, -+// encrypted. -+type FileHints struct { -+ // IsBinary can be set to hint that the contents are binary data. -+ IsBinary bool -+ // FileName hints at the name of the file that should be written. It's -+ // truncated to 255 bytes if longer. It may be empty to suggest that the -+ // file should not be written to disk. It may be equal to "_CONSOLE" to -+ // suggest the data should not be written to disk. -+ FileName string -+ // ModTime contains the modification time of the file, or the zero time if not applicable. -+ ModTime time.Time -+} -+ -+// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. -+// The resulting WriteCloser must be closed after the contents of the file have -+// been written. -+// If config is nil, sensible defaults will be used. -+func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ if hints == nil { -+ hints = &FileHints{} -+ } -+ -+ key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) -+ if err != nil { -+ return -+ } -+ w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) -+ if err != nil { -+ return -+ } -+ -+ literaldata := w -+ if algo := config.Compression(); algo != packet.CompressionNone { -+ var compConfig *packet.CompressionConfig -+ if config != nil { -+ compConfig = config.CompressionConfig -+ } -+ literaldata, err = packet.SerializeCompressed(w, algo, compConfig) -+ if err != nil { -+ return -+ } -+ } -+ -+ var epochSeconds uint32 -+ if !hints.ModTime.IsZero() { -+ epochSeconds = uint32(hints.ModTime.Unix()) -+ } -+ return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) -+} -+ -+// 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 intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { -+ var j int -+ for _, v := range a { -+ for _, v2 := range b { -+ if v == v2 { -+ a[j] = v -+ j++ -+ break -+ } -+ } -+ } -+ -+ return a[:j] -+} -+ -+func hashToHashId(h crypto.Hash) uint8 { -+ v, ok := s2k.HashToHashId(h) -+ if !ok { -+ panic("tried to convert unknown hash") -+ } -+ return v -+} -+ -+// writeAndSign writes the data as a payload package and, optionally, signs -+// it. hints contains optional information, that is also encrypted, -+// that aids the recipients in processing the message. The resulting -+// WriteCloser must be closed after the contents of the file have been -+// written. If config is nil, sensible defaults will be used. -+func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ var signer *packet.PrivateKey -+ if signed != nil { -+ signKey, ok := signed.signingKey(config.Now()) -+ if !ok { -+ return nil, errors.InvalidArgumentError("no valid signing keys") -+ } -+ signer = signKey.PrivateKey -+ if signer == nil { -+ return nil, errors.InvalidArgumentError("no private key in signing key") -+ } -+ if signer.Encrypted { -+ return nil, errors.InvalidArgumentError("signing key must be decrypted") -+ } -+ } -+ -+ var hash crypto.Hash -+ for _, hashId := range candidateHashes { -+ if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { -+ hash = h -+ break -+ } -+ } -+ -+ // 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 { -+ hash = h -+ break -+ } -+ } -+ } -+ -+ if hash == 0 { -+ hashId := candidateHashes[0] -+ name, ok := s2k.HashIdToString(hashId) -+ if !ok { -+ name = "#" + strconv.Itoa(int(hashId)) -+ } -+ return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") -+ } -+ -+ if signer != nil { -+ ops := &packet.OnePassSignature{ -+ SigType: packet.SigTypeBinary, -+ Hash: hash, -+ PubKeyAlgo: signer.PubKeyAlgo, -+ KeyId: signer.KeyId, -+ IsLast: true, -+ } -+ if err := ops.Serialize(payload); err != nil { -+ return nil, err -+ } -+ } -+ -+ if hints == nil { -+ hints = &FileHints{} -+ } -+ -+ w := payload -+ if signer != nil { -+ // If we need to write a signature packet after the literal -+ // data then we need to stop literalData from closing -+ // encryptedData. -+ w = noOpCloser{w} -+ -+ } -+ var epochSeconds uint32 -+ if !hints.ModTime.IsZero() { -+ epochSeconds = uint32(hints.ModTime.Unix()) -+ } -+ literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) -+ if err != nil { -+ return nil, err -+ } -+ -+ if signer != nil { -+ return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil -+ } -+ return literalData, nil -+} -+ -+// Encrypt encrypts a message to a number of recipients and, optionally, signs -+// it. hints contains optional information, that is also encrypted, that aids -+// the recipients in processing the message. The resulting WriteCloser must -+// be closed after the contents of the file have been written. -+// If config is nil, sensible defaults will be used. -+func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ if len(to) == 0 { -+ return nil, errors.InvalidArgumentError("no encryption recipient provided") -+ } -+ -+ // These are the possible ciphers that we'll use for the message. -+ candidateCiphers := []uint8{ -+ uint8(packet.CipherAES128), -+ uint8(packet.CipherAES256), -+ uint8(packet.CipherCAST5), -+ } -+ // 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), -+ } -+ // 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[len(candidateCiphers)-1:] -+ defaultHashes := candidateHashes[len(candidateHashes)-1:] -+ -+ encryptKeys := make([]Key, len(to)) -+ for i := range to { -+ var ok bool -+ encryptKeys[i], ok = to[i].encryptionKey(config.Now()) -+ if !ok { -+ return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") -+ } -+ -+ sig := to[i].primaryIdentity().SelfSignature -+ -+ preferredSymmetric := sig.PreferredSymmetric -+ if len(preferredSymmetric) == 0 { -+ preferredSymmetric = defaultCiphers -+ } -+ preferredHashes := sig.PreferredHash -+ if len(preferredHashes) == 0 { -+ preferredHashes = defaultHashes -+ } -+ candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) -+ candidateHashes = intersectPreferences(candidateHashes, preferredHashes) -+ } -+ -+ if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { -+ return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") -+ } -+ -+ cipher := packet.CipherFunction(candidateCiphers[0]) -+ // If the cipher specified by config is a candidate, we'll use that. -+ configuredCipher := config.Cipher() -+ for _, c := range candidateCiphers { -+ cipherFunc := packet.CipherFunction(c) -+ if cipherFunc == configuredCipher { -+ cipher = cipherFunc -+ break -+ } -+ } -+ -+ symKey := make([]byte, cipher.KeySize()) -+ if _, err := io.ReadFull(config.Random(), symKey); err != nil { -+ return nil, err -+ } -+ -+ for _, key := range encryptKeys { -+ if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { -+ return nil, err -+ } -+ } -+ -+ payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) -+ if err != nil { -+ return -+ } -+ -+ return writeAndSign(payload, candidateHashes, signed, hints, config) -+} -+ -+// Sign signs a message. The resulting WriteCloser must be closed after the -+// contents of the file have been written. hints contains optional information -+// that aids the recipients in processing the message. -+// If config is nil, sensible defaults will be used. -+func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) { -+ if signed == nil { -+ return nil, errors.InvalidArgumentError("no signer provided") -+ } -+ -+ // 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), -+ } -+ defaultHashes := candidateHashes[len(candidateHashes)-1:] -+ preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash -+ if len(preferredHashes) == 0 { -+ preferredHashes = defaultHashes -+ } -+ candidateHashes = intersectPreferences(candidateHashes, preferredHashes) -+ return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config) -+} -+ -+// signatureWriter hashes the contents of a message while passing it along to -+// literalData. When closed, it closes literalData, writes a signature packet -+// to encryptedData and then also closes encryptedData. -+type signatureWriter struct { -+ encryptedData io.WriteCloser -+ literalData io.WriteCloser -+ hashType crypto.Hash -+ h hash.Hash -+ signer *packet.PrivateKey -+ config *packet.Config -+} -+ -+func (s signatureWriter) Write(data []byte) (int, error) { -+ s.h.Write(data) -+ return s.literalData.Write(data) -+} -+ -+func (s signatureWriter) Close() error { -+ sig := &packet.Signature{ -+ SigType: packet.SigTypeBinary, -+ PubKeyAlgo: s.signer.PubKeyAlgo, -+ Hash: s.hashType, -+ CreationTime: s.config.Now(), -+ IssuerKeyId: &s.signer.KeyId, -+ } -+ -+ if err := sig.Sign(s.h, s.signer, s.config); err != nil { -+ return err -+ } -+ if err := s.literalData.Close(); err != nil { -+ return err -+ } -+ if err := sig.Serialize(s.encryptedData); err != nil { -+ return err -+ } -+ return s.encryptedData.Close() -+} -+ -+// 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. -+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 -+} -diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_compat.go b/vendor/golang.org/x/crypto/poly1305/poly1305_compat.go -new file mode 100644 -index 000000000000..dd975a32c988 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/poly1305/poly1305_compat.go -@@ -0,0 +1,91 @@ -+// Copyright 2012 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 poly1305 implements Poly1305 one-time message authentication code as -+// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. -+// -+// Poly1305 is a fast, one-time authentication function. It is infeasible for an -+// attacker to generate an authenticator for a message without the key. However, a -+// key must only be used for a single message. Authenticating two different -+// messages with the same key allows an attacker to forge authenticators for other -+// messages with the same key. -+// -+// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was -+// used with a fixed key in order to generate one-time keys from an nonce. -+// However, in this package AES isn't used and the one-time key is specified -+// directly. -+// -+// Deprecated: Poly1305 as implemented by this package is a cryptographic -+// building block that is not safe for general purpose use. -+// For encryption, use the full ChaCha20-Poly1305 construction implemented by -+// golang.org/x/crypto/chacha20poly1305. For authentication, use a general -+// purpose MAC such as HMAC implemented by crypto/hmac. -+package poly1305 // import "golang.org/x/crypto/poly1305" -+ -+import "golang.org/x/crypto/internal/poly1305" -+ -+// TagSize is the size, in bytes, of a poly1305 authenticator. -+// -+// For use with golang.org/x/crypto/chacha20poly1305, chacha20poly1305.Overhead -+// can be used instead. -+const TagSize = 16 -+ -+// Sum generates an authenticator for msg using a one-time key and puts the -+// 16-byte result into out. Authenticating two different messages with the same -+// key allows an attacker to forge messages at will. -+func Sum(out *[16]byte, m []byte, key *[32]byte) { -+ poly1305.Sum(out, m, key) -+} -+ -+// Verify returns true if mac is a valid authenticator for m with the given key. -+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { -+ return poly1305.Verify(mac, m, key) -+} -+ -+// New returns a new MAC computing an authentication -+// tag of all data written to it with the given key. -+// This allows writing the message progressively instead -+// of passing it as a single slice. Common users should use -+// the Sum function instead. -+// -+// The key must be unique for each message, as authenticating -+// two different messages with the same key allows an attacker -+// to forge messages at will. -+func New(key *[32]byte) *MAC { -+ return &MAC{mac: poly1305.New(key)} -+} -+ -+// MAC is an io.Writer computing an authentication tag -+// of the data written to it. -+// -+// MAC cannot be used like common hash.Hash implementations, -+// because using a poly1305 key twice breaks its security. -+// Therefore writing data to a running MAC after calling -+// Sum or Verify causes it to panic. -+type MAC struct { -+ mac *poly1305.MAC -+} -+ -+// Size returns the number of bytes Sum will return. -+func (h *MAC) Size() int { return TagSize } -+ -+// Write adds more data to the running message authentication code. -+// It never returns an error. -+// -+// It must not be called after the first call of Sum or Verify. -+func (h *MAC) Write(p []byte) (n int, err error) { -+ return h.mac.Write(p) -+} -+ -+// Sum computes the authenticator of all data written to the -+// message authentication code. -+func (h *MAC) Sum(b []byte) []byte { -+ return h.mac.Sum(b) -+} -+ -+// Verify returns whether the authenticator of all data written to -+// the message authentication code matches the expected value. -+func (h *MAC) Verify(expected []byte) bool { -+ return h.mac.Verify(expected) -+} -diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go -new file mode 100644 -index 000000000000..cf3eeb158a9c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go -@@ -0,0 +1,124 @@ -+// Copyright 2010 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 ripemd160 implements the RIPEMD-160 hash algorithm. -+// -+// Deprecated: RIPEMD-160 is a legacy hash and should not be used for new -+// applications. Also, this package does not and will not provide an optimized -+// implementation. Instead, use a modern hash like SHA-256 (from crypto/sha256). -+package ripemd160 // import "golang.org/x/crypto/ripemd160" -+ -+// RIPEMD-160 is designed by Hans Dobbertin, Antoon Bosselaers, and Bart -+// Preneel with specifications available at: -+// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ crypto.RegisterHash(crypto.RIPEMD160, New) -+} -+ -+// The size of the checksum in bytes. -+const Size = 20 -+ -+// The block size of the hash algorithm in bytes. -+const BlockSize = 64 -+ -+const ( -+ _s0 = 0x67452301 -+ _s1 = 0xefcdab89 -+ _s2 = 0x98badcfe -+ _s3 = 0x10325476 -+ _s4 = 0xc3d2e1f0 -+) -+ -+// digest represents the partial evaluation of a checksum. -+type digest struct { -+ s [5]uint32 // running context -+ x [BlockSize]byte // temporary buffer -+ nx int // index into x -+ tc uint64 // total count of bytes processed -+} -+ -+func (d *digest) Reset() { -+ d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 -+ d.nx = 0 -+ d.tc = 0 -+} -+ -+// New returns a new hash.Hash computing the checksum. -+func New() hash.Hash { -+ result := new(digest) -+ result.Reset() -+ return result -+} -+ -+func (d *digest) Size() int { return Size } -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Write(p []byte) (nn int, err error) { -+ nn = len(p) -+ d.tc += uint64(nn) -+ if d.nx > 0 { -+ n := len(p) -+ if n > BlockSize-d.nx { -+ n = BlockSize - d.nx -+ } -+ for i := 0; i < n; i++ { -+ d.x[d.nx+i] = p[i] -+ } -+ d.nx += n -+ if d.nx == BlockSize { -+ _Block(d, d.x[0:]) -+ d.nx = 0 -+ } -+ p = p[n:] -+ } -+ n := _Block(d, p) -+ p = p[n:] -+ if len(p) > 0 { -+ d.nx = copy(d.x[:], p) -+ } -+ return -+} -+ -+func (d0 *digest) Sum(in []byte) []byte { -+ // Make a copy of d0 so that caller can keep writing and summing. -+ d := *d0 -+ -+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. -+ tc := d.tc -+ var tmp [64]byte -+ tmp[0] = 0x80 -+ if tc%64 < 56 { -+ d.Write(tmp[0 : 56-tc%64]) -+ } else { -+ d.Write(tmp[0 : 64+56-tc%64]) -+ } -+ -+ // Length in bits. -+ tc <<= 3 -+ for i := uint(0); i < 8; i++ { -+ tmp[i] = byte(tc >> (8 * i)) -+ } -+ d.Write(tmp[0:8]) -+ -+ if d.nx != 0 { -+ panic("d.nx != 0") -+ } -+ -+ var digest [Size]byte -+ for i, s := range d.s { -+ digest[i*4] = byte(s) -+ digest[i*4+1] = byte(s >> 8) -+ digest[i*4+2] = byte(s >> 16) -+ digest[i*4+3] = byte(s >> 24) -+ } -+ -+ return append(in, digest[:]...) -+} -diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go -new file mode 100644 -index 000000000000..e0edc02f0f30 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go -@@ -0,0 +1,165 @@ -+// Copyright 2010 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. -+ -+// RIPEMD-160 block step. -+// In its own file so that a faster assembly or C version -+// can be substituted easily. -+ -+package ripemd160 -+ -+import ( -+ "math/bits" -+) -+ -+// work buffer indices and roll amounts for one line -+var _n = [80]uint{ -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -+ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, -+ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, -+ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, -+ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, -+} -+ -+var _r = [80]uint{ -+ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, -+ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, -+ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, -+ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, -+ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, -+} -+ -+// same for the other parallel one -+var n_ = [80]uint{ -+ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, -+ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, -+ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, -+ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, -+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, -+} -+ -+var r_ = [80]uint{ -+ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, -+ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, -+ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, -+ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, -+ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, -+} -+ -+func _Block(md *digest, p []byte) int { -+ n := 0 -+ var x [16]uint32 -+ var alpha, beta uint32 -+ for len(p) >= BlockSize { -+ a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4] -+ aa, bb, cc, dd, ee := a, b, c, d, e -+ j := 0 -+ for i := 0; i < 16; i++ { -+ x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 -+ j += 4 -+ } -+ -+ // round 1 -+ i := 0 -+ for i < 16 { -+ alpha = a + (b ^ c ^ d) + x[_n[i]] -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 2 -+ for i < 32 { -+ alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999 -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 3 -+ for i < 48 { -+ alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1 -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 4 -+ for i < 64 { -+ alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 5 -+ for i < 80 { -+ alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb ^ cc ^ dd) + x[n_[i]] -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // combine results -+ dd += c + md.s[1] -+ md.s[1] = md.s[2] + d + ee -+ md.s[2] = md.s[3] + e + aa -+ md.s[3] = md.s[4] + a + bb -+ md.s[4] = md.s[0] + b + cc -+ md.s[0] = dd -+ -+ p = p[BlockSize:] -+ n += BlockSize -+ } -+ return n -+} -diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go -index 656e8df942b8..c400dfcf7bce 100644 ---- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go -+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build amd64,!appengine,!gccgo -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc - - package salsa - -diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s -index 18085d2e8c69..c0892772045a 100644 ---- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s -+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s -@@ -2,13 +2,14 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build amd64,!appengine,!gccgo -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc - - // This code was translated into a form compatible with 6a from the public - // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html - - // func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) --// This needs up to 64 bytes at 360(SP); hence the non-obvious frame size. -+// This needs up to 64 bytes at 360(R12); hence the non-obvious frame size. - TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVQ out+0(FP),DI - MOVQ in+8(FP),SI -@@ -17,10 +18,8 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVQ key+32(FP),R8 - - MOVQ SP,R12 -- MOVQ SP,R9 -- ADDQ $31, R9 -- ANDQ $~31, R9 -- MOVQ R9, SP -+ ADDQ $31, R12 -+ ANDQ $~31, R12 - - MOVQ DX,R9 - MOVQ CX,DX -@@ -32,116 +31,116 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVL 0(R10),R8 - MOVL 0(DX),AX - MOVL 16(R10),R11 -- MOVL CX,0(SP) -- MOVL R8, 4 (SP) -- MOVL AX, 8 (SP) -- MOVL R11, 12 (SP) -+ MOVL CX,0(R12) -+ MOVL R8, 4 (R12) -+ MOVL AX, 8 (R12) -+ MOVL R11, 12 (R12) - MOVL 8(DX),CX - MOVL 24(R10),R8 - MOVL 4(R10),AX - MOVL 4(DX),R11 -- MOVL CX,16(SP) -- MOVL R8, 20 (SP) -- MOVL AX, 24 (SP) -- MOVL R11, 28 (SP) -+ MOVL CX,16(R12) -+ MOVL R8, 20 (R12) -+ MOVL AX, 24 (R12) -+ MOVL R11, 28 (R12) - MOVL 12(DX),CX - MOVL 12(R10),DX - MOVL 28(R10),R8 - MOVL 8(R10),AX -- MOVL DX,32(SP) -- MOVL CX, 36 (SP) -- MOVL R8, 40 (SP) -- MOVL AX, 44 (SP) -+ MOVL DX,32(R12) -+ MOVL CX, 36 (R12) -+ MOVL R8, 40 (R12) -+ MOVL AX, 44 (R12) - MOVQ $1634760805,DX - MOVQ $857760878,CX - MOVQ $2036477234,R8 - MOVQ $1797285236,AX -- MOVL DX,48(SP) -- MOVL CX, 52 (SP) -- MOVL R8, 56 (SP) -- MOVL AX, 60 (SP) -+ MOVL DX,48(R12) -+ MOVL CX, 52 (R12) -+ MOVL R8, 56 (R12) -+ MOVL AX, 60 (R12) - CMPQ R9,$256 - JB BYTESBETWEEN1AND255 -- MOVOA 48(SP),X0 -+ MOVOA 48(R12),X0 - PSHUFL $0X55,X0,X1 - PSHUFL $0XAA,X0,X2 - PSHUFL $0XFF,X0,X3 - PSHUFL $0X00,X0,X0 -- MOVOA X1,64(SP) -- MOVOA X2,80(SP) -- MOVOA X3,96(SP) -- MOVOA X0,112(SP) -- MOVOA 0(SP),X0 -+ MOVOA X1,64(R12) -+ MOVOA X2,80(R12) -+ MOVOA X3,96(R12) -+ MOVOA X0,112(R12) -+ MOVOA 0(R12),X0 - PSHUFL $0XAA,X0,X1 - PSHUFL $0XFF,X0,X2 - PSHUFL $0X00,X0,X3 - PSHUFL $0X55,X0,X0 -- MOVOA X1,128(SP) -- MOVOA X2,144(SP) -- MOVOA X3,160(SP) -- MOVOA X0,176(SP) -- MOVOA 16(SP),X0 -+ MOVOA X1,128(R12) -+ MOVOA X2,144(R12) -+ MOVOA X3,160(R12) -+ MOVOA X0,176(R12) -+ MOVOA 16(R12),X0 - PSHUFL $0XFF,X0,X1 - PSHUFL $0X55,X0,X2 - PSHUFL $0XAA,X0,X0 -- MOVOA X1,192(SP) -- MOVOA X2,208(SP) -- MOVOA X0,224(SP) -- MOVOA 32(SP),X0 -+ MOVOA X1,192(R12) -+ MOVOA X2,208(R12) -+ MOVOA X0,224(R12) -+ MOVOA 32(R12),X0 - PSHUFL $0X00,X0,X1 - PSHUFL $0XAA,X0,X2 - PSHUFL $0XFF,X0,X0 -- MOVOA X1,240(SP) -- MOVOA X2,256(SP) -- MOVOA X0,272(SP) -+ MOVOA X1,240(R12) -+ MOVOA X2,256(R12) -+ MOVOA X0,272(R12) - BYTESATLEAST256: -- MOVL 16(SP),DX -- MOVL 36 (SP),CX -- MOVL DX,288(SP) -- MOVL CX,304(SP) -+ MOVL 16(R12),DX -+ MOVL 36 (R12),CX -+ MOVL DX,288(R12) -+ MOVL CX,304(R12) - SHLQ $32,CX - ADDQ CX,DX - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX -- MOVL DX, 292 (SP) -- MOVL CX, 308 (SP) -+ MOVL DX, 292 (R12) -+ MOVL CX, 308 (R12) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX -- MOVL DX, 296 (SP) -- MOVL CX, 312 (SP) -+ MOVL DX, 296 (R12) -+ MOVL CX, 312 (R12) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX -- MOVL DX, 300 (SP) -- MOVL CX, 316 (SP) -+ MOVL DX, 300 (R12) -+ MOVL CX, 316 (R12) - ADDQ $1,DX - MOVQ DX,CX - SHRQ $32,CX -- MOVL DX,16(SP) -- MOVL CX, 36 (SP) -- MOVQ R9,352(SP) -+ MOVL DX,16(R12) -+ MOVL CX, 36 (R12) -+ MOVQ R9,352(R12) - MOVQ $20,DX -- MOVOA 64(SP),X0 -- MOVOA 80(SP),X1 -- MOVOA 96(SP),X2 -- MOVOA 256(SP),X3 -- MOVOA 272(SP),X4 -- MOVOA 128(SP),X5 -- MOVOA 144(SP),X6 -- MOVOA 176(SP),X7 -- MOVOA 192(SP),X8 -- MOVOA 208(SP),X9 -- MOVOA 224(SP),X10 -- MOVOA 304(SP),X11 -- MOVOA 112(SP),X12 -- MOVOA 160(SP),X13 -- MOVOA 240(SP),X14 -- MOVOA 288(SP),X15 -+ MOVOA 64(R12),X0 -+ MOVOA 80(R12),X1 -+ MOVOA 96(R12),X2 -+ MOVOA 256(R12),X3 -+ MOVOA 272(R12),X4 -+ MOVOA 128(R12),X5 -+ MOVOA 144(R12),X6 -+ MOVOA 176(R12),X7 -+ MOVOA 192(R12),X8 -+ MOVOA 208(R12),X9 -+ MOVOA 224(R12),X10 -+ MOVOA 304(R12),X11 -+ MOVOA 112(R12),X12 -+ MOVOA 160(R12),X13 -+ MOVOA 240(R12),X14 -+ MOVOA 288(R12),X15 - MAINLOOP1: -- MOVOA X1,320(SP) -- MOVOA X2,336(SP) -+ MOVOA X1,320(R12) -+ MOVOA X2,336(R12) - MOVOA X13,X1 - PADDL X12,X1 - MOVOA X1,X2 -@@ -191,8 +190,8 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PXOR X1,X12 - PSRLL $14,X2 - PXOR X2,X12 -- MOVOA 320(SP),X1 -- MOVOA X12,320(SP) -+ MOVOA 320(R12),X1 -+ MOVOA X12,320(R12) - MOVOA X9,X2 - PADDL X7,X2 - MOVOA X2,X12 -@@ -207,8 +206,8 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PXOR X2,X3 - PSRLL $25,X12 - PXOR X12,X3 -- MOVOA 336(SP),X2 -- MOVOA X0,336(SP) -+ MOVOA 336(R12),X2 -+ MOVOA X0,336(R12) - MOVOA X6,X0 - PADDL X2,X0 - MOVOA X0,X12 -@@ -251,8 +250,8 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PXOR X0,X1 - PSRLL $14,X12 - PXOR X12,X1 -- MOVOA 320(SP),X0 -- MOVOA X1,320(SP) -+ MOVOA 320(R12),X0 -+ MOVOA X1,320(R12) - MOVOA X4,X1 - PADDL X0,X1 - MOVOA X1,X12 -@@ -267,8 +266,8 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PXOR X1,X2 - PSRLL $14,X12 - PXOR X12,X2 -- MOVOA 336(SP),X12 -- MOVOA X2,336(SP) -+ MOVOA 336(R12),X12 -+ MOVOA X2,336(R12) - MOVOA X14,X1 - PADDL X12,X1 - MOVOA X1,X2 -@@ -311,8 +310,8 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PXOR X1,X0 - PSRLL $14,X2 - PXOR X2,X0 -- MOVOA 320(SP),X1 -- MOVOA X0,320(SP) -+ MOVOA 320(R12),X1 -+ MOVOA X0,320(R12) - MOVOA X8,X0 - PADDL X14,X0 - MOVOA X0,X2 -@@ -327,8 +326,8 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PXOR X0,X6 - PSRLL $25,X2 - PXOR X2,X6 -- MOVOA 336(SP),X2 -- MOVOA X12,336(SP) -+ MOVOA 336(R12),X2 -+ MOVOA X12,336(R12) - MOVOA X3,X0 - PADDL X2,X0 - MOVOA X0,X12 -@@ -378,14 +377,14 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PXOR X0,X2 - PSRLL $14,X12 - PXOR X12,X2 -- MOVOA 320(SP),X12 -- MOVOA 336(SP),X0 -+ MOVOA 320(R12),X12 -+ MOVOA 336(R12),X0 - SUBQ $2,DX - JA MAINLOOP1 -- PADDL 112(SP),X12 -- PADDL 176(SP),X7 -- PADDL 224(SP),X10 -- PADDL 272(SP),X4 -+ PADDL 112(R12),X12 -+ PADDL 176(R12),X7 -+ PADDL 224(R12),X10 -+ PADDL 272(R12),X4 - MOVD X12,DX - MOVD X7,CX - MOVD X10,R8 -@@ -446,10 +445,10 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVL CX,196(DI) - MOVL R8,200(DI) - MOVL R9,204(DI) -- PADDL 240(SP),X14 -- PADDL 64(SP),X0 -- PADDL 128(SP),X5 -- PADDL 192(SP),X8 -+ PADDL 240(R12),X14 -+ PADDL 64(R12),X0 -+ PADDL 128(R12),X5 -+ PADDL 192(R12),X8 - MOVD X14,DX - MOVD X0,CX - MOVD X5,R8 -@@ -510,10 +509,10 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVL CX,212(DI) - MOVL R8,216(DI) - MOVL R9,220(DI) -- PADDL 288(SP),X15 -- PADDL 304(SP),X11 -- PADDL 80(SP),X1 -- PADDL 144(SP),X6 -+ PADDL 288(R12),X15 -+ PADDL 304(R12),X11 -+ PADDL 80(R12),X1 -+ PADDL 144(R12),X6 - MOVD X15,DX - MOVD X11,CX - MOVD X1,R8 -@@ -574,10 +573,10 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVL CX,228(DI) - MOVL R8,232(DI) - MOVL R9,236(DI) -- PADDL 160(SP),X13 -- PADDL 208(SP),X9 -- PADDL 256(SP),X3 -- PADDL 96(SP),X2 -+ PADDL 160(R12),X13 -+ PADDL 208(R12),X9 -+ PADDL 256(R12),X3 -+ PADDL 96(R12),X2 - MOVD X13,DX - MOVD X9,CX - MOVD X3,R8 -@@ -638,7 +637,7 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVL CX,244(DI) - MOVL R8,248(DI) - MOVL R9,252(DI) -- MOVQ 352(SP),R9 -+ MOVQ 352(R12),R9 - SUBQ $256,R9 - ADDQ $256,SI - ADDQ $256,DI -@@ -650,17 +649,17 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - CMPQ R9,$64 - JAE NOCOPY - MOVQ DI,DX -- LEAQ 360(SP),DI -+ LEAQ 360(R12),DI - MOVQ R9,CX - REP; MOVSB -- LEAQ 360(SP),DI -- LEAQ 360(SP),SI -+ LEAQ 360(R12),DI -+ LEAQ 360(R12),SI - NOCOPY: -- MOVQ R9,352(SP) -- MOVOA 48(SP),X0 -- MOVOA 0(SP),X1 -- MOVOA 16(SP),X2 -- MOVOA 32(SP),X3 -+ MOVQ R9,352(R12) -+ MOVOA 48(R12),X0 -+ MOVOA 0(R12),X1 -+ MOVOA 16(R12),X2 -+ MOVOA 32(R12),X3 - MOVOA X1,X4 - MOVQ $20,CX - MAINLOOP2: -@@ -791,10 +790,10 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - PSHUFL $0X39,X3,X3 - PXOR X6,X0 - JA MAINLOOP2 -- PADDL 48(SP),X0 -- PADDL 0(SP),X1 -- PADDL 16(SP),X2 -- PADDL 32(SP),X3 -+ PADDL 48(R12),X0 -+ PADDL 0(R12),X1 -+ PADDL 16(R12),X2 -+ PADDL 32(R12),X3 - MOVD X0,CX - MOVD X1,R8 - MOVD X2,R9 -@@ -855,16 +854,16 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - MOVL R8,44(DI) - MOVL R9,28(DI) - MOVL AX,12(DI) -- MOVQ 352(SP),R9 -- MOVL 16(SP),CX -- MOVL 36 (SP),R8 -+ MOVQ 352(R12),R9 -+ MOVL 16(R12),CX -+ MOVL 36 (R12),R8 - ADDQ $1,CX - SHLQ $32,R8 - ADDQ R8,CX - MOVQ CX,R8 - SHRQ $32,R8 -- MOVL CX,16(SP) -- MOVL R8, 36 (SP) -+ MOVL CX,16(R12) -+ MOVL R8, 36 (R12) - CMPQ R9,$64 - JA BYTESATLEAST65 - JAE BYTESATLEAST64 -@@ -874,7 +873,6 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment - REP; MOVSB - BYTESATLEAST64: - DONE: -- MOVQ R12,SP - RET - BYTESATLEAST65: - SUBQ $64,R9 -diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go -index 8a46bd2b3af6..4392cc1ac740 100644 ---- a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go -+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go -@@ -2,7 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// +build !amd64 appengine gccgo -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc - - package salsa - -diff --git a/vendor/golang.org/x/crypto/salsa20/salsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa20.go -new file mode 100644 -index 000000000000..6f9bb106ca54 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/salsa20/salsa20.go -@@ -0,0 +1,58 @@ -+// Copyright 2012 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 salsa20 implements the Salsa20 stream cipher as specified in https://cr.yp.to/snuffle/spec.pdf. -+ -+Salsa20 differs from many other stream ciphers in that it is message orientated -+rather than byte orientated. Keystream blocks are not preserved between calls, -+therefore each side must encrypt/decrypt data with the same segmentation. -+ -+Another aspect of this difference is that part of the counter is exposed as -+a nonce in each call. Encrypting two different messages with the same (key, -+nonce) pair leads to trivial plaintext recovery. This is analogous to -+encrypting two different messages with the same key with a traditional stream -+cipher. -+ -+This package also implements XSalsa20: a version of Salsa20 with a 24-byte -+nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply -+passing a 24-byte slice as the nonce triggers XSalsa20. -+*/ -+package salsa20 // import "golang.org/x/crypto/salsa20" -+ -+// TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20. -+ -+import ( -+ "golang.org/x/crypto/internal/subtle" -+ "golang.org/x/crypto/salsa20/salsa" -+) -+ -+// XORKeyStream crypts bytes from in to out using the given key and nonce. -+// In and out must overlap entirely or not at all. Nonce must -+// be either 8 or 24 bytes long. -+func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { -+ if len(out) < len(in) { -+ panic("salsa20: output smaller than input") -+ } -+ if subtle.InexactOverlap(out[:len(in)], in) { -+ panic("salsa20: invalid buffer overlap") -+ } -+ -+ var subNonce [16]byte -+ -+ if len(nonce) == 24 { -+ var subKey [32]byte -+ var hNonce [16]byte -+ copy(hNonce[:], nonce[:16]) -+ salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma) -+ copy(subNonce[:], nonce[16:]) -+ key = &subKey -+ } else if len(nonce) == 8 { -+ copy(subNonce[:], nonce[:]) -+ } else { -+ panic("salsa20: nonce must be 8 or 24 bytes") -+ } -+ -+ salsa.XORKeyStream(out, in, &subNonce, key) -+} -diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go -new file mode 100644 -index 000000000000..bbe4494c6c98 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/scrypt/scrypt.go -@@ -0,0 +1,212 @@ -+// Copyright 2012 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 scrypt implements the scrypt key derivation function as defined in -+// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard -+// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf). -+package scrypt // import "golang.org/x/crypto/scrypt" -+ -+import ( -+ "crypto/sha256" -+ "encoding/binary" -+ "errors" -+ "math/bits" -+ -+ "golang.org/x/crypto/pbkdf2" -+) -+ -+const maxInt = int(^uint(0) >> 1) -+ -+// blockCopy copies n numbers from src into dst. -+func blockCopy(dst, src []uint32, n int) { -+ copy(dst, src[:n]) -+} -+ -+// blockXOR XORs numbers from dst with n numbers from src. -+func blockXOR(dst, src []uint32, n int) { -+ for i, v := range src[:n] { -+ dst[i] ^= v -+ } -+} -+ -+// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in, -+// and puts the result into both tmp and out. -+func salsaXOR(tmp *[16]uint32, in, out []uint32) { -+ w0 := tmp[0] ^ in[0] -+ w1 := tmp[1] ^ in[1] -+ w2 := tmp[2] ^ in[2] -+ w3 := tmp[3] ^ in[3] -+ w4 := tmp[4] ^ in[4] -+ w5 := tmp[5] ^ in[5] -+ w6 := tmp[6] ^ in[6] -+ w7 := tmp[7] ^ in[7] -+ w8 := tmp[8] ^ in[8] -+ w9 := tmp[9] ^ in[9] -+ w10 := tmp[10] ^ in[10] -+ w11 := tmp[11] ^ in[11] -+ w12 := tmp[12] ^ in[12] -+ w13 := tmp[13] ^ in[13] -+ w14 := tmp[14] ^ in[14] -+ w15 := tmp[15] ^ in[15] -+ -+ x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8 -+ x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 -+ -+ for i := 0; i < 8; i += 2 { -+ x4 ^= bits.RotateLeft32(x0+x12, 7) -+ x8 ^= bits.RotateLeft32(x4+x0, 9) -+ x12 ^= bits.RotateLeft32(x8+x4, 13) -+ x0 ^= bits.RotateLeft32(x12+x8, 18) -+ -+ x9 ^= bits.RotateLeft32(x5+x1, 7) -+ x13 ^= bits.RotateLeft32(x9+x5, 9) -+ x1 ^= bits.RotateLeft32(x13+x9, 13) -+ x5 ^= bits.RotateLeft32(x1+x13, 18) -+ -+ x14 ^= bits.RotateLeft32(x10+x6, 7) -+ x2 ^= bits.RotateLeft32(x14+x10, 9) -+ x6 ^= bits.RotateLeft32(x2+x14, 13) -+ x10 ^= bits.RotateLeft32(x6+x2, 18) -+ -+ x3 ^= bits.RotateLeft32(x15+x11, 7) -+ x7 ^= bits.RotateLeft32(x3+x15, 9) -+ x11 ^= bits.RotateLeft32(x7+x3, 13) -+ x15 ^= bits.RotateLeft32(x11+x7, 18) -+ -+ x1 ^= bits.RotateLeft32(x0+x3, 7) -+ x2 ^= bits.RotateLeft32(x1+x0, 9) -+ x3 ^= bits.RotateLeft32(x2+x1, 13) -+ x0 ^= bits.RotateLeft32(x3+x2, 18) -+ -+ x6 ^= bits.RotateLeft32(x5+x4, 7) -+ x7 ^= bits.RotateLeft32(x6+x5, 9) -+ x4 ^= bits.RotateLeft32(x7+x6, 13) -+ x5 ^= bits.RotateLeft32(x4+x7, 18) -+ -+ x11 ^= bits.RotateLeft32(x10+x9, 7) -+ x8 ^= bits.RotateLeft32(x11+x10, 9) -+ x9 ^= bits.RotateLeft32(x8+x11, 13) -+ x10 ^= bits.RotateLeft32(x9+x8, 18) -+ -+ x12 ^= bits.RotateLeft32(x15+x14, 7) -+ x13 ^= bits.RotateLeft32(x12+x15, 9) -+ x14 ^= bits.RotateLeft32(x13+x12, 13) -+ x15 ^= bits.RotateLeft32(x14+x13, 18) -+ } -+ x0 += w0 -+ x1 += w1 -+ x2 += w2 -+ x3 += w3 -+ x4 += w4 -+ x5 += w5 -+ x6 += w6 -+ x7 += w7 -+ x8 += w8 -+ x9 += w9 -+ x10 += w10 -+ x11 += w11 -+ x12 += w12 -+ x13 += w13 -+ x14 += w14 -+ x15 += w15 -+ -+ out[0], tmp[0] = x0, x0 -+ out[1], tmp[1] = x1, x1 -+ out[2], tmp[2] = x2, x2 -+ out[3], tmp[3] = x3, x3 -+ out[4], tmp[4] = x4, x4 -+ out[5], tmp[5] = x5, x5 -+ out[6], tmp[6] = x6, x6 -+ out[7], tmp[7] = x7, x7 -+ out[8], tmp[8] = x8, x8 -+ out[9], tmp[9] = x9, x9 -+ out[10], tmp[10] = x10, x10 -+ out[11], tmp[11] = x11, x11 -+ out[12], tmp[12] = x12, x12 -+ out[13], tmp[13] = x13, x13 -+ out[14], tmp[14] = x14, x14 -+ out[15], tmp[15] = x15, x15 -+} -+ -+func blockMix(tmp *[16]uint32, in, out []uint32, r int) { -+ blockCopy(tmp[:], in[(2*r-1)*16:], 16) -+ for i := 0; i < 2*r; i += 2 { -+ salsaXOR(tmp, in[i*16:], out[i*8:]) -+ salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:]) -+ } -+} -+ -+func integer(b []uint32, r int) uint64 { -+ j := (2*r - 1) * 16 -+ return uint64(b[j]) | uint64(b[j+1])<<32 -+} -+ -+func smix(b []byte, r, N int, v, xy []uint32) { -+ var tmp [16]uint32 -+ R := 32 * r -+ x := xy -+ y := xy[R:] -+ -+ j := 0 -+ for i := 0; i < R; i++ { -+ x[i] = binary.LittleEndian.Uint32(b[j:]) -+ j += 4 -+ } -+ for i := 0; i < N; i += 2 { -+ blockCopy(v[i*R:], x, R) -+ blockMix(&tmp, x, y, r) -+ -+ blockCopy(v[(i+1)*R:], y, R) -+ blockMix(&tmp, y, x, r) -+ } -+ for i := 0; i < N; i += 2 { -+ j := int(integer(x, r) & uint64(N-1)) -+ blockXOR(x, v[j*R:], R) -+ blockMix(&tmp, x, y, r) -+ -+ j = int(integer(y, r) & uint64(N-1)) -+ blockXOR(y, v[j*R:], R) -+ blockMix(&tmp, y, x, r) -+ } -+ j = 0 -+ for _, v := range x[:R] { -+ binary.LittleEndian.PutUint32(b[j:], v) -+ j += 4 -+ } -+} -+ -+// Key derives a key from the password, salt, and cost parameters, returning -+// a byte slice of length keyLen that can be used as cryptographic key. -+// -+// N is a CPU/memory cost parameter, which must be a power of two greater than 1. -+// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the -+// limits, the function returns a nil byte slice and an error. -+// -+// For example, you can get a derived key for e.g. AES-256 (which needs a -+// 32-byte key) by doing: -+// -+// dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) -+// -+// The recommended parameters for interactive logins as of 2017 are N=32768, r=8 -+// and p=1. The parameters N, r, and p should be increased as memory latency and -+// CPU parallelism increases; consider setting N to the highest power of 2 you -+// can derive within 100 milliseconds. Remember to get a good random salt. -+func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { -+ if N <= 1 || N&(N-1) != 0 { -+ return nil, errors.New("scrypt: N must be > 1 and a power of 2") -+ } -+ if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { -+ return nil, errors.New("scrypt: parameters are too large") -+ } -+ -+ xy := make([]uint32, 64*r) -+ v := make([]uint32, 32*N*r) -+ b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) -+ -+ for i := 0; i < p; i++ { -+ smix(b[i*128*r:], r, N, v, xy) -+ } -+ -+ return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil -+} -diff --git a/vendor/golang.org/x/crypto/sha3/doc.go b/vendor/golang.org/x/crypto/sha3/doc.go -new file mode 100644 -index 000000000000..c2fef30afff3 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/doc.go -@@ -0,0 +1,66 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package sha3 implements the SHA-3 fixed-output-length hash functions and -+// the SHAKE variable-output-length hash functions defined by FIPS-202. -+// -+// Both types of hash function use the "sponge" construction and the Keccak -+// permutation. For a detailed specification see http://keccak.noekeon.org/ -+// -+// -+// Guidance -+// -+// If you aren't sure what function you need, use SHAKE256 with at least 64 -+// bytes of output. The SHAKE instances are faster than the SHA3 instances; -+// the latter have to allocate memory to conform to the hash.Hash interface. -+// -+// If you need a secret-key MAC (message authentication code), prepend the -+// secret key to the input, hash with SHAKE256 and read at least 32 bytes of -+// output. -+// -+// -+// Security strengths -+// -+// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security -+// strength against preimage attacks of x bits. Since they only produce "x" -+// bits of output, their collision-resistance is only "x/2" bits. -+// -+// The SHAKE-256 and -128 functions have a generic security strength of 256 and -+// 128 bits against all attacks, provided that at least 2x bits of their output -+// is used. Requesting more than 64 or 32 bytes of output, respectively, does -+// not increase the collision-resistance of the SHAKE functions. -+// -+// -+// The sponge construction -+// -+// A sponge builds a pseudo-random function from a public pseudo-random -+// permutation, by applying the permutation to a state of "rate + capacity" -+// bytes, but hiding "capacity" of the bytes. -+// -+// A sponge starts out with a zero state. To hash an input using a sponge, up -+// to "rate" bytes of the input are XORed into the sponge's state. The sponge -+// is then "full" and the permutation is applied to "empty" it. This process is -+// repeated until all the input has been "absorbed". The input is then padded. -+// The digest is "squeezed" from the sponge in the same way, except that output -+// is copied out instead of input being XORed in. -+// -+// A sponge is parameterized by its generic security strength, which is equal -+// to half its capacity; capacity + rate is equal to the permutation's width. -+// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means -+// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. -+// -+// -+// Recommendations -+// -+// The SHAKE functions are recommended for most new uses. They can produce -+// output of arbitrary length. SHAKE256, with an output length of at least -+// 64 bytes, provides 256-bit security against all attacks. The Keccak team -+// recommends it for most applications upgrading from SHA2-512. (NIST chose a -+// much stronger, but much slower, sponge instance for SHA3-512.) -+// -+// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. -+// They produce output of the same length, with the same security strengths -+// against all attacks. This means, in particular, that SHA3-256 only has -+// 128-bit collision resistance, because its output length is 32 bytes. -+package sha3 // import "golang.org/x/crypto/sha3" -diff --git a/vendor/golang.org/x/crypto/sha3/hashes.go b/vendor/golang.org/x/crypto/sha3/hashes.go -new file mode 100644 -index 000000000000..0d8043fd2a17 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/hashes.go -@@ -0,0 +1,97 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+// This file provides functions for creating instances of the SHA-3 -+// and SHAKE hash functions, as well as utility functions for hashing -+// bytes. -+ -+import ( -+ "hash" -+) -+ -+// New224 creates a new SHA3-224 hash. -+// Its generic security strength is 224 bits against preimage attacks, -+// and 112 bits against collision attacks. -+func New224() hash.Hash { -+ if h := new224Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 144, outputLen: 28, dsbyte: 0x06} -+} -+ -+// New256 creates a new SHA3-256 hash. -+// Its generic security strength is 256 bits against preimage attacks, -+// and 128 bits against collision attacks. -+func New256() hash.Hash { -+ if h := new256Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 136, outputLen: 32, dsbyte: 0x06} -+} -+ -+// New384 creates a new SHA3-384 hash. -+// Its generic security strength is 384 bits against preimage attacks, -+// and 192 bits against collision attacks. -+func New384() hash.Hash { -+ if h := new384Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 104, outputLen: 48, dsbyte: 0x06} -+} -+ -+// New512 creates a new SHA3-512 hash. -+// Its generic security strength is 512 bits against preimage attacks, -+// and 256 bits against collision attacks. -+func New512() hash.Hash { -+ if h := new512Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 72, outputLen: 64, dsbyte: 0x06} -+} -+ -+// NewLegacyKeccak256 creates a new Keccak-256 hash. -+// -+// Only use this function if you require compatibility with an existing cryptosystem -+// that uses non-standard padding. All other users should use New256 instead. -+func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } -+ -+// NewLegacyKeccak512 creates a new Keccak-512 hash. -+// -+// Only use this function if you require compatibility with an existing cryptosystem -+// that uses non-standard padding. All other users should use New512 instead. -+func NewLegacyKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } -+ -+// Sum224 returns the SHA3-224 digest of the data. -+func Sum224(data []byte) (digest [28]byte) { -+ h := New224() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -+ -+// Sum256 returns the SHA3-256 digest of the data. -+func Sum256(data []byte) (digest [32]byte) { -+ h := New256() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -+ -+// Sum384 returns the SHA3-384 digest of the data. -+func Sum384(data []byte) (digest [48]byte) { -+ h := New384() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -+ -+// Sum512 returns the SHA3-512 digest of the data. -+func Sum512(data []byte) (digest [64]byte) { -+ h := New512() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -diff --git a/vendor/golang.org/x/crypto/sha3/hashes_generic.go b/vendor/golang.org/x/crypto/sha3/hashes_generic.go -new file mode 100644 -index 000000000000..c74fc20fcb33 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/hashes_generic.go -@@ -0,0 +1,28 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !gc || purego || !s390x -+// +build !gc purego !s390x -+ -+package sha3 -+ -+import ( -+ "hash" -+) -+ -+// new224Asm returns an assembly implementation of SHA3-224 if available, -+// otherwise it returns nil. -+func new224Asm() hash.Hash { return nil } -+ -+// new256Asm returns an assembly implementation of SHA3-256 if available, -+// otherwise it returns nil. -+func new256Asm() hash.Hash { return nil } -+ -+// new384Asm returns an assembly implementation of SHA3-384 if available, -+// otherwise it returns nil. -+func new384Asm() hash.Hash { return nil } -+ -+// new512Asm returns an assembly implementation of SHA3-512 if available, -+// otherwise it returns nil. -+func new512Asm() hash.Hash { return nil } -diff --git a/vendor/golang.org/x/crypto/sha3/keccakf.go b/vendor/golang.org/x/crypto/sha3/keccakf.go -new file mode 100644 -index 000000000000..0f4ae8bacff5 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/keccakf.go -@@ -0,0 +1,413 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc -+ -+package sha3 -+ -+// rc stores the round constants for use in the ι step. -+var rc = [24]uint64{ -+ 0x0000000000000001, -+ 0x0000000000008082, -+ 0x800000000000808A, -+ 0x8000000080008000, -+ 0x000000000000808B, -+ 0x0000000080000001, -+ 0x8000000080008081, -+ 0x8000000000008009, -+ 0x000000000000008A, -+ 0x0000000000000088, -+ 0x0000000080008009, -+ 0x000000008000000A, -+ 0x000000008000808B, -+ 0x800000000000008B, -+ 0x8000000000008089, -+ 0x8000000000008003, -+ 0x8000000000008002, -+ 0x8000000000000080, -+ 0x000000000000800A, -+ 0x800000008000000A, -+ 0x8000000080008081, -+ 0x8000000000008080, -+ 0x0000000080000001, -+ 0x8000000080008008, -+} -+ -+// keccakF1600 applies the Keccak permutation to a 1600b-wide -+// state represented as a slice of 25 uint64s. -+func keccakF1600(a *[25]uint64) { -+ // Implementation translated from Keccak-inplace.c -+ // in the keccak reference code. -+ var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 -+ -+ for i := 0; i < 24; i += 4 { -+ // Combines the 5 steps in each round into 2 steps. -+ // Unrolls 4 rounds per loop and spreads some steps across rounds. -+ -+ // Round 1 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[6] ^ d1 -+ bc1 = t<<44 | t>>(64-44) -+ t = a[12] ^ d2 -+ bc2 = t<<43 | t>>(64-43) -+ t = a[18] ^ d3 -+ bc3 = t<<21 | t>>(64-21) -+ t = a[24] ^ d4 -+ bc4 = t<<14 | t>>(64-14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc2 = t<<3 | t>>(64-3) -+ t = a[16] ^ d1 -+ bc3 = t<<45 | t>>(64-45) -+ t = a[22] ^ d2 -+ bc4 = t<<61 | t>>(64-61) -+ t = a[3] ^ d3 -+ bc0 = t<<28 | t>>(64-28) -+ t = a[9] ^ d4 -+ bc1 = t<<20 | t>>(64-20) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc4 = t<<18 | t>>(64-18) -+ t = a[1] ^ d1 -+ bc0 = t<<1 | t>>(64-1) -+ t = a[7] ^ d2 -+ bc1 = t<<6 | t>>(64-6) -+ t = a[13] ^ d3 -+ bc2 = t<<25 | t>>(64-25) -+ t = a[19] ^ d4 -+ bc3 = t<<8 | t>>(64-8) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc1 = t<<36 | t>>(64-36) -+ t = a[11] ^ d1 -+ bc2 = t<<10 | t>>(64-10) -+ t = a[17] ^ d2 -+ bc3 = t<<15 | t>>(64-15) -+ t = a[23] ^ d3 -+ bc4 = t<<56 | t>>(64-56) -+ t = a[4] ^ d4 -+ bc0 = t<<27 | t>>(64-27) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc3 = t<<41 | t>>(64-41) -+ t = a[21] ^ d1 -+ bc4 = t<<2 | t>>(64-2) -+ t = a[2] ^ d2 -+ bc0 = t<<62 | t>>(64-62) -+ t = a[8] ^ d3 -+ bc1 = t<<55 | t>>(64-55) -+ t = a[14] ^ d4 -+ bc2 = t<<39 | t>>(64-39) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ // Round 2 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[16] ^ d1 -+ bc1 = t<<44 | t>>(64-44) -+ t = a[7] ^ d2 -+ bc2 = t<<43 | t>>(64-43) -+ t = a[23] ^ d3 -+ bc3 = t<<21 | t>>(64-21) -+ t = a[14] ^ d4 -+ bc4 = t<<14 | t>>(64-14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc2 = t<<3 | t>>(64-3) -+ t = a[11] ^ d1 -+ bc3 = t<<45 | t>>(64-45) -+ t = a[2] ^ d2 -+ bc4 = t<<61 | t>>(64-61) -+ t = a[18] ^ d3 -+ bc0 = t<<28 | t>>(64-28) -+ t = a[9] ^ d4 -+ bc1 = t<<20 | t>>(64-20) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc4 = t<<18 | t>>(64-18) -+ t = a[6] ^ d1 -+ bc0 = t<<1 | t>>(64-1) -+ t = a[22] ^ d2 -+ bc1 = t<<6 | t>>(64-6) -+ t = a[13] ^ d3 -+ bc2 = t<<25 | t>>(64-25) -+ t = a[4] ^ d4 -+ bc3 = t<<8 | t>>(64-8) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc1 = t<<36 | t>>(64-36) -+ t = a[1] ^ d1 -+ bc2 = t<<10 | t>>(64-10) -+ t = a[17] ^ d2 -+ bc3 = t<<15 | t>>(64-15) -+ t = a[8] ^ d3 -+ bc4 = t<<56 | t>>(64-56) -+ t = a[24] ^ d4 -+ bc0 = t<<27 | t>>(64-27) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc3 = t<<41 | t>>(64-41) -+ t = a[21] ^ d1 -+ bc4 = t<<2 | t>>(64-2) -+ t = a[12] ^ d2 -+ bc0 = t<<62 | t>>(64-62) -+ t = a[3] ^ d3 -+ bc1 = t<<55 | t>>(64-55) -+ t = a[19] ^ d4 -+ bc2 = t<<39 | t>>(64-39) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ // Round 3 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[11] ^ d1 -+ bc1 = t<<44 | t>>(64-44) -+ t = a[22] ^ d2 -+ bc2 = t<<43 | t>>(64-43) -+ t = a[8] ^ d3 -+ bc3 = t<<21 | t>>(64-21) -+ t = a[19] ^ d4 -+ bc4 = t<<14 | t>>(64-14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc2 = t<<3 | t>>(64-3) -+ t = a[1] ^ d1 -+ bc3 = t<<45 | t>>(64-45) -+ t = a[12] ^ d2 -+ bc4 = t<<61 | t>>(64-61) -+ t = a[23] ^ d3 -+ bc0 = t<<28 | t>>(64-28) -+ t = a[9] ^ d4 -+ bc1 = t<<20 | t>>(64-20) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc4 = t<<18 | t>>(64-18) -+ t = a[16] ^ d1 -+ bc0 = t<<1 | t>>(64-1) -+ t = a[2] ^ d2 -+ bc1 = t<<6 | t>>(64-6) -+ t = a[13] ^ d3 -+ bc2 = t<<25 | t>>(64-25) -+ t = a[24] ^ d4 -+ bc3 = t<<8 | t>>(64-8) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc1 = t<<36 | t>>(64-36) -+ t = a[6] ^ d1 -+ bc2 = t<<10 | t>>(64-10) -+ t = a[17] ^ d2 -+ bc3 = t<<15 | t>>(64-15) -+ t = a[3] ^ d3 -+ bc4 = t<<56 | t>>(64-56) -+ t = a[14] ^ d4 -+ bc0 = t<<27 | t>>(64-27) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc3 = t<<41 | t>>(64-41) -+ t = a[21] ^ d1 -+ bc4 = t<<2 | t>>(64-2) -+ t = a[7] ^ d2 -+ bc0 = t<<62 | t>>(64-62) -+ t = a[18] ^ d3 -+ bc1 = t<<55 | t>>(64-55) -+ t = a[4] ^ d4 -+ bc2 = t<<39 | t>>(64-39) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ // Round 4 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[1] ^ d1 -+ bc1 = t<<44 | t>>(64-44) -+ t = a[2] ^ d2 -+ bc2 = t<<43 | t>>(64-43) -+ t = a[3] ^ d3 -+ bc3 = t<<21 | t>>(64-21) -+ t = a[4] ^ d4 -+ bc4 = t<<14 | t>>(64-14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc2 = t<<3 | t>>(64-3) -+ t = a[6] ^ d1 -+ bc3 = t<<45 | t>>(64-45) -+ t = a[7] ^ d2 -+ bc4 = t<<61 | t>>(64-61) -+ t = a[8] ^ d3 -+ bc0 = t<<28 | t>>(64-28) -+ t = a[9] ^ d4 -+ bc1 = t<<20 | t>>(64-20) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc4 = t<<18 | t>>(64-18) -+ t = a[11] ^ d1 -+ bc0 = t<<1 | t>>(64-1) -+ t = a[12] ^ d2 -+ bc1 = t<<6 | t>>(64-6) -+ t = a[13] ^ d3 -+ bc2 = t<<25 | t>>(64-25) -+ t = a[14] ^ d4 -+ bc3 = t<<8 | t>>(64-8) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc1 = t<<36 | t>>(64-36) -+ t = a[16] ^ d1 -+ bc2 = t<<10 | t>>(64-10) -+ t = a[17] ^ d2 -+ bc3 = t<<15 | t>>(64-15) -+ t = a[18] ^ d3 -+ bc4 = t<<56 | t>>(64-56) -+ t = a[19] ^ d4 -+ bc0 = t<<27 | t>>(64-27) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc3 = t<<41 | t>>(64-41) -+ t = a[21] ^ d1 -+ bc4 = t<<2 | t>>(64-2) -+ t = a[22] ^ d2 -+ bc0 = t<<62 | t>>(64-62) -+ t = a[23] ^ d3 -+ bc1 = t<<55 | t>>(64-55) -+ t = a[24] ^ d4 -+ bc2 = t<<39 | t>>(64-39) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ } -+} -diff --git a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go -new file mode 100644 -index 000000000000..248a38241ff9 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go -@@ -0,0 +1,14 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc -+ -+package sha3 -+ -+// This function is implemented in keccakf_amd64.s. -+ -+//go:noescape -+ -+func keccakF1600(a *[25]uint64) -diff --git a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s -new file mode 100644 -index 000000000000..4cfa54383bfa ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s -@@ -0,0 +1,391 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc -+ -+// This code was translated into a form compatible with 6a from the public -+// domain sources at https://github.com/gvanas/KeccakCodePackage -+ -+// Offsets in state -+#define _ba (0*8) -+#define _be (1*8) -+#define _bi (2*8) -+#define _bo (3*8) -+#define _bu (4*8) -+#define _ga (5*8) -+#define _ge (6*8) -+#define _gi (7*8) -+#define _go (8*8) -+#define _gu (9*8) -+#define _ka (10*8) -+#define _ke (11*8) -+#define _ki (12*8) -+#define _ko (13*8) -+#define _ku (14*8) -+#define _ma (15*8) -+#define _me (16*8) -+#define _mi (17*8) -+#define _mo (18*8) -+#define _mu (19*8) -+#define _sa (20*8) -+#define _se (21*8) -+#define _si (22*8) -+#define _so (23*8) -+#define _su (24*8) -+ -+// Temporary registers -+#define rT1 AX -+ -+// Round vars -+#define rpState DI -+#define rpStack SP -+ -+#define rDa BX -+#define rDe CX -+#define rDi DX -+#define rDo R8 -+#define rDu R9 -+ -+#define rBa R10 -+#define rBe R11 -+#define rBi R12 -+#define rBo R13 -+#define rBu R14 -+ -+#define rCa SI -+#define rCe BP -+#define rCi rBi -+#define rCo rBo -+#define rCu R15 -+ -+#define MOVQ_RBI_RCE MOVQ rBi, rCe -+#define XORQ_RT1_RCA XORQ rT1, rCa -+#define XORQ_RT1_RCE XORQ rT1, rCe -+#define XORQ_RBA_RCU XORQ rBa, rCu -+#define XORQ_RBE_RCU XORQ rBe, rCu -+#define XORQ_RDU_RCU XORQ rDu, rCu -+#define XORQ_RDA_RCA XORQ rDa, rCa -+#define XORQ_RDE_RCE XORQ rDe, rCe -+ -+#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ -+ /* Prepare round */ \ -+ MOVQ rCe, rDa; \ -+ ROLQ $1, rDa; \ -+ \ -+ MOVQ _bi(iState), rCi; \ -+ XORQ _gi(iState), rDi; \ -+ XORQ rCu, rDa; \ -+ XORQ _ki(iState), rCi; \ -+ XORQ _mi(iState), rDi; \ -+ XORQ rDi, rCi; \ -+ \ -+ MOVQ rCi, rDe; \ -+ ROLQ $1, rDe; \ -+ \ -+ MOVQ _bo(iState), rCo; \ -+ XORQ _go(iState), rDo; \ -+ XORQ rCa, rDe; \ -+ XORQ _ko(iState), rCo; \ -+ XORQ _mo(iState), rDo; \ -+ XORQ rDo, rCo; \ -+ \ -+ MOVQ rCo, rDi; \ -+ ROLQ $1, rDi; \ -+ \ -+ MOVQ rCu, rDo; \ -+ XORQ rCe, rDi; \ -+ ROLQ $1, rDo; \ -+ \ -+ MOVQ rCa, rDu; \ -+ XORQ rCi, rDo; \ -+ ROLQ $1, rDu; \ -+ \ -+ /* Result b */ \ -+ MOVQ _ba(iState), rBa; \ -+ MOVQ _ge(iState), rBe; \ -+ XORQ rCo, rDu; \ -+ MOVQ _ki(iState), rBi; \ -+ MOVQ _mo(iState), rBo; \ -+ MOVQ _su(iState), rBu; \ -+ XORQ rDe, rBe; \ -+ ROLQ $44, rBe; \ -+ XORQ rDi, rBi; \ -+ XORQ rDa, rBa; \ -+ ROLQ $43, rBi; \ -+ \ -+ MOVQ rBe, rCa; \ -+ MOVQ rc, rT1; \ -+ ORQ rBi, rCa; \ -+ XORQ rBa, rT1; \ -+ XORQ rT1, rCa; \ -+ MOVQ rCa, _ba(oState); \ -+ \ -+ XORQ rDu, rBu; \ -+ ROLQ $14, rBu; \ -+ MOVQ rBa, rCu; \ -+ ANDQ rBe, rCu; \ -+ XORQ rBu, rCu; \ -+ MOVQ rCu, _bu(oState); \ -+ \ -+ XORQ rDo, rBo; \ -+ ROLQ $21, rBo; \ -+ MOVQ rBo, rT1; \ -+ ANDQ rBu, rT1; \ -+ XORQ rBi, rT1; \ -+ MOVQ rT1, _bi(oState); \ -+ \ -+ NOTQ rBi; \ -+ ORQ rBa, rBu; \ -+ ORQ rBo, rBi; \ -+ XORQ rBo, rBu; \ -+ XORQ rBe, rBi; \ -+ MOVQ rBu, _bo(oState); \ -+ MOVQ rBi, _be(oState); \ -+ B_RBI_RCE; \ -+ \ -+ /* Result g */ \ -+ MOVQ _gu(iState), rBe; \ -+ XORQ rDu, rBe; \ -+ MOVQ _ka(iState), rBi; \ -+ ROLQ $20, rBe; \ -+ XORQ rDa, rBi; \ -+ ROLQ $3, rBi; \ -+ MOVQ _bo(iState), rBa; \ -+ MOVQ rBe, rT1; \ -+ ORQ rBi, rT1; \ -+ XORQ rDo, rBa; \ -+ MOVQ _me(iState), rBo; \ -+ MOVQ _si(iState), rBu; \ -+ ROLQ $28, rBa; \ -+ XORQ rBa, rT1; \ -+ MOVQ rT1, _ga(oState); \ -+ G_RT1_RCA; \ -+ \ -+ XORQ rDe, rBo; \ -+ ROLQ $45, rBo; \ -+ MOVQ rBi, rT1; \ -+ ANDQ rBo, rT1; \ -+ XORQ rBe, rT1; \ -+ MOVQ rT1, _ge(oState); \ -+ G_RT1_RCE; \ -+ \ -+ XORQ rDi, rBu; \ -+ ROLQ $61, rBu; \ -+ MOVQ rBu, rT1; \ -+ ORQ rBa, rT1; \ -+ XORQ rBo, rT1; \ -+ MOVQ rT1, _go(oState); \ -+ \ -+ ANDQ rBe, rBa; \ -+ XORQ rBu, rBa; \ -+ MOVQ rBa, _gu(oState); \ -+ NOTQ rBu; \ -+ G_RBA_RCU; \ -+ \ -+ ORQ rBu, rBo; \ -+ XORQ rBi, rBo; \ -+ MOVQ rBo, _gi(oState); \ -+ \ -+ /* Result k */ \ -+ MOVQ _be(iState), rBa; \ -+ MOVQ _gi(iState), rBe; \ -+ MOVQ _ko(iState), rBi; \ -+ MOVQ _mu(iState), rBo; \ -+ MOVQ _sa(iState), rBu; \ -+ XORQ rDi, rBe; \ -+ ROLQ $6, rBe; \ -+ XORQ rDo, rBi; \ -+ ROLQ $25, rBi; \ -+ MOVQ rBe, rT1; \ -+ ORQ rBi, rT1; \ -+ XORQ rDe, rBa; \ -+ ROLQ $1, rBa; \ -+ XORQ rBa, rT1; \ -+ MOVQ rT1, _ka(oState); \ -+ K_RT1_RCA; \ -+ \ -+ XORQ rDu, rBo; \ -+ ROLQ $8, rBo; \ -+ MOVQ rBi, rT1; \ -+ ANDQ rBo, rT1; \ -+ XORQ rBe, rT1; \ -+ MOVQ rT1, _ke(oState); \ -+ K_RT1_RCE; \ -+ \ -+ XORQ rDa, rBu; \ -+ ROLQ $18, rBu; \ -+ NOTQ rBo; \ -+ MOVQ rBo, rT1; \ -+ ANDQ rBu, rT1; \ -+ XORQ rBi, rT1; \ -+ MOVQ rT1, _ki(oState); \ -+ \ -+ MOVQ rBu, rT1; \ -+ ORQ rBa, rT1; \ -+ XORQ rBo, rT1; \ -+ MOVQ rT1, _ko(oState); \ -+ \ -+ ANDQ rBe, rBa; \ -+ XORQ rBu, rBa; \ -+ MOVQ rBa, _ku(oState); \ -+ K_RBA_RCU; \ -+ \ -+ /* Result m */ \ -+ MOVQ _ga(iState), rBe; \ -+ XORQ rDa, rBe; \ -+ MOVQ _ke(iState), rBi; \ -+ ROLQ $36, rBe; \ -+ XORQ rDe, rBi; \ -+ MOVQ _bu(iState), rBa; \ -+ ROLQ $10, rBi; \ -+ MOVQ rBe, rT1; \ -+ MOVQ _mi(iState), rBo; \ -+ ANDQ rBi, rT1; \ -+ XORQ rDu, rBa; \ -+ MOVQ _so(iState), rBu; \ -+ ROLQ $27, rBa; \ -+ XORQ rBa, rT1; \ -+ MOVQ rT1, _ma(oState); \ -+ M_RT1_RCA; \ -+ \ -+ XORQ rDi, rBo; \ -+ ROLQ $15, rBo; \ -+ MOVQ rBi, rT1; \ -+ ORQ rBo, rT1; \ -+ XORQ rBe, rT1; \ -+ MOVQ rT1, _me(oState); \ -+ M_RT1_RCE; \ -+ \ -+ XORQ rDo, rBu; \ -+ ROLQ $56, rBu; \ -+ NOTQ rBo; \ -+ MOVQ rBo, rT1; \ -+ ORQ rBu, rT1; \ -+ XORQ rBi, rT1; \ -+ MOVQ rT1, _mi(oState); \ -+ \ -+ ORQ rBa, rBe; \ -+ XORQ rBu, rBe; \ -+ MOVQ rBe, _mu(oState); \ -+ \ -+ ANDQ rBa, rBu; \ -+ XORQ rBo, rBu; \ -+ MOVQ rBu, _mo(oState); \ -+ M_RBE_RCU; \ -+ \ -+ /* Result s */ \ -+ MOVQ _bi(iState), rBa; \ -+ MOVQ _go(iState), rBe; \ -+ MOVQ _ku(iState), rBi; \ -+ XORQ rDi, rBa; \ -+ MOVQ _ma(iState), rBo; \ -+ ROLQ $62, rBa; \ -+ XORQ rDo, rBe; \ -+ MOVQ _se(iState), rBu; \ -+ ROLQ $55, rBe; \ -+ \ -+ XORQ rDu, rBi; \ -+ MOVQ rBa, rDu; \ -+ XORQ rDe, rBu; \ -+ ROLQ $2, rBu; \ -+ ANDQ rBe, rDu; \ -+ XORQ rBu, rDu; \ -+ MOVQ rDu, _su(oState); \ -+ \ -+ ROLQ $39, rBi; \ -+ S_RDU_RCU; \ -+ NOTQ rBe; \ -+ XORQ rDa, rBo; \ -+ MOVQ rBe, rDa; \ -+ ANDQ rBi, rDa; \ -+ XORQ rBa, rDa; \ -+ MOVQ rDa, _sa(oState); \ -+ S_RDA_RCA; \ -+ \ -+ ROLQ $41, rBo; \ -+ MOVQ rBi, rDe; \ -+ ORQ rBo, rDe; \ -+ XORQ rBe, rDe; \ -+ MOVQ rDe, _se(oState); \ -+ S_RDE_RCE; \ -+ \ -+ MOVQ rBo, rDi; \ -+ MOVQ rBu, rDo; \ -+ ANDQ rBu, rDi; \ -+ ORQ rBa, rDo; \ -+ XORQ rBi, rDi; \ -+ XORQ rBo, rDo; \ -+ MOVQ rDi, _si(oState); \ -+ MOVQ rDo, _so(oState) \ -+ -+// func keccakF1600(state *[25]uint64) -+TEXT ·keccakF1600(SB), 0, $200-8 -+ MOVQ state+0(FP), rpState -+ -+ // Convert the user state into an internal state -+ NOTQ _be(rpState) -+ NOTQ _bi(rpState) -+ NOTQ _go(rpState) -+ NOTQ _ki(rpState) -+ NOTQ _mi(rpState) -+ NOTQ _sa(rpState) -+ -+ // Execute the KeccakF permutation -+ MOVQ _ba(rpState), rCa -+ MOVQ _be(rpState), rCe -+ MOVQ _bu(rpState), rCu -+ -+ XORQ _ga(rpState), rCa -+ XORQ _ge(rpState), rCe -+ XORQ _gu(rpState), rCu -+ -+ XORQ _ka(rpState), rCa -+ XORQ _ke(rpState), rCe -+ XORQ _ku(rpState), rCu -+ -+ XORQ _ma(rpState), rCa -+ XORQ _me(rpState), rCe -+ XORQ _mu(rpState), rCu -+ -+ XORQ _sa(rpState), rCa -+ XORQ _se(rpState), rCe -+ MOVQ _si(rpState), rDi -+ MOVQ _so(rpState), rDo -+ XORQ _su(rpState), rCu -+ -+ mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) -+ -+ // Revert the internal state to the user state -+ NOTQ _be(rpState) -+ NOTQ _bi(rpState) -+ NOTQ _go(rpState) -+ NOTQ _ki(rpState) -+ NOTQ _mi(rpState) -+ NOTQ _sa(rpState) -+ -+ RET -diff --git a/vendor/golang.org/x/crypto/sha3/register.go b/vendor/golang.org/x/crypto/sha3/register.go -new file mode 100644 -index 000000000000..8b4453aac3c3 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/register.go -@@ -0,0 +1,19 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.4 -+// +build go1.4 -+ -+package sha3 -+ -+import ( -+ "crypto" -+) -+ -+func init() { -+ crypto.RegisterHash(crypto.SHA3_224, New224) -+ crypto.RegisterHash(crypto.SHA3_256, New256) -+ crypto.RegisterHash(crypto.SHA3_384, New384) -+ crypto.RegisterHash(crypto.SHA3_512, New512) -+} -diff --git a/vendor/golang.org/x/crypto/sha3/sha3.go b/vendor/golang.org/x/crypto/sha3/sha3.go -new file mode 100644 -index 000000000000..fa182beb40b5 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/sha3.go -@@ -0,0 +1,193 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+// spongeDirection indicates the direction bytes are flowing through the sponge. -+type spongeDirection int -+ -+const ( -+ // spongeAbsorbing indicates that the sponge is absorbing input. -+ spongeAbsorbing spongeDirection = iota -+ // spongeSqueezing indicates that the sponge is being squeezed. -+ spongeSqueezing -+) -+ -+const ( -+ // maxRate is the maximum size of the internal buffer. SHAKE-256 -+ // currently needs the largest buffer. -+ maxRate = 168 -+) -+ -+type state struct { -+ // Generic sponge components. -+ a [25]uint64 // main state of the hash -+ buf []byte // points into storage -+ rate int // the number of bytes of state to use -+ -+ // dsbyte contains the "domain separation" bits and the first bit of -+ // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the -+ // SHA-3 and SHAKE functions by appending bitstrings to the message. -+ // Using a little-endian bit-ordering convention, these are "01" for SHA-3 -+ // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the -+ // padding rule from section 5.1 is applied to pad the message to a multiple -+ // of the rate, which involves adding a "1" bit, zero or more "0" bits, and -+ // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, -+ // giving 00000110b (0x06) and 00011111b (0x1f). -+ // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf -+ // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and -+ // Extendable-Output Functions (May 2014)" -+ dsbyte byte -+ -+ storage storageBuf -+ -+ // Specific to SHA-3 and SHAKE. -+ outputLen int // the default output size in bytes -+ state spongeDirection // whether the sponge is absorbing or squeezing -+} -+ -+// BlockSize returns the rate of sponge underlying this hash function. -+func (d *state) BlockSize() int { return d.rate } -+ -+// Size returns the output size of the hash function in bytes. -+func (d *state) Size() int { return d.outputLen } -+ -+// Reset clears the internal state by zeroing the sponge state and -+// the byte buffer, and setting Sponge.state to absorbing. -+func (d *state) Reset() { -+ // Zero the permutation's state. -+ for i := range d.a { -+ d.a[i] = 0 -+ } -+ d.state = spongeAbsorbing -+ d.buf = d.storage.asBytes()[:0] -+} -+ -+func (d *state) clone() *state { -+ ret := *d -+ if ret.state == spongeAbsorbing { -+ ret.buf = ret.storage.asBytes()[:len(ret.buf)] -+ } else { -+ ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate] -+ } -+ -+ return &ret -+} -+ -+// permute applies the KeccakF-1600 permutation. It handles -+// any input-output buffering. -+func (d *state) permute() { -+ switch d.state { -+ case spongeAbsorbing: -+ // If we're absorbing, we need to xor the input into the state -+ // before applying the permutation. -+ xorIn(d, d.buf) -+ d.buf = d.storage.asBytes()[:0] -+ keccakF1600(&d.a) -+ case spongeSqueezing: -+ // If we're squeezing, we need to apply the permutation before -+ // copying more output. -+ keccakF1600(&d.a) -+ d.buf = d.storage.asBytes()[:d.rate] -+ copyOut(d, d.buf) -+ } -+} -+ -+// pads appends the domain separation bits in dsbyte, applies -+// the multi-bitrate 10..1 padding rule, and permutes the state. -+func (d *state) padAndPermute(dsbyte byte) { -+ if d.buf == nil { -+ d.buf = d.storage.asBytes()[:0] -+ } -+ // Pad with this instance's domain-separator bits. We know that there's -+ // at least one byte of space in d.buf because, if it were full, -+ // permute would have been called to empty it. dsbyte also contains the -+ // first one bit for the padding. See the comment in the state struct. -+ d.buf = append(d.buf, dsbyte) -+ zerosStart := len(d.buf) -+ d.buf = d.storage.asBytes()[:d.rate] -+ for i := zerosStart; i < d.rate; i++ { -+ d.buf[i] = 0 -+ } -+ // This adds the final one bit for the padding. Because of the way that -+ // bits are numbered from the LSB upwards, the final bit is the MSB of -+ // the last byte. -+ d.buf[d.rate-1] ^= 0x80 -+ // Apply the permutation -+ d.permute() -+ d.state = spongeSqueezing -+ d.buf = d.storage.asBytes()[:d.rate] -+ copyOut(d, d.buf) -+} -+ -+// Write absorbs more data into the hash's state. It produces an error -+// if more data is written to the ShakeHash after writing -+func (d *state) Write(p []byte) (written int, err error) { -+ if d.state != spongeAbsorbing { -+ panic("sha3: write to sponge after read") -+ } -+ if d.buf == nil { -+ d.buf = d.storage.asBytes()[:0] -+ } -+ written = len(p) -+ -+ for len(p) > 0 { -+ if len(d.buf) == 0 && len(p) >= d.rate { -+ // The fast path; absorb a full "rate" bytes of input and apply the permutation. -+ xorIn(d, p[:d.rate]) -+ p = p[d.rate:] -+ keccakF1600(&d.a) -+ } else { -+ // The slow path; buffer the input until we can fill the sponge, and then xor it in. -+ todo := d.rate - len(d.buf) -+ if todo > len(p) { -+ todo = len(p) -+ } -+ d.buf = append(d.buf, p[:todo]...) -+ p = p[todo:] -+ -+ // If the sponge is full, apply the permutation. -+ if len(d.buf) == d.rate { -+ d.permute() -+ } -+ } -+ } -+ -+ return -+} -+ -+// Read squeezes an arbitrary number of bytes from the sponge. -+func (d *state) Read(out []byte) (n int, err error) { -+ // If we're still absorbing, pad and apply the permutation. -+ if d.state == spongeAbsorbing { -+ d.padAndPermute(d.dsbyte) -+ } -+ -+ n = len(out) -+ -+ // Now, do the squeezing. -+ for len(out) > 0 { -+ n := copy(out, d.buf) -+ d.buf = d.buf[n:] -+ out = out[n:] -+ -+ // Apply the permutation if we've squeezed the sponge dry. -+ if len(d.buf) == 0 { -+ d.permute() -+ } -+ } -+ -+ return -+} -+ -+// Sum applies padding to the hash state and then squeezes out the desired -+// number of output bytes. -+func (d *state) Sum(in []byte) []byte { -+ // Make a copy of the original hash so that caller can keep writing -+ // and summing. -+ dup := d.clone() -+ hash := make([]byte, dup.outputLen) -+ dup.Read(hash) -+ return append(in, hash...) -+} -diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go -new file mode 100644 -index 000000000000..4fcfc924ef64 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go -@@ -0,0 +1,285 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package sha3 -+ -+// This file contains code for using the 'compute intermediate -+// message digest' (KIMD) and 'compute last message digest' (KLMD) -+// instructions to compute SHA-3 and SHAKE hashes on IBM Z. -+ -+import ( -+ "hash" -+ -+ "golang.org/x/sys/cpu" -+) -+ -+// codes represent 7-bit KIMD/KLMD function codes as defined in -+// the Principles of Operation. -+type code uint64 -+ -+const ( -+ // function codes for KIMD/KLMD -+ sha3_224 code = 32 -+ sha3_256 = 33 -+ sha3_384 = 34 -+ sha3_512 = 35 -+ shake_128 = 36 -+ shake_256 = 37 -+ nopad = 0x100 -+) -+ -+// kimd is a wrapper for the 'compute intermediate message digest' instruction. -+// src must be a multiple of the rate for the given function code. -+//go:noescape -+func kimd(function code, chain *[200]byte, src []byte) -+ -+// klmd is a wrapper for the 'compute last message digest' instruction. -+// src padding is handled by the instruction. -+//go:noescape -+func klmd(function code, chain *[200]byte, dst, src []byte) -+ -+type asmState struct { -+ a [200]byte // 1600 bit state -+ buf []byte // care must be taken to ensure cap(buf) is a multiple of rate -+ rate int // equivalent to block size -+ storage [3072]byte // underlying storage for buf -+ outputLen int // output length if fixed, 0 if not -+ function code // KIMD/KLMD function code -+ state spongeDirection // whether the sponge is absorbing or squeezing -+} -+ -+func newAsmState(function code) *asmState { -+ var s asmState -+ s.function = function -+ switch function { -+ case sha3_224: -+ s.rate = 144 -+ s.outputLen = 28 -+ case sha3_256: -+ s.rate = 136 -+ s.outputLen = 32 -+ case sha3_384: -+ s.rate = 104 -+ s.outputLen = 48 -+ case sha3_512: -+ s.rate = 72 -+ s.outputLen = 64 -+ case shake_128: -+ s.rate = 168 -+ case shake_256: -+ s.rate = 136 -+ default: -+ panic("sha3: unrecognized function code") -+ } -+ -+ // limit s.buf size to a multiple of s.rate -+ s.resetBuf() -+ return &s -+} -+ -+func (s *asmState) clone() *asmState { -+ c := *s -+ c.buf = c.storage[:len(s.buf):cap(s.buf)] -+ return &c -+} -+ -+// copyIntoBuf copies b into buf. It will panic if there is not enough space to -+// store all of b. -+func (s *asmState) copyIntoBuf(b []byte) { -+ bufLen := len(s.buf) -+ s.buf = s.buf[:len(s.buf)+len(b)] -+ copy(s.buf[bufLen:], b) -+} -+ -+// resetBuf points buf at storage, sets the length to 0 and sets cap to be a -+// multiple of the rate. -+func (s *asmState) resetBuf() { -+ max := (cap(s.storage) / s.rate) * s.rate -+ s.buf = s.storage[:0:max] -+} -+ -+// Write (via the embedded io.Writer interface) adds more data to the running hash. -+// It never returns an error. -+func (s *asmState) Write(b []byte) (int, error) { -+ if s.state != spongeAbsorbing { -+ panic("sha3: write to sponge after read") -+ } -+ length := len(b) -+ for len(b) > 0 { -+ if len(s.buf) == 0 && len(b) >= cap(s.buf) { -+ // Hash the data directly and push any remaining bytes -+ // into the buffer. -+ remainder := len(b) % s.rate -+ kimd(s.function, &s.a, b[:len(b)-remainder]) -+ if remainder != 0 { -+ s.copyIntoBuf(b[len(b)-remainder:]) -+ } -+ return length, nil -+ } -+ -+ if len(s.buf) == cap(s.buf) { -+ // flush the buffer -+ kimd(s.function, &s.a, s.buf) -+ s.buf = s.buf[:0] -+ } -+ -+ // copy as much as we can into the buffer -+ n := len(b) -+ if len(b) > cap(s.buf)-len(s.buf) { -+ n = cap(s.buf) - len(s.buf) -+ } -+ s.copyIntoBuf(b[:n]) -+ b = b[n:] -+ } -+ return length, nil -+} -+ -+// Read squeezes an arbitrary number of bytes from the sponge. -+func (s *asmState) Read(out []byte) (n int, err error) { -+ n = len(out) -+ -+ // need to pad if we were absorbing -+ if s.state == spongeAbsorbing { -+ s.state = spongeSqueezing -+ -+ // write hash directly into out if possible -+ if len(out)%s.rate == 0 { -+ klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 -+ s.buf = s.buf[:0] -+ return -+ } -+ -+ // write hash into buffer -+ max := cap(s.buf) -+ if max > len(out) { -+ max = (len(out)/s.rate)*s.rate + s.rate -+ } -+ klmd(s.function, &s.a, s.buf[:max], s.buf) -+ s.buf = s.buf[:max] -+ } -+ -+ for len(out) > 0 { -+ // flush the buffer -+ if len(s.buf) != 0 { -+ c := copy(out, s.buf) -+ out = out[c:] -+ s.buf = s.buf[c:] -+ continue -+ } -+ -+ // write hash directly into out if possible -+ if len(out)%s.rate == 0 { -+ klmd(s.function|nopad, &s.a, out, nil) -+ return -+ } -+ -+ // write hash into buffer -+ s.resetBuf() -+ if cap(s.buf) > len(out) { -+ s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] -+ } -+ klmd(s.function|nopad, &s.a, s.buf, nil) -+ } -+ return -+} -+ -+// Sum appends the current hash to b and returns the resulting slice. -+// It does not change the underlying hash state. -+func (s *asmState) Sum(b []byte) []byte { -+ if s.outputLen == 0 { -+ panic("sha3: cannot call Sum on SHAKE functions") -+ } -+ -+ // Copy the state to preserve the original. -+ a := s.a -+ -+ // Hash the buffer. Note that we don't clear it because we -+ // aren't updating the state. -+ klmd(s.function, &a, nil, s.buf) -+ return append(b, a[:s.outputLen]...) -+} -+ -+// Reset resets the Hash to its initial state. -+func (s *asmState) Reset() { -+ for i := range s.a { -+ s.a[i] = 0 -+ } -+ s.resetBuf() -+ s.state = spongeAbsorbing -+} -+ -+// Size returns the number of bytes Sum will return. -+func (s *asmState) Size() int { -+ return s.outputLen -+} -+ -+// BlockSize returns the hash's underlying block size. -+// The Write method must be able to accept any amount -+// of data, but it may operate more efficiently if all writes -+// are a multiple of the block size. -+func (s *asmState) BlockSize() int { -+ return s.rate -+} -+ -+// Clone returns a copy of the ShakeHash in its current state. -+func (s *asmState) Clone() ShakeHash { -+ return s.clone() -+} -+ -+// new224Asm returns an assembly implementation of SHA3-224 if available, -+// otherwise it returns nil. -+func new224Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_224) -+ } -+ return nil -+} -+ -+// new256Asm returns an assembly implementation of SHA3-256 if available, -+// otherwise it returns nil. -+func new256Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_256) -+ } -+ return nil -+} -+ -+// new384Asm returns an assembly implementation of SHA3-384 if available, -+// otherwise it returns nil. -+func new384Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_384) -+ } -+ return nil -+} -+ -+// new512Asm returns an assembly implementation of SHA3-512 if available, -+// otherwise it returns nil. -+func new512Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_512) -+ } -+ return nil -+} -+ -+// newShake128Asm returns an assembly implementation of SHAKE-128 if available, -+// otherwise it returns nil. -+func newShake128Asm() ShakeHash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(shake_128) -+ } -+ return nil -+} -+ -+// newShake256Asm returns an assembly implementation of SHAKE-256 if available, -+// otherwise it returns nil. -+func newShake256Asm() ShakeHash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(shake_256) -+ } -+ return nil -+} -diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.s b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s -new file mode 100644 -index 000000000000..a0e051b0451e ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.s -@@ -0,0 +1,34 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+ -+// func kimd(function code, chain *[200]byte, src []byte) -+TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 -+ MOVD function+0(FP), R0 -+ MOVD chain+8(FP), R1 -+ LMG src+16(FP), R2, R3 // R2=base, R3=len -+ -+continue: -+ WORD $0xB93E0002 // KIMD --, R2 -+ BVS continue // continue if interrupted -+ MOVD $0, R0 // reset R0 for pre-go1.8 compilers -+ RET -+ -+// func klmd(function code, chain *[200]byte, dst, src []byte) -+TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 -+ // TODO: SHAKE support -+ MOVD function+0(FP), R0 -+ MOVD chain+8(FP), R1 -+ LMG dst+16(FP), R2, R3 // R2=base, R3=len -+ LMG src+40(FP), R4, R5 // R4=base, R5=len -+ -+continue: -+ WORD $0xB93F0024 // KLMD R2, R4 -+ BVS continue // continue if interrupted -+ MOVD $0, R0 // reset R0 for pre-go1.8 compilers -+ RET -diff --git a/vendor/golang.org/x/crypto/sha3/shake.go b/vendor/golang.org/x/crypto/sha3/shake.go -new file mode 100644 -index 000000000000..d7be2954ab26 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/shake.go -@@ -0,0 +1,173 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+// This file defines the ShakeHash interface, and provides -+// functions for creating SHAKE and cSHAKE instances, as well as utility -+// functions for hashing bytes to arbitrary-length output. -+// -+// -+// SHAKE implementation is based on FIPS PUB 202 [1] -+// cSHAKE implementations is based on NIST SP 800-185 [2] -+// -+// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf -+// [2] https://doi.org/10.6028/NIST.SP.800-185 -+ -+import ( -+ "encoding/binary" -+ "io" -+) -+ -+// ShakeHash defines the interface to hash functions that -+// support arbitrary-length output. -+type ShakeHash interface { -+ // Write absorbs more data into the hash's state. It panics if input is -+ // written to it after output has been read from it. -+ io.Writer -+ -+ // Read reads more output from the hash; reading affects the hash's -+ // state. (ShakeHash.Read is thus very different from Hash.Sum) -+ // It never returns an error. -+ io.Reader -+ -+ // Clone returns a copy of the ShakeHash in its current state. -+ Clone() ShakeHash -+ -+ // Reset resets the ShakeHash to its initial state. -+ Reset() -+} -+ -+// cSHAKE specific context -+type cshakeState struct { -+ *state // SHA-3 state context and Read/Write operations -+ -+ // initBlock is the cSHAKE specific initialization set of bytes. It is initialized -+ // by newCShake function and stores concatenation of N followed by S, encoded -+ // by the method specified in 3.3 of [1]. -+ // It is stored here in order for Reset() to be able to put context into -+ // initial state. -+ initBlock []byte -+} -+ -+// Consts for configuring initial SHA-3 state -+const ( -+ dsbyteShake = 0x1f -+ dsbyteCShake = 0x04 -+ rate128 = 168 -+ rate256 = 136 -+) -+ -+func bytepad(input []byte, w int) []byte { -+ // leftEncode always returns max 9 bytes -+ buf := make([]byte, 0, 9+len(input)+w) -+ buf = append(buf, leftEncode(uint64(w))...) -+ buf = append(buf, input...) -+ padlen := w - (len(buf) % w) -+ return append(buf, make([]byte, padlen)...) -+} -+ -+func leftEncode(value uint64) []byte { -+ var b [9]byte -+ binary.BigEndian.PutUint64(b[1:], value) -+ // Trim all but last leading zero bytes -+ i := byte(1) -+ for i < 8 && b[i] == 0 { -+ i++ -+ } -+ // Prepend number of encoded bytes -+ b[i-1] = 9 - i -+ return b[i-1:] -+} -+ -+func newCShake(N, S []byte, rate int, dsbyte byte) ShakeHash { -+ c := cshakeState{state: &state{rate: rate, dsbyte: dsbyte}} -+ -+ // leftEncode returns max 9 bytes -+ c.initBlock = make([]byte, 0, 9*2+len(N)+len(S)) -+ c.initBlock = append(c.initBlock, leftEncode(uint64(len(N)*8))...) -+ c.initBlock = append(c.initBlock, N...) -+ c.initBlock = append(c.initBlock, leftEncode(uint64(len(S)*8))...) -+ c.initBlock = append(c.initBlock, S...) -+ c.Write(bytepad(c.initBlock, c.rate)) -+ return &c -+} -+ -+// Reset resets the hash to initial state. -+func (c *cshakeState) Reset() { -+ c.state.Reset() -+ c.Write(bytepad(c.initBlock, c.rate)) -+} -+ -+// Clone returns copy of a cSHAKE context within its current state. -+func (c *cshakeState) Clone() ShakeHash { -+ b := make([]byte, len(c.initBlock)) -+ copy(b, c.initBlock) -+ return &cshakeState{state: c.clone(), initBlock: b} -+} -+ -+// Clone returns copy of SHAKE context within its current state. -+func (c *state) Clone() ShakeHash { -+ return c.clone() -+} -+ -+// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. -+// Its generic security strength is 128 bits against all attacks if at -+// least 32 bytes of its output are used. -+func NewShake128() ShakeHash { -+ if h := newShake128Asm(); h != nil { -+ return h -+ } -+ return &state{rate: rate128, dsbyte: dsbyteShake} -+} -+ -+// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. -+// Its generic security strength is 256 bits against all attacks if -+// at least 64 bytes of its output are used. -+func NewShake256() ShakeHash { -+ if h := newShake256Asm(); h != nil { -+ return h -+ } -+ return &state{rate: rate256, dsbyte: dsbyteShake} -+} -+ -+// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash, -+// a customizable variant of SHAKE128. -+// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is -+// desired. S is a customization byte string used for domain separation - two cSHAKE -+// computations on same input with different S yield unrelated outputs. -+// When N and S are both empty, this is equivalent to NewShake128. -+func NewCShake128(N, S []byte) ShakeHash { -+ if len(N) == 0 && len(S) == 0 { -+ return NewShake128() -+ } -+ return newCShake(N, S, rate128, dsbyteCShake) -+} -+ -+// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash, -+// a customizable variant of SHAKE256. -+// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is -+// desired. S is a customization byte string used for domain separation - two cSHAKE -+// computations on same input with different S yield unrelated outputs. -+// When N and S are both empty, this is equivalent to NewShake256. -+func NewCShake256(N, S []byte) ShakeHash { -+ if len(N) == 0 && len(S) == 0 { -+ return NewShake256() -+ } -+ return newCShake(N, S, rate256, dsbyteCShake) -+} -+ -+// ShakeSum128 writes an arbitrary-length digest of data into hash. -+func ShakeSum128(hash, data []byte) { -+ h := NewShake128() -+ h.Write(data) -+ h.Read(hash) -+} -+ -+// ShakeSum256 writes an arbitrary-length digest of data into hash. -+func ShakeSum256(hash, data []byte) { -+ h := NewShake256() -+ h.Write(data) -+ h.Read(hash) -+} -diff --git a/vendor/golang.org/x/crypto/sha3/shake_generic.go b/vendor/golang.org/x/crypto/sha3/shake_generic.go -new file mode 100644 -index 000000000000..5c0710ef98ff ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/shake_generic.go -@@ -0,0 +1,20 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !gc || purego || !s390x -+// +build !gc purego !s390x -+ -+package sha3 -+ -+// newShake128Asm returns an assembly implementation of SHAKE-128 if available, -+// otherwise it returns nil. -+func newShake128Asm() ShakeHash { -+ return nil -+} -+ -+// newShake256Asm returns an assembly implementation of SHAKE-256 if available, -+// otherwise it returns nil. -+func newShake256Asm() ShakeHash { -+ return nil -+} -diff --git a/vendor/golang.org/x/crypto/sha3/xor.go b/vendor/golang.org/x/crypto/sha3/xor.go -new file mode 100644 -index 000000000000..59c8eb94186e ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/xor.go -@@ -0,0 +1,24 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (!amd64 && !386 && !ppc64le) || purego -+// +build !amd64,!386,!ppc64le purego -+ -+package sha3 -+ -+// A storageBuf is an aligned array of maxRate bytes. -+type storageBuf [maxRate]byte -+ -+func (b *storageBuf) asBytes() *[maxRate]byte { -+ return (*[maxRate]byte)(b) -+} -+ -+var ( -+ xorIn = xorInGeneric -+ copyOut = copyOutGeneric -+ xorInUnaligned = xorInGeneric -+ copyOutUnaligned = copyOutGeneric -+) -+ -+const xorImplementationUnaligned = "generic" -diff --git a/vendor/golang.org/x/crypto/sha3/xor_generic.go b/vendor/golang.org/x/crypto/sha3/xor_generic.go -new file mode 100644 -index 000000000000..8d947711272c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/xor_generic.go -@@ -0,0 +1,28 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+import "encoding/binary" -+ -+// xorInGeneric xors the bytes in buf into the state; it -+// makes no non-portable assumptions about memory layout -+// or alignment. -+func xorInGeneric(d *state, buf []byte) { -+ n := len(buf) / 8 -+ -+ for i := 0; i < n; i++ { -+ a := binary.LittleEndian.Uint64(buf) -+ d.a[i] ^= a -+ buf = buf[8:] -+ } -+} -+ -+// copyOutGeneric copies uint64s to a byte buffer. -+func copyOutGeneric(d *state, b []byte) { -+ for i := 0; len(b) >= 8; i++ { -+ binary.LittleEndian.PutUint64(b, d.a[i]) -+ b = b[8:] -+ } -+} -diff --git a/vendor/golang.org/x/crypto/sha3/xor_unaligned.go b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go -new file mode 100644 -index 000000000000..1ce606246d5c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go -@@ -0,0 +1,68 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (amd64 || 386 || ppc64le) && !purego -+// +build amd64 386 ppc64le -+// +build !purego -+ -+package sha3 -+ -+import "unsafe" -+ -+// A storageBuf is an aligned array of maxRate bytes. -+type storageBuf [maxRate / 8]uint64 -+ -+func (b *storageBuf) asBytes() *[maxRate]byte { -+ return (*[maxRate]byte)(unsafe.Pointer(b)) -+} -+ -+// xorInUnaligned uses unaligned reads and writes to update d.a to contain d.a -+// XOR buf. -+func xorInUnaligned(d *state, buf []byte) { -+ n := len(buf) -+ bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] -+ if n >= 72 { -+ d.a[0] ^= bw[0] -+ d.a[1] ^= bw[1] -+ d.a[2] ^= bw[2] -+ d.a[3] ^= bw[3] -+ d.a[4] ^= bw[4] -+ d.a[5] ^= bw[5] -+ d.a[6] ^= bw[6] -+ d.a[7] ^= bw[7] -+ d.a[8] ^= bw[8] -+ } -+ if n >= 104 { -+ d.a[9] ^= bw[9] -+ d.a[10] ^= bw[10] -+ d.a[11] ^= bw[11] -+ d.a[12] ^= bw[12] -+ } -+ if n >= 136 { -+ d.a[13] ^= bw[13] -+ d.a[14] ^= bw[14] -+ d.a[15] ^= bw[15] -+ d.a[16] ^= bw[16] -+ } -+ if n >= 144 { -+ d.a[17] ^= bw[17] -+ } -+ if n >= 168 { -+ d.a[18] ^= bw[18] -+ d.a[19] ^= bw[19] -+ d.a[20] ^= bw[20] -+ } -+} -+ -+func copyOutUnaligned(d *state, buf []byte) { -+ ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) -+ copy(buf, ab[:]) -+} -+ -+var ( -+ xorIn = xorInUnaligned -+ copyOut = copyOutUnaligned -+) -+ -+const xorImplementationUnaligned = "unaligned" -diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go -new file mode 100644 -index 000000000000..3cfe723d2998 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ssh/agent/client.go -@@ -0,0 +1,819 @@ -+// Copyright 2012 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 agent implements the ssh-agent protocol, and provides both -+// a client and a server. The client can talk to a standard ssh-agent -+// that uses UNIX sockets, and one could implement an alternative -+// ssh-agent process using the sample server. -+// -+// References: -+// [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00 -+package agent // import "golang.org/x/crypto/ssh/agent" -+ -+import ( -+ "bytes" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "encoding/base64" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "math/big" -+ "sync" -+ -+ "golang.org/x/crypto/ed25519" -+ "golang.org/x/crypto/ssh" -+) -+ -+// SignatureFlags represent additional flags that can be passed to the signature -+// requests an defined in [PROTOCOL.agent] section 4.5.1. -+type SignatureFlags uint32 -+ -+// SignatureFlag values as defined in [PROTOCOL.agent] section 5.3. -+const ( -+ SignatureFlagReserved SignatureFlags = 1 << iota -+ SignatureFlagRsaSha256 -+ SignatureFlagRsaSha512 -+) -+ -+// Agent represents the capabilities of an ssh-agent. -+type Agent interface { -+ // List returns the identities known to the agent. -+ List() ([]*Key, error) -+ -+ // Sign has the agent sign the data using a protocol 2 key as defined -+ // in [PROTOCOL.agent] section 2.6.2. -+ Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) -+ -+ // Add adds a private key to the agent. -+ Add(key AddedKey) error -+ -+ // Remove removes all identities with the given public key. -+ Remove(key ssh.PublicKey) error -+ -+ // RemoveAll removes all identities. -+ RemoveAll() error -+ -+ // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. -+ Lock(passphrase []byte) error -+ -+ // Unlock undoes the effect of Lock -+ Unlock(passphrase []byte) error -+ -+ // Signers returns signers for all the known keys. -+ Signers() ([]ssh.Signer, error) -+} -+ -+type ExtendedAgent interface { -+ Agent -+ -+ // SignWithFlags signs like Sign, but allows for additional flags to be sent/received -+ SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) -+ -+ // Extension processes a custom extension request. Standard-compliant agents are not -+ // required to support any extensions, but this method allows agents to implement -+ // vendor-specific methods or add experimental features. See [PROTOCOL.agent] section 4.7. -+ // If agent extensions are unsupported entirely this method MUST return an -+ // ErrExtensionUnsupported error. Similarly, if just the specific extensionType in -+ // the request is unsupported by the agent then ErrExtensionUnsupported MUST be -+ // returned. -+ // -+ // In the case of success, since [PROTOCOL.agent] section 4.7 specifies that the contents -+ // of the response are unspecified (including the type of the message), the complete -+ // response will be returned as a []byte slice, including the "type" byte of the message. -+ Extension(extensionType string, contents []byte) ([]byte, error) -+} -+ -+// ConstraintExtension describes an optional constraint defined by users. -+type ConstraintExtension struct { -+ // ExtensionName consist of a UTF-8 string suffixed by the -+ // implementation domain following the naming scheme defined -+ // in Section 4.2 of [RFC4251], e.g. "foo@example.com". -+ ExtensionName string -+ // ExtensionDetails contains the actual content of the extended -+ // constraint. -+ ExtensionDetails []byte -+} -+ -+// AddedKey describes an SSH key to be added to an Agent. -+type AddedKey struct { -+ // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey, -+ // ed25519.PrivateKey or *ecdsa.PrivateKey, which will be inserted into the -+ // agent. -+ PrivateKey interface{} -+ // Certificate, if not nil, is communicated to the agent and will be -+ // stored with the key. -+ Certificate *ssh.Certificate -+ // Comment is an optional, free-form string. -+ Comment string -+ // LifetimeSecs, if not zero, is the number of seconds that the -+ // agent will store the key for. -+ LifetimeSecs uint32 -+ // ConfirmBeforeUse, if true, requests that the agent confirm with the -+ // user before each use of this key. -+ ConfirmBeforeUse bool -+ // ConstraintExtensions are the experimental or private-use constraints -+ // defined by users. -+ ConstraintExtensions []ConstraintExtension -+} -+ -+// See [PROTOCOL.agent], section 3. -+const ( -+ agentRequestV1Identities = 1 -+ agentRemoveAllV1Identities = 9 -+ -+ // 3.2 Requests from client to agent for protocol 2 key operations -+ agentAddIdentity = 17 -+ agentRemoveIdentity = 18 -+ agentRemoveAllIdentities = 19 -+ agentAddIDConstrained = 25 -+ -+ // 3.3 Key-type independent requests from client to agent -+ agentAddSmartcardKey = 20 -+ agentRemoveSmartcardKey = 21 -+ agentLock = 22 -+ agentUnlock = 23 -+ agentAddSmartcardKeyConstrained = 26 -+ -+ // 3.7 Key constraint identifiers -+ agentConstrainLifetime = 1 -+ agentConstrainConfirm = 2 -+ agentConstrainExtension = 3 -+) -+ -+// maxAgentResponseBytes is the maximum agent reply size that is accepted. This -+// is a sanity check, not a limit in the spec. -+const maxAgentResponseBytes = 16 << 20 -+ -+// Agent messages: -+// These structures mirror the wire format of the corresponding ssh agent -+// messages found in [PROTOCOL.agent]. -+ -+// 3.4 Generic replies from agent to client -+const agentFailure = 5 -+ -+type failureAgentMsg struct{} -+ -+const agentSuccess = 6 -+ -+type successAgentMsg struct{} -+ -+// See [PROTOCOL.agent], section 2.5.2. -+const agentRequestIdentities = 11 -+ -+type requestIdentitiesAgentMsg struct{} -+ -+// See [PROTOCOL.agent], section 2.5.2. -+const agentIdentitiesAnswer = 12 -+ -+type identitiesAnswerAgentMsg struct { -+ NumKeys uint32 `sshtype:"12"` -+ Keys []byte `ssh:"rest"` -+} -+ -+// See [PROTOCOL.agent], section 2.6.2. -+const agentSignRequest = 13 -+ -+type signRequestAgentMsg struct { -+ KeyBlob []byte `sshtype:"13"` -+ Data []byte -+ Flags uint32 -+} -+ -+// See [PROTOCOL.agent], section 2.6.2. -+ -+// 3.6 Replies from agent to client for protocol 2 key operations -+const agentSignResponse = 14 -+ -+type signResponseAgentMsg struct { -+ SigBlob []byte `sshtype:"14"` -+} -+ -+type publicKey struct { -+ Format string -+ Rest []byte `ssh:"rest"` -+} -+ -+// 3.7 Key constraint identifiers -+type constrainLifetimeAgentMsg struct { -+ LifetimeSecs uint32 `sshtype:"1"` -+} -+ -+type constrainExtensionAgentMsg struct { -+ ExtensionName string `sshtype:"3"` -+ ExtensionDetails []byte -+ -+ // Rest is a field used for parsing, not part of message -+ Rest []byte `ssh:"rest"` -+} -+ -+// See [PROTOCOL.agent], section 4.7 -+const agentExtension = 27 -+const agentExtensionFailure = 28 -+ -+// ErrExtensionUnsupported indicates that an extension defined in -+// [PROTOCOL.agent] section 4.7 is unsupported by the agent. Specifically this -+// error indicates that the agent returned a standard SSH_AGENT_FAILURE message -+// as the result of a SSH_AGENTC_EXTENSION request. Note that the protocol -+// specification (and therefore this error) does not distinguish between a -+// specific extension being unsupported and extensions being unsupported entirely. -+var ErrExtensionUnsupported = errors.New("agent: extension unsupported") -+ -+type extensionAgentMsg struct { -+ ExtensionType string `sshtype:"27"` -+ Contents []byte -+} -+ -+// Key represents a protocol 2 public key as defined in -+// [PROTOCOL.agent], section 2.5.2. -+type Key struct { -+ Format string -+ Blob []byte -+ Comment string -+} -+ -+func clientErr(err error) error { -+ return fmt.Errorf("agent: client error: %v", err) -+} -+ -+// String returns the storage form of an agent key with the format, base64 -+// encoded serialized key, and the comment if it is not empty. -+func (k *Key) String() string { -+ s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob) -+ -+ if k.Comment != "" { -+ s += " " + k.Comment -+ } -+ -+ return s -+} -+ -+// Type returns the public key type. -+func (k *Key) Type() string { -+ return k.Format -+} -+ -+// Marshal returns key blob to satisfy the ssh.PublicKey interface. -+func (k *Key) Marshal() []byte { -+ return k.Blob -+} -+ -+// Verify satisfies the ssh.PublicKey interface. -+func (k *Key) Verify(data []byte, sig *ssh.Signature) error { -+ pubKey, err := ssh.ParsePublicKey(k.Blob) -+ if err != nil { -+ return fmt.Errorf("agent: bad public key: %v", err) -+ } -+ return pubKey.Verify(data, sig) -+} -+ -+type wireKey struct { -+ Format string -+ Rest []byte `ssh:"rest"` -+} -+ -+func parseKey(in []byte) (out *Key, rest []byte, err error) { -+ var record struct { -+ Blob []byte -+ Comment string -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := ssh.Unmarshal(in, &record); err != nil { -+ return nil, nil, err -+ } -+ -+ var wk wireKey -+ if err := ssh.Unmarshal(record.Blob, &wk); err != nil { -+ return nil, nil, err -+ } -+ -+ return &Key{ -+ Format: wk.Format, -+ Blob: record.Blob, -+ Comment: record.Comment, -+ }, record.Rest, nil -+} -+ -+// client is a client for an ssh-agent process. -+type client struct { -+ // conn is typically a *net.UnixConn -+ conn io.ReadWriter -+ // mu is used to prevent concurrent access to the agent -+ mu sync.Mutex -+} -+ -+// NewClient returns an Agent that talks to an ssh-agent process over -+// the given connection. -+func NewClient(rw io.ReadWriter) ExtendedAgent { -+ return &client{conn: rw} -+} -+ -+// call sends an RPC to the agent. On success, the reply is -+// unmarshaled into reply and replyType is set to the first byte of -+// the reply, which contains the type of the message. -+func (c *client) call(req []byte) (reply interface{}, err error) { -+ buf, err := c.callRaw(req) -+ if err != nil { -+ return nil, err -+ } -+ reply, err = unmarshal(buf) -+ if err != nil { -+ return nil, clientErr(err) -+ } -+ return reply, nil -+} -+ -+// callRaw sends an RPC to the agent. On success, the raw -+// bytes of the response are returned; no unmarshalling is -+// performed on the response. -+func (c *client) callRaw(req []byte) (reply []byte, err error) { -+ c.mu.Lock() -+ defer c.mu.Unlock() -+ -+ msg := make([]byte, 4+len(req)) -+ binary.BigEndian.PutUint32(msg, uint32(len(req))) -+ copy(msg[4:], req) -+ if _, err = c.conn.Write(msg); err != nil { -+ return nil, clientErr(err) -+ } -+ -+ var respSizeBuf [4]byte -+ if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil { -+ return nil, clientErr(err) -+ } -+ respSize := binary.BigEndian.Uint32(respSizeBuf[:]) -+ if respSize > maxAgentResponseBytes { -+ return nil, clientErr(errors.New("response too large")) -+ } -+ -+ buf := make([]byte, respSize) -+ if _, err = io.ReadFull(c.conn, buf); err != nil { -+ return nil, clientErr(err) -+ } -+ return buf, nil -+} -+ -+func (c *client) simpleCall(req []byte) error { -+ resp, err := c.call(req) -+ if err != nil { -+ return err -+ } -+ if _, ok := resp.(*successAgentMsg); ok { -+ return nil -+ } -+ return errors.New("agent: failure") -+} -+ -+func (c *client) RemoveAll() error { -+ return c.simpleCall([]byte{agentRemoveAllIdentities}) -+} -+ -+func (c *client) Remove(key ssh.PublicKey) error { -+ req := ssh.Marshal(&agentRemoveIdentityMsg{ -+ KeyBlob: key.Marshal(), -+ }) -+ return c.simpleCall(req) -+} -+ -+func (c *client) Lock(passphrase []byte) error { -+ req := ssh.Marshal(&agentLockMsg{ -+ Passphrase: passphrase, -+ }) -+ return c.simpleCall(req) -+} -+ -+func (c *client) Unlock(passphrase []byte) error { -+ req := ssh.Marshal(&agentUnlockMsg{ -+ Passphrase: passphrase, -+ }) -+ return c.simpleCall(req) -+} -+ -+// List returns the identities known to the agent. -+func (c *client) List() ([]*Key, error) { -+ // see [PROTOCOL.agent] section 2.5.2. -+ req := []byte{agentRequestIdentities} -+ -+ msg, err := c.call(req) -+ if err != nil { -+ return nil, err -+ } -+ -+ switch msg := msg.(type) { -+ case *identitiesAnswerAgentMsg: -+ if msg.NumKeys > maxAgentResponseBytes/8 { -+ return nil, errors.New("agent: too many keys in agent reply") -+ } -+ keys := make([]*Key, msg.NumKeys) -+ data := msg.Keys -+ for i := uint32(0); i < msg.NumKeys; i++ { -+ var key *Key -+ var err error -+ if key, data, err = parseKey(data); err != nil { -+ return nil, err -+ } -+ keys[i] = key -+ } -+ return keys, nil -+ case *failureAgentMsg: -+ return nil, errors.New("agent: failed to list keys") -+ } -+ panic("unreachable") -+} -+ -+// Sign has the agent sign the data using a protocol 2 key as defined -+// in [PROTOCOL.agent] section 2.6.2. -+func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { -+ return c.SignWithFlags(key, data, 0) -+} -+ -+func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) { -+ req := ssh.Marshal(signRequestAgentMsg{ -+ KeyBlob: key.Marshal(), -+ Data: data, -+ Flags: uint32(flags), -+ }) -+ -+ msg, err := c.call(req) -+ if err != nil { -+ return nil, err -+ } -+ -+ switch msg := msg.(type) { -+ case *signResponseAgentMsg: -+ var sig ssh.Signature -+ if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil { -+ return nil, err -+ } -+ -+ return &sig, nil -+ case *failureAgentMsg: -+ return nil, errors.New("agent: failed to sign challenge") -+ } -+ panic("unreachable") -+} -+ -+// unmarshal parses an agent message in packet, returning the parsed -+// form and the message type of packet. -+func unmarshal(packet []byte) (interface{}, error) { -+ if len(packet) < 1 { -+ return nil, errors.New("agent: empty packet") -+ } -+ var msg interface{} -+ switch packet[0] { -+ case agentFailure: -+ return new(failureAgentMsg), nil -+ case agentSuccess: -+ return new(successAgentMsg), nil -+ case agentIdentitiesAnswer: -+ msg = new(identitiesAnswerAgentMsg) -+ case agentSignResponse: -+ msg = new(signResponseAgentMsg) -+ case agentV1IdentitiesAnswer: -+ msg = new(agentV1IdentityMsg) -+ default: -+ return nil, fmt.Errorf("agent: unknown type tag %d", packet[0]) -+ } -+ if err := ssh.Unmarshal(packet, msg); err != nil { -+ return nil, err -+ } -+ return msg, nil -+} -+ -+type rsaKeyMsg struct { -+ Type string `sshtype:"17|25"` -+ N *big.Int -+ E *big.Int -+ D *big.Int -+ Iqmp *big.Int // IQMP = Inverse Q Mod P -+ P *big.Int -+ Q *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type dsaKeyMsg struct { -+ Type string `sshtype:"17|25"` -+ P *big.Int -+ Q *big.Int -+ G *big.Int -+ Y *big.Int -+ X *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ecdsaKeyMsg struct { -+ Type string `sshtype:"17|25"` -+ Curve string -+ KeyBytes []byte -+ D *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ed25519KeyMsg struct { -+ Type string `sshtype:"17|25"` -+ Pub []byte -+ Priv []byte -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+// Insert adds a private key to the agent. -+func (c *client) insertKey(s interface{}, comment string, constraints []byte) error { -+ var req []byte -+ switch k := s.(type) { -+ case *rsa.PrivateKey: -+ if len(k.Primes) != 2 { -+ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) -+ } -+ k.Precompute() -+ req = ssh.Marshal(rsaKeyMsg{ -+ Type: ssh.KeyAlgoRSA, -+ N: k.N, -+ E: big.NewInt(int64(k.E)), -+ D: k.D, -+ Iqmp: k.Precomputed.Qinv, -+ P: k.Primes[0], -+ Q: k.Primes[1], -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *dsa.PrivateKey: -+ req = ssh.Marshal(dsaKeyMsg{ -+ Type: ssh.KeyAlgoDSA, -+ P: k.P, -+ Q: k.Q, -+ G: k.G, -+ Y: k.Y, -+ X: k.X, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *ecdsa.PrivateKey: -+ nistID := fmt.Sprintf("nistp%d", k.Params().BitSize) -+ req = ssh.Marshal(ecdsaKeyMsg{ -+ Type: "ecdsa-sha2-" + nistID, -+ Curve: nistID, -+ KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y), -+ D: k.D, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519KeyMsg{ -+ Type: ssh.KeyAlgoED25519, -+ Pub: []byte(k)[32:], -+ Priv: []byte(k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ // This function originally supported only *ed25519.PrivateKey, however the -+ // general idiom is to pass ed25519.PrivateKey by value, not by pointer. -+ // We still support the pointer variant for backwards compatibility. -+ case *ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519KeyMsg{ -+ Type: ssh.KeyAlgoED25519, -+ Pub: []byte(*k)[32:], -+ Priv: []byte(*k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ default: -+ return fmt.Errorf("agent: unsupported key type %T", s) -+ } -+ -+ // if constraints are present then the message type needs to be changed. -+ if len(constraints) != 0 { -+ req[0] = agentAddIDConstrained -+ } -+ -+ resp, err := c.call(req) -+ if err != nil { -+ return err -+ } -+ if _, ok := resp.(*successAgentMsg); ok { -+ return nil -+ } -+ return errors.New("agent: failure") -+} -+ -+type rsaCertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ D *big.Int -+ Iqmp *big.Int // IQMP = Inverse Q Mod P -+ P *big.Int -+ Q *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type dsaCertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ X *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ecdsaCertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ D *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ed25519CertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ Pub []byte -+ Priv []byte -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+// Add adds a private key to the agent. If a certificate is given, -+// that certificate is added instead as public key. -+func (c *client) Add(key AddedKey) error { -+ var constraints []byte -+ -+ if secs := key.LifetimeSecs; secs != 0 { -+ constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...) -+ } -+ -+ if key.ConfirmBeforeUse { -+ constraints = append(constraints, agentConstrainConfirm) -+ } -+ -+ cert := key.Certificate -+ if cert == nil { -+ return c.insertKey(key.PrivateKey, key.Comment, constraints) -+ } -+ return c.insertCert(key.PrivateKey, cert, key.Comment, constraints) -+} -+ -+func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error { -+ var req []byte -+ switch k := s.(type) { -+ case *rsa.PrivateKey: -+ if len(k.Primes) != 2 { -+ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) -+ } -+ k.Precompute() -+ req = ssh.Marshal(rsaCertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ D: k.D, -+ Iqmp: k.Precomputed.Qinv, -+ P: k.Primes[0], -+ Q: k.Primes[1], -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *dsa.PrivateKey: -+ req = ssh.Marshal(dsaCertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ X: k.X, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *ecdsa.PrivateKey: -+ req = ssh.Marshal(ecdsaCertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ D: k.D, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519CertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ Pub: []byte(k)[32:], -+ Priv: []byte(k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ // This function originally supported only *ed25519.PrivateKey, however the -+ // general idiom is to pass ed25519.PrivateKey by value, not by pointer. -+ // We still support the pointer variant for backwards compatibility. -+ case *ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519CertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ Pub: []byte(*k)[32:], -+ Priv: []byte(*k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ default: -+ return fmt.Errorf("agent: unsupported key type %T", s) -+ } -+ -+ // if constraints are present then the message type needs to be changed. -+ if len(constraints) != 0 { -+ req[0] = agentAddIDConstrained -+ } -+ -+ signer, err := ssh.NewSignerFromKey(s) -+ if err != nil { -+ return err -+ } -+ if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { -+ return errors.New("agent: signer and cert have different public key") -+ } -+ -+ resp, err := c.call(req) -+ if err != nil { -+ return err -+ } -+ if _, ok := resp.(*successAgentMsg); ok { -+ return nil -+ } -+ return errors.New("agent: failure") -+} -+ -+// Signers provides a callback for client authentication. -+func (c *client) Signers() ([]ssh.Signer, error) { -+ keys, err := c.List() -+ if err != nil { -+ return nil, err -+ } -+ -+ var result []ssh.Signer -+ for _, k := range keys { -+ result = append(result, &agentKeyringSigner{c, k}) -+ } -+ return result, nil -+} -+ -+type agentKeyringSigner struct { -+ agent *client -+ pub ssh.PublicKey -+} -+ -+func (s *agentKeyringSigner) PublicKey() ssh.PublicKey { -+ return s.pub -+} -+ -+func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) { -+ // The agent has its own entropy source, so the rand argument is ignored. -+ return s.agent.Sign(s.pub, data) -+} -+ -+func (s *agentKeyringSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*ssh.Signature, error) { -+ if algorithm == "" || algorithm == s.pub.Type() { -+ return s.Sign(rand, data) -+ } -+ -+ var flags SignatureFlags -+ switch algorithm { -+ case ssh.KeyAlgoRSASHA256: -+ flags = SignatureFlagRsaSha256 -+ case ssh.KeyAlgoRSASHA512: -+ flags = SignatureFlagRsaSha512 -+ default: -+ return nil, fmt.Errorf("agent: unsupported algorithm %q", algorithm) -+ } -+ -+ return s.agent.SignWithFlags(s.pub, data, flags) -+} -+ -+var _ ssh.AlgorithmSigner = &agentKeyringSigner{} -+ -+// Calls an extension method. It is up to the agent implementation as to whether or not -+// any particular extension is supported and may always return an error. Because the -+// type of the response is up to the implementation, this returns the bytes of the -+// response and does not attempt any type of unmarshalling. -+func (c *client) Extension(extensionType string, contents []byte) ([]byte, error) { -+ req := ssh.Marshal(extensionAgentMsg{ -+ ExtensionType: extensionType, -+ Contents: contents, -+ }) -+ buf, err := c.callRaw(req) -+ if err != nil { -+ return nil, err -+ } -+ if len(buf) == 0 { -+ return nil, errors.New("agent: failure; empty response") -+ } -+ // [PROTOCOL.agent] section 4.7 indicates that an SSH_AGENT_FAILURE message -+ // represents an agent that does not support the extension -+ if buf[0] == agentFailure { -+ return nil, ErrExtensionUnsupported -+ } -+ if buf[0] == agentExtensionFailure { -+ return nil, errors.New("agent: generic extension failure") -+ } -+ -+ return buf, nil -+} -diff --git a/vendor/golang.org/x/crypto/ssh/agent/forward.go b/vendor/golang.org/x/crypto/ssh/agent/forward.go -new file mode 100644 -index 000000000000..fd24ba900d25 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ssh/agent/forward.go -@@ -0,0 +1,103 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import ( -+ "errors" -+ "io" -+ "net" -+ "sync" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+// RequestAgentForwarding sets up agent forwarding for the session. -+// ForwardToAgent or ForwardToRemote should be called to route -+// the authentication requests. -+func RequestAgentForwarding(session *ssh.Session) error { -+ ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil) -+ if err != nil { -+ return err -+ } -+ if !ok { -+ return errors.New("forwarding request denied") -+ } -+ return nil -+} -+ -+// ForwardToAgent routes authentication requests to the given keyring. -+func ForwardToAgent(client *ssh.Client, keyring Agent) error { -+ channels := client.HandleChannelOpen(channelType) -+ if channels == nil { -+ return errors.New("agent: already have handler for " + channelType) -+ } -+ -+ go func() { -+ for ch := range channels { -+ channel, reqs, err := ch.Accept() -+ if err != nil { -+ continue -+ } -+ go ssh.DiscardRequests(reqs) -+ go func() { -+ ServeAgent(keyring, channel) -+ channel.Close() -+ }() -+ } -+ }() -+ return nil -+} -+ -+const channelType = "auth-agent@openssh.com" -+ -+// ForwardToRemote routes authentication requests to the ssh-agent -+// process serving on the given unix socket. -+func ForwardToRemote(client *ssh.Client, addr string) error { -+ channels := client.HandleChannelOpen(channelType) -+ if channels == nil { -+ return errors.New("agent: already have handler for " + channelType) -+ } -+ conn, err := net.Dial("unix", addr) -+ if err != nil { -+ return err -+ } -+ conn.Close() -+ -+ go func() { -+ for ch := range channels { -+ channel, reqs, err := ch.Accept() -+ if err != nil { -+ continue -+ } -+ go ssh.DiscardRequests(reqs) -+ go forwardUnixSocket(channel, addr) -+ } -+ }() -+ return nil -+} -+ -+func forwardUnixSocket(channel ssh.Channel, addr string) { -+ conn, err := net.Dial("unix", addr) -+ if err != nil { -+ return -+ } -+ -+ var wg sync.WaitGroup -+ wg.Add(2) -+ go func() { -+ io.Copy(conn, channel) -+ conn.(*net.UnixConn).CloseWrite() -+ wg.Done() -+ }() -+ go func() { -+ io.Copy(channel, conn) -+ channel.CloseWrite() -+ wg.Done() -+ }() -+ -+ wg.Wait() -+ conn.Close() -+ channel.Close() -+} -diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go -new file mode 100644 -index 000000000000..21bfa870fa4d ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go -@@ -0,0 +1,241 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "crypto/subtle" -+ "errors" -+ "fmt" -+ "sync" -+ "time" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+type privKey struct { -+ signer ssh.Signer -+ comment string -+ expire *time.Time -+} -+ -+type keyring struct { -+ mu sync.Mutex -+ keys []privKey -+ -+ locked bool -+ passphrase []byte -+} -+ -+var errLocked = errors.New("agent: locked") -+ -+// NewKeyring returns an Agent that holds keys in memory. It is safe -+// for concurrent use by multiple goroutines. -+func NewKeyring() Agent { -+ return &keyring{} -+} -+ -+// RemoveAll removes all identities. -+func (r *keyring) RemoveAll() error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ -+ r.keys = nil -+ return nil -+} -+ -+// removeLocked does the actual key removal. The caller must already be holding the -+// keyring mutex. -+func (r *keyring) removeLocked(want []byte) error { -+ found := false -+ for i := 0; i < len(r.keys); { -+ if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { -+ found = true -+ r.keys[i] = r.keys[len(r.keys)-1] -+ r.keys = r.keys[:len(r.keys)-1] -+ continue -+ } else { -+ i++ -+ } -+ } -+ -+ if !found { -+ return errors.New("agent: key not found") -+ } -+ return nil -+} -+ -+// Remove removes all identities with the given public key. -+func (r *keyring) Remove(key ssh.PublicKey) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ -+ return r.removeLocked(key.Marshal()) -+} -+ -+// Lock locks the agent. Sign and Remove will fail, and List will return an empty list. -+func (r *keyring) Lock(passphrase []byte) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ -+ r.locked = true -+ r.passphrase = passphrase -+ return nil -+} -+ -+// Unlock undoes the effect of Lock -+func (r *keyring) Unlock(passphrase []byte) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if !r.locked { -+ return errors.New("agent: not locked") -+ } -+ if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { -+ return fmt.Errorf("agent: incorrect passphrase") -+ } -+ -+ r.locked = false -+ r.passphrase = nil -+ return nil -+} -+ -+// expireKeysLocked removes expired keys from the keyring. If a key was added -+// with a lifetimesecs contraint and seconds >= lifetimesecs seconds have -+// elapsed, it is removed. The caller *must* be holding the keyring mutex. -+func (r *keyring) expireKeysLocked() { -+ for _, k := range r.keys { -+ if k.expire != nil && time.Now().After(*k.expire) { -+ r.removeLocked(k.signer.PublicKey().Marshal()) -+ } -+ } -+} -+ -+// List returns the identities known to the agent. -+func (r *keyring) List() ([]*Key, error) { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ // section 2.7: locked agents return empty. -+ return nil, nil -+ } -+ -+ r.expireKeysLocked() -+ var ids []*Key -+ for _, k := range r.keys { -+ pub := k.signer.PublicKey() -+ ids = append(ids, &Key{ -+ Format: pub.Type(), -+ Blob: pub.Marshal(), -+ Comment: k.comment}) -+ } -+ return ids, nil -+} -+ -+// Insert adds a private key to the keyring. If a certificate -+// is given, that certificate is added as public key. Note that -+// any constraints given are ignored. -+func (r *keyring) Add(key AddedKey) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ signer, err := ssh.NewSignerFromKey(key.PrivateKey) -+ -+ if err != nil { -+ return err -+ } -+ -+ if cert := key.Certificate; cert != nil { -+ signer, err = ssh.NewCertSigner(cert, signer) -+ if err != nil { -+ return err -+ } -+ } -+ -+ p := privKey{ -+ signer: signer, -+ comment: key.Comment, -+ } -+ -+ if key.LifetimeSecs > 0 { -+ t := time.Now().Add(time.Duration(key.LifetimeSecs) * time.Second) -+ p.expire = &t -+ } -+ -+ r.keys = append(r.keys, p) -+ -+ return nil -+} -+ -+// Sign returns a signature for the data. -+func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { -+ return r.SignWithFlags(key, data, 0) -+} -+ -+func (r *keyring) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return nil, errLocked -+ } -+ -+ r.expireKeysLocked() -+ wanted := key.Marshal() -+ for _, k := range r.keys { -+ if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { -+ if flags == 0 { -+ return k.signer.Sign(rand.Reader, data) -+ } else { -+ if algorithmSigner, ok := k.signer.(ssh.AlgorithmSigner); !ok { -+ return nil, fmt.Errorf("agent: signature does not support non-default signature algorithm: %T", k.signer) -+ } else { -+ var algorithm string -+ switch flags { -+ case SignatureFlagRsaSha256: -+ algorithm = ssh.KeyAlgoRSASHA256 -+ case SignatureFlagRsaSha512: -+ algorithm = ssh.KeyAlgoRSASHA512 -+ default: -+ return nil, fmt.Errorf("agent: unsupported signature flags: %d", flags) -+ } -+ return algorithmSigner.SignWithAlgorithm(rand.Reader, data, algorithm) -+ } -+ } -+ } -+ } -+ return nil, errors.New("not found") -+} -+ -+// Signers returns signers for all the known keys. -+func (r *keyring) Signers() ([]ssh.Signer, error) { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return nil, errLocked -+ } -+ -+ r.expireKeysLocked() -+ s := make([]ssh.Signer, 0, len(r.keys)) -+ for _, k := range r.keys { -+ s = append(s, k.signer) -+ } -+ return s, nil -+} -+ -+// The keyring does not support any extensions -+func (r *keyring) Extension(extensionType string, contents []byte) ([]byte, error) { -+ return nil, ErrExtensionUnsupported -+} -diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go -new file mode 100644 -index 000000000000..6e7a1e02f27b ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ssh/agent/server.go -@@ -0,0 +1,570 @@ -+// Copyright 2012 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 agent -+ -+import ( -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "log" -+ "math/big" -+ -+ "golang.org/x/crypto/ed25519" -+ "golang.org/x/crypto/ssh" -+) -+ -+// Server wraps an Agent and uses it to implement the agent side of -+// the SSH-agent, wire protocol. -+type server struct { -+ agent Agent -+} -+ -+func (s *server) processRequestBytes(reqData []byte) []byte { -+ rep, err := s.processRequest(reqData) -+ if err != nil { -+ if err != errLocked { -+ // TODO(hanwen): provide better logging interface? -+ log.Printf("agent %d: %v", reqData[0], err) -+ } -+ return []byte{agentFailure} -+ } -+ -+ if err == nil && rep == nil { -+ return []byte{agentSuccess} -+ } -+ -+ return ssh.Marshal(rep) -+} -+ -+func marshalKey(k *Key) []byte { -+ var record struct { -+ Blob []byte -+ Comment string -+ } -+ record.Blob = k.Marshal() -+ record.Comment = k.Comment -+ -+ return ssh.Marshal(&record) -+} -+ -+// See [PROTOCOL.agent], section 2.5.1. -+const agentV1IdentitiesAnswer = 2 -+ -+type agentV1IdentityMsg struct { -+ Numkeys uint32 `sshtype:"2"` -+} -+ -+type agentRemoveIdentityMsg struct { -+ KeyBlob []byte `sshtype:"18"` -+} -+ -+type agentLockMsg struct { -+ Passphrase []byte `sshtype:"22"` -+} -+ -+type agentUnlockMsg struct { -+ Passphrase []byte `sshtype:"23"` -+} -+ -+func (s *server) processRequest(data []byte) (interface{}, error) { -+ switch data[0] { -+ case agentRequestV1Identities: -+ return &agentV1IdentityMsg{0}, nil -+ -+ case agentRemoveAllV1Identities: -+ return nil, nil -+ -+ case agentRemoveIdentity: -+ var req agentRemoveIdentityMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ -+ var wk wireKey -+ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { -+ return nil, err -+ } -+ -+ return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) -+ -+ case agentRemoveAllIdentities: -+ return nil, s.agent.RemoveAll() -+ -+ case agentLock: -+ var req agentLockMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ -+ return nil, s.agent.Lock(req.Passphrase) -+ -+ case agentUnlock: -+ var req agentUnlockMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ return nil, s.agent.Unlock(req.Passphrase) -+ -+ case agentSignRequest: -+ var req signRequestAgentMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ -+ var wk wireKey -+ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { -+ return nil, err -+ } -+ -+ k := &Key{ -+ Format: wk.Format, -+ Blob: req.KeyBlob, -+ } -+ -+ var sig *ssh.Signature -+ var err error -+ if extendedAgent, ok := s.agent.(ExtendedAgent); ok { -+ sig, err = extendedAgent.SignWithFlags(k, req.Data, SignatureFlags(req.Flags)) -+ } else { -+ sig, err = s.agent.Sign(k, req.Data) -+ } -+ -+ if err != nil { -+ return nil, err -+ } -+ return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil -+ -+ case agentRequestIdentities: -+ keys, err := s.agent.List() -+ if err != nil { -+ return nil, err -+ } -+ -+ rep := identitiesAnswerAgentMsg{ -+ NumKeys: uint32(len(keys)), -+ } -+ for _, k := range keys { -+ rep.Keys = append(rep.Keys, marshalKey(k)...) -+ } -+ return rep, nil -+ -+ case agentAddIDConstrained, agentAddIdentity: -+ return nil, s.insertIdentity(data) -+ -+ case agentExtension: -+ // Return a stub object where the whole contents of the response gets marshaled. -+ var responseStub struct { -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if extendedAgent, ok := s.agent.(ExtendedAgent); !ok { -+ // If this agent doesn't implement extensions, [PROTOCOL.agent] section 4.7 -+ // requires that we return a standard SSH_AGENT_FAILURE message. -+ responseStub.Rest = []byte{agentFailure} -+ } else { -+ var req extensionAgentMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ res, err := extendedAgent.Extension(req.ExtensionType, req.Contents) -+ if err != nil { -+ // If agent extensions are unsupported, return a standard SSH_AGENT_FAILURE -+ // message as required by [PROTOCOL.agent] section 4.7. -+ if err == ErrExtensionUnsupported { -+ responseStub.Rest = []byte{agentFailure} -+ } else { -+ // As the result of any other error processing an extension request, -+ // [PROTOCOL.agent] section 4.7 requires that we return a -+ // SSH_AGENT_EXTENSION_FAILURE code. -+ responseStub.Rest = []byte{agentExtensionFailure} -+ } -+ } else { -+ if len(res) == 0 { -+ return nil, nil -+ } -+ responseStub.Rest = res -+ } -+ } -+ -+ return responseStub, nil -+ } -+ -+ return nil, fmt.Errorf("unknown opcode %d", data[0]) -+} -+ -+func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) { -+ for len(constraints) != 0 { -+ switch constraints[0] { -+ case agentConstrainLifetime: -+ lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5]) -+ constraints = constraints[5:] -+ case agentConstrainConfirm: -+ confirmBeforeUse = true -+ constraints = constraints[1:] -+ case agentConstrainExtension: -+ var msg constrainExtensionAgentMsg -+ if err = ssh.Unmarshal(constraints, &msg); err != nil { -+ return 0, false, nil, err -+ } -+ extensions = append(extensions, ConstraintExtension{ -+ ExtensionName: msg.ExtensionName, -+ ExtensionDetails: msg.ExtensionDetails, -+ }) -+ constraints = msg.Rest -+ default: -+ return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0]) -+ } -+ } -+ return -+} -+ -+func setConstraints(key *AddedKey, constraintBytes []byte) error { -+ lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes) -+ if err != nil { -+ return err -+ } -+ -+ key.LifetimeSecs = lifetimeSecs -+ key.ConfirmBeforeUse = confirmBeforeUse -+ key.ConstraintExtensions = constraintExtensions -+ return nil -+} -+ -+func parseRSAKey(req []byte) (*AddedKey, error) { -+ var k rsaKeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ if k.E.BitLen() > 30 { -+ return nil, errors.New("agent: RSA public exponent too large") -+ } -+ priv := &rsa.PrivateKey{ -+ PublicKey: rsa.PublicKey{ -+ E: int(k.E.Int64()), -+ N: k.N, -+ }, -+ D: k.D, -+ Primes: []*big.Int{k.P, k.Q}, -+ } -+ priv.Precompute() -+ -+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseEd25519Key(req []byte) (*AddedKey, error) { -+ var k ed25519KeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ priv := ed25519.PrivateKey(k.Priv) -+ -+ addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseDSAKey(req []byte) (*AddedKey, error) { -+ var k dsaKeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ priv := &dsa.PrivateKey{ -+ PublicKey: dsa.PublicKey{ -+ Parameters: dsa.Parameters{ -+ P: k.P, -+ Q: k.Q, -+ G: k.G, -+ }, -+ Y: k.Y, -+ }, -+ X: k.X, -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) { -+ priv = &ecdsa.PrivateKey{ -+ D: privScalar, -+ } -+ -+ switch curveName { -+ case "nistp256": -+ priv.Curve = elliptic.P256() -+ case "nistp384": -+ priv.Curve = elliptic.P384() -+ case "nistp521": -+ priv.Curve = elliptic.P521() -+ default: -+ return nil, fmt.Errorf("agent: unknown curve %q", curveName) -+ } -+ -+ priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes) -+ if priv.X == nil || priv.Y == nil { -+ return nil, errors.New("agent: point not on curve") -+ } -+ -+ return priv, nil -+} -+ -+func parseEd25519Cert(req []byte) (*AddedKey, error) { -+ var k ed25519CertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ priv := ed25519.PrivateKey(k.Priv) -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad ED25519 certificate") -+ } -+ -+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseECDSAKey(req []byte) (*AddedKey, error) { -+ var k ecdsaKeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ -+ priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D) -+ if err != nil { -+ return nil, err -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseRSACert(req []byte) (*AddedKey, error) { -+ var k rsaCertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad RSA certificate") -+ } -+ -+ // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go -+ var rsaPub struct { -+ Name string -+ E *big.Int -+ N *big.Int -+ } -+ if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil { -+ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) -+ } -+ -+ if rsaPub.E.BitLen() > 30 { -+ return nil, errors.New("agent: RSA public exponent too large") -+ } -+ -+ priv := rsa.PrivateKey{ -+ PublicKey: rsa.PublicKey{ -+ E: int(rsaPub.E.Int64()), -+ N: rsaPub.N, -+ }, -+ D: k.D, -+ Primes: []*big.Int{k.Q, k.P}, -+ } -+ priv.Precompute() -+ -+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseDSACert(req []byte) (*AddedKey, error) { -+ var k dsaCertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad DSA certificate") -+ } -+ -+ // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go -+ var w struct { -+ Name string -+ P, Q, G, Y *big.Int -+ } -+ if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil { -+ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) -+ } -+ -+ priv := &dsa.PrivateKey{ -+ PublicKey: dsa.PublicKey{ -+ Parameters: dsa.Parameters{ -+ P: w.P, -+ Q: w.Q, -+ G: w.G, -+ }, -+ Y: w.Y, -+ }, -+ X: k.X, -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseECDSACert(req []byte) (*AddedKey, error) { -+ var k ecdsaCertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad ECDSA certificate") -+ } -+ -+ // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go -+ var ecdsaPub struct { -+ Name string -+ ID string -+ Key []byte -+ } -+ if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil { -+ return nil, err -+ } -+ -+ priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D) -+ if err != nil { -+ return nil, err -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func (s *server) insertIdentity(req []byte) error { -+ var record struct { -+ Type string `sshtype:"17|25"` -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := ssh.Unmarshal(req, &record); err != nil { -+ return err -+ } -+ -+ var addedKey *AddedKey -+ var err error -+ -+ switch record.Type { -+ case ssh.KeyAlgoRSA: -+ addedKey, err = parseRSAKey(req) -+ case ssh.KeyAlgoDSA: -+ addedKey, err = parseDSAKey(req) -+ case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: -+ addedKey, err = parseECDSAKey(req) -+ case ssh.KeyAlgoED25519: -+ addedKey, err = parseEd25519Key(req) -+ case ssh.CertAlgoRSAv01: -+ addedKey, err = parseRSACert(req) -+ case ssh.CertAlgoDSAv01: -+ addedKey, err = parseDSACert(req) -+ case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: -+ addedKey, err = parseECDSACert(req) -+ case ssh.CertAlgoED25519v01: -+ addedKey, err = parseEd25519Cert(req) -+ default: -+ return fmt.Errorf("agent: not implemented: %q", record.Type) -+ } -+ -+ if err != nil { -+ return err -+ } -+ return s.agent.Add(*addedKey) -+} -+ -+// ServeAgent serves the agent protocol on the given connection. It -+// returns when an I/O error occurs. -+func ServeAgent(agent Agent, c io.ReadWriter) error { -+ s := &server{agent} -+ -+ var length [4]byte -+ for { -+ if _, err := io.ReadFull(c, length[:]); err != nil { -+ return err -+ } -+ l := binary.BigEndian.Uint32(length[:]) -+ if l == 0 { -+ return fmt.Errorf("agent: request size is 0") -+ } -+ if l > maxAgentResponseBytes { -+ // We also cap requests. -+ return fmt.Errorf("agent: request too large: %d", l) -+ } -+ -+ req := make([]byte, l) -+ if _, err := io.ReadFull(c, req); err != nil { -+ return err -+ } -+ -+ repData := s.processRequestBytes(req) -+ if len(repData) > maxAgentResponseBytes { -+ return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) -+ } -+ -+ binary.BigEndian.PutUint32(length[:], uint32(len(repData))) -+ if _, err := c.Write(length[:]); err != nil { -+ return err -+ } -+ if _, err := c.Write(repData); err != nil { -+ return err -+ } -+ } -+} -diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go -index 916c840b6988..a69e22491d37 100644 ---- a/vendor/golang.org/x/crypto/ssh/certs.go -+++ b/vendor/golang.org/x/crypto/ssh/certs.go -@@ -14,8 +14,10 @@ import ( - "time" - ) - --// These constants from [PROTOCOL.certkeys] represent the algorithm names --// for certificate types supported by this package. -+// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear -+// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms. -+// Unlike key algorithm names, these are not passed to AlgorithmSigner and don't -+// appear in the Signature.Format field. - const ( - CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" - CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" -@@ -25,6 +27,21 @@ const ( - CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" - CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" - CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" -+ -+ // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a -+ // Certificate.Type (or PublicKey.Type), but only in -+ // ClientConfig.HostKeyAlgorithms. -+ CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com" -+ CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com" -+) -+ -+const ( -+ // Deprecated: use CertAlgoRSAv01. -+ CertSigAlgoRSAv01 = CertAlgoRSAv01 -+ // Deprecated: use CertAlgoRSASHA256v01. -+ CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01 -+ // Deprecated: use CertAlgoRSASHA512v01. -+ CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01 - ) - - // Certificate types distinguish between host and user -@@ -423,6 +440,16 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { - } - c.SignatureKey = authority.PublicKey() - -+ // Default to KeyAlgoRSASHA512 for ssh-rsa signers. -+ if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { -+ sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512) -+ if err != nil { -+ return err -+ } -+ c.Signature = sig -+ return nil -+ } -+ - sig, err := authority.Sign(rand, c.bytesForSigning()) - if err != nil { - return err -@@ -431,26 +458,40 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { - return nil - } - --var certAlgoNames = map[string]string{ -- KeyAlgoRSA: CertAlgoRSAv01, -- KeyAlgoDSA: CertAlgoDSAv01, -- KeyAlgoECDSA256: CertAlgoECDSA256v01, -- KeyAlgoECDSA384: CertAlgoECDSA384v01, -- KeyAlgoECDSA521: CertAlgoECDSA521v01, -- KeyAlgoSKECDSA256: CertAlgoSKECDSA256v01, -- KeyAlgoED25519: CertAlgoED25519v01, -- KeyAlgoSKED25519: CertAlgoSKED25519v01, -+// certKeyAlgoNames is a mapping from known certificate algorithm names to the -+// corresponding public key signature algorithm. -+var certKeyAlgoNames = map[string]string{ -+ CertAlgoRSAv01: KeyAlgoRSA, -+ CertAlgoRSASHA256v01: KeyAlgoRSASHA256, -+ CertAlgoRSASHA512v01: KeyAlgoRSASHA512, -+ CertAlgoDSAv01: KeyAlgoDSA, -+ CertAlgoECDSA256v01: KeyAlgoECDSA256, -+ CertAlgoECDSA384v01: KeyAlgoECDSA384, -+ CertAlgoECDSA521v01: KeyAlgoECDSA521, -+ CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256, -+ CertAlgoED25519v01: KeyAlgoED25519, -+ CertAlgoSKED25519v01: KeyAlgoSKED25519, -+} -+ -+// underlyingAlgo returns the signature algorithm associated with algo (which is -+// an advertised or negotiated public key or host key algorithm). These are -+// usually the same, except for certificate algorithms. -+func underlyingAlgo(algo string) string { -+ if a, ok := certKeyAlgoNames[algo]; ok { -+ return a -+ } -+ return algo - } - --// certToPrivAlgo returns the underlying algorithm for a certificate algorithm. --// Panics if a non-certificate algorithm is passed. --func certToPrivAlgo(algo string) string { -- for privAlgo, pubAlgo := range certAlgoNames { -- if pubAlgo == algo { -- return privAlgo -+// certificateAlgo returns the certificate algorithms that uses the provided -+// underlying signature algorithm. -+func certificateAlgo(algo string) (certAlgo string, ok bool) { -+ for certName, algoName := range certKeyAlgoNames { -+ if algoName == algo { -+ return certName, true - } - } -- panic("unknown cert algorithm") -+ return "", false - } - - func (cert *Certificate) bytesForSigning() []byte { -@@ -494,13 +535,13 @@ func (c *Certificate) Marshal() []byte { - return result - } - --// Type returns the key name. It is part of the PublicKey interface. -+// Type returns the certificate algorithm name. It is part of the PublicKey interface. - func (c *Certificate) Type() string { -- algo, ok := certAlgoNames[c.Key.Type()] -+ certName, ok := certificateAlgo(c.Key.Type()) - if !ok { -- panic("unknown cert key type " + c.Key.Type()) -+ panic("unknown certificate type for key type " + c.Key.Type()) - } -- return algo -+ return certName - } - - // Verify verifies a signature against the certificate's public -diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go -index 8bd6b3daff52..f8bdf4984cb7 100644 ---- a/vendor/golang.org/x/crypto/ssh/cipher.go -+++ b/vendor/golang.org/x/crypto/ssh/cipher.go -@@ -18,7 +18,7 @@ import ( - "io/ioutil" - - "golang.org/x/crypto/chacha20" -- "golang.org/x/crypto/poly1305" -+ "golang.org/x/crypto/internal/poly1305" - ) - - const ( -@@ -394,6 +394,10 @@ func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) - } - c.incIV() - -+ if len(plain) == 0 { -+ return nil, errors.New("ssh: empty packet") -+ } -+ - padding := plain[0] - if padding < 4 { - // padding is a byte, so it automatically satisfies -@@ -710,6 +714,10 @@ func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([ - plain := c.buf[4:contentEnd] - s.XORKeyStream(plain, plain) - -+ if len(plain) == 0 { -+ return nil, errors.New("ssh: empty packet") -+ } -+ - padding := plain[0] - if padding < 4 { - // padding is a byte, so it automatically satisfies -diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go -index 7b00bff1caa5..bdc356cbdf1e 100644 ---- a/vendor/golang.org/x/crypto/ssh/client.go -+++ b/vendor/golang.org/x/crypto/ssh/client.go -@@ -77,7 +77,7 @@ func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan - } - - conn := &connection{ -- sshConn: sshConn{conn: c}, -+ sshConn: sshConn{conn: c, user: fullConf.User}, - } - - if err := conn.clientHandshake(addr, &fullConf); err != nil { -@@ -113,14 +113,18 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e - return c.clientAuthenticate(config) - } - --// verifyHostKeySignature verifies the host key obtained in the key --// exchange. --func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { -+// verifyHostKeySignature verifies the host key obtained in the key exchange. -+// algo is the negotiated algorithm, and may be a certificate type. -+func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error { - sig, rest, ok := parseSignatureBody(result.Signature) - if len(rest) > 0 || !ok { - return errors.New("ssh: signature parse error") - } - -+ if a := underlyingAlgo(algo); sig.Format != a { -+ return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, a) -+ } -+ - return hostKey.Verify(result.H, sig) - } - -@@ -224,11 +228,11 @@ type ClientConfig struct { - // be used for the connection. If empty, a reasonable default is used. - ClientVersion string - -- // HostKeyAlgorithms lists the key types that the client will -- // accept from the server as host key, in order of -+ // HostKeyAlgorithms lists the public key algorithms that the client will -+ // accept from the server for host key authentication, in order of - // preference. If empty, a reasonable default is used. Any -- // string returned from PublicKey.Type method may be used, or -- // any of the CertAlgoXxxx and KeyAlgoXxxx constants. -+ // string returned from a PublicKey.Type method may be used, or -+ // any of the CertAlgo and KeyAlgo constants. - HostKeyAlgorithms []string - - // Timeout is the maximum amount of time for the TCP connection to establish. -diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go -index c611aeb68467..409b5ea1d49d 100644 ---- a/vendor/golang.org/x/crypto/ssh/client_auth.go -+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go -@@ -9,6 +9,7 @@ import ( - "errors" - "fmt" - "io" -+ "strings" - ) - - type authResult int -@@ -29,6 +30,33 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error { - if err != nil { - return err - } -+ // The server may choose to send a SSH_MSG_EXT_INFO at this point (if we -+ // advertised willingness to receive one, which we always do) or not. See -+ // RFC 8308, Section 2.4. -+ extensions := make(map[string][]byte) -+ if len(packet) > 0 && packet[0] == msgExtInfo { -+ var extInfo extInfoMsg -+ if err := Unmarshal(packet, &extInfo); err != nil { -+ return err -+ } -+ payload := extInfo.Payload -+ for i := uint32(0); i < extInfo.NumExtensions; i++ { -+ name, rest, ok := parseString(payload) -+ if !ok { -+ return parseError(msgExtInfo) -+ } -+ value, rest, ok := parseString(rest) -+ if !ok { -+ return parseError(msgExtInfo) -+ } -+ extensions[string(name)] = value -+ payload = rest -+ } -+ packet, err = c.transport.readPacket() -+ if err != nil { -+ return err -+ } -+ } - var serviceAccept serviceAcceptMsg - if err := Unmarshal(packet, &serviceAccept); err != nil { - return err -@@ -41,7 +69,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error { - - sessionID := c.transport.getSessionID() - for auth := AuthMethod(new(noneAuth)); auth != nil; { -- ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand) -+ ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions) - if err != nil { - return err - } -@@ -93,7 +121,7 @@ type AuthMethod interface { - // If authentication is not successful, a []string of alternative - // method names is returned. If the slice is nil, it will be ignored - // and the previous set of possible methods will be reused. -- auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error) -+ auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) - - // method returns the RFC 4252 method name. - method() string -@@ -102,7 +130,7 @@ type AuthMethod interface { - // "none" authentication, RFC 4252 section 5.2. - type noneAuth int - --func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { -+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { - if err := c.writePacket(Marshal(&userAuthRequestMsg{ - User: user, - Service: serviceSSH, -@@ -122,7 +150,7 @@ func (n *noneAuth) method() string { - // a function call, e.g. by prompting the user. - type passwordCallback func() (password string, err error) - --func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { -+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { - type passwordAuthMsg struct { - User string `sshtype:"50"` - Service string -@@ -189,7 +217,46 @@ func (cb publicKeyCallback) method() string { - return "publickey" - } - --func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { -+func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as AlgorithmSigner, algo string) { -+ keyFormat := signer.PublicKey().Type() -+ -+ // Like in sendKexInit, if the public key implements AlgorithmSigner we -+ // assume it supports all algorithms, otherwise only the key format one. -+ as, ok := signer.(AlgorithmSigner) -+ if !ok { -+ return algorithmSignerWrapper{signer}, keyFormat -+ } -+ -+ extPayload, ok := extensions["server-sig-algs"] -+ if !ok { -+ // If there is no "server-sig-algs" extension, fall back to the key -+ // format algorithm. -+ return as, keyFormat -+ } -+ -+ // The server-sig-algs extension only carries underlying signature -+ // algorithm, but we are trying to select a protocol-level public key -+ // algorithm, which might be a certificate type. Extend the list of server -+ // supported algorithms to include the corresponding certificate algorithms. -+ serverAlgos := strings.Split(string(extPayload), ",") -+ for _, algo := range serverAlgos { -+ if certAlgo, ok := certificateAlgo(algo); ok { -+ serverAlgos = append(serverAlgos, certAlgo) -+ } -+ } -+ -+ keyAlgos := algorithmsForKeyFormat(keyFormat) -+ algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos) -+ if err != nil { -+ // If there is no overlap, try the key anyway with the key format -+ // algorithm, to support servers that fail to list all supported -+ // algorithms. -+ return as, keyFormat -+ } -+ return as, algo -+} -+ -+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) { - // Authentication is performed by sending an enquiry to test if a key is - // acceptable to the remote. If the key is acceptable, the client will - // attempt to authenticate with the valid key. If not the client will repeat -@@ -201,7 +268,10 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand - } - var methods []string - for _, signer := range signers { -- ok, err := validateKey(signer.PublicKey(), user, c) -+ pub := signer.PublicKey() -+ as, algo := pickSignatureAlgorithm(signer, extensions) -+ -+ ok, err := validateKey(pub, algo, user, c) - if err != nil { - return authFailure, nil, err - } -@@ -209,13 +279,13 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand - continue - } - -- pub := signer.PublicKey() - pubKey := pub.Marshal() -- sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{ -+ data := buildDataSignedForAuth(session, userAuthRequestMsg{ - User: user, - Service: serviceSSH, - Method: cb.method(), -- }, []byte(pub.Type()), pubKey)) -+ }, algo, pubKey) -+ sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) - if err != nil { - return authFailure, nil, err - } -@@ -229,7 +299,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand - Service: serviceSSH, - Method: cb.method(), - HasSig: true, -- Algoname: pub.Type(), -+ Algoname: algo, - PubKey: pubKey, - Sig: sig, - } -@@ -266,26 +336,25 @@ func containsMethod(methods []string, method string) bool { - } - - // validateKey validates the key provided is acceptable to the server. --func validateKey(key PublicKey, user string, c packetConn) (bool, error) { -+func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) { - pubKey := key.Marshal() - msg := publickeyAuthMsg{ - User: user, - Service: serviceSSH, - Method: "publickey", - HasSig: false, -- Algoname: key.Type(), -+ Algoname: algo, - PubKey: pubKey, - } - if err := c.writePacket(Marshal(&msg)); err != nil { - return false, err - } - -- return confirmKeyAck(key, c) -+ return confirmKeyAck(key, algo, c) - } - --func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { -+func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) { - pubKey := key.Marshal() -- algoname := key.Type() - - for { - packet, err := c.readPacket() -@@ -302,14 +371,14 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { - if err := Unmarshal(packet, &msg); err != nil { - return false, err - } -- if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) { -+ if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) { - return false, nil - } - return true, nil - case msgUserAuthFailure: - return false, nil - default: -- return false, unexpectedMessageError(msgUserAuthSuccess, packet[0]) -+ return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0]) - } - } - } -@@ -330,6 +399,7 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet - // along with a list of remaining authentication methods to try next and - // an error if an unexpected response was received. - func handleAuthResponse(c packetConn) (authResult, []string, error) { -+ gotMsgExtInfo := false - for { - packet, err := c.readPacket() - if err != nil { -@@ -341,6 +411,12 @@ func handleAuthResponse(c packetConn) (authResult, []string, error) { - if err := handleBannerResponse(c, packet); err != nil { - return authFailure, nil, err - } -+ case msgExtInfo: -+ // Ignore post-authentication RFC 8308 extensions, once. -+ if gotMsgExtInfo { -+ return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) -+ } -+ gotMsgExtInfo = true - case msgUserAuthFailure: - var msg userAuthFailureMsg - if err := Unmarshal(packet, &msg); err != nil { -@@ -380,10 +456,10 @@ func handleBannerResponse(c packetConn, packet []byte) error { - // disabling echoing (e.g. for passwords), and return all the answers. - // Challenge may be called multiple times in a single session. After - // successful authentication, the server may send a challenge with no --// questions, for which the user and instruction messages should be -+// questions, for which the name and instruction messages should be - // printed. RFC 4256 section 3.3 details how the UI should behave for - // both CLI and GUI environments. --type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error) -+type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error) - - // KeyboardInteractive returns an AuthMethod using a prompt/response - // sequence controlled by the server. -@@ -395,7 +471,7 @@ func (cb KeyboardInteractiveChallenge) method() string { - return "keyboard-interactive" - } - --func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { -+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { - type initiateMsg struct { - User string `sshtype:"50"` - Service string -@@ -412,6 +488,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe - return authFailure, nil, err - } - -+ gotMsgExtInfo := false - for { - packet, err := c.readPacket() - if err != nil { -@@ -425,6 +502,13 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe - return authFailure, nil, err - } - continue -+ case msgExtInfo: -+ // Ignore post-authentication RFC 8308 extensions, once. -+ if gotMsgExtInfo { -+ return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) -+ } -+ gotMsgExtInfo = true -+ continue - case msgUserAuthInfoRequest: - // OK - case msgUserAuthFailure: -@@ -465,7 +549,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe - return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs") - } - -- answers, err := cb(msg.User, msg.Instruction, prompts, echos) -+ answers, err := cb(msg.Name, msg.Instruction, prompts, echos) - if err != nil { - return authFailure, nil, err - } -@@ -497,9 +581,9 @@ type retryableAuthMethod struct { - maxTries int - } - --func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) { -+func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) { - for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { -- ok, methods, err = r.authMethod.auth(session, user, c, rand) -+ ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions) - if ok != authFailure || err != nil { // either success, partial success or error terminate - return ok, methods, err - } -@@ -542,7 +626,7 @@ type gssAPIWithMICCallback struct { - target string - } - --func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { -+func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { - m := &userAuthRequestMsg{ - User: user, - Service: serviceSSH, -diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go -index 290382d059ef..2a47a61ded9c 100644 ---- a/vendor/golang.org/x/crypto/ssh/common.go -+++ b/vendor/golang.org/x/crypto/ssh/common.go -@@ -44,11 +44,11 @@ var preferredCiphers = []string{ - // supportedKexAlgos specifies the supported key-exchange algorithms in - // preference order. - var supportedKexAlgos = []string{ -- kexAlgoCurve25519SHA256, -+ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, - // P384 and P521 are not constant-time yet, but since we don't - // reuse ephemeral keys, using them for ECDH should be OK. - kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, -- kexAlgoDH14SHA1, kexAlgoDH1SHA1, -+ kexAlgoDH14SHA256, kexAlgoDH14SHA1, kexAlgoDH1SHA1, - } - - // serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden -@@ -61,18 +61,20 @@ var serverForbiddenKexAlgos = map[string]struct{}{ - // preferredKexAlgos specifies the default preference for key-exchange algorithms - // in preference order. - var preferredKexAlgos = []string{ -- kexAlgoCurve25519SHA256, -+ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, - kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, -- kexAlgoDH14SHA1, -+ kexAlgoDH14SHA256, kexAlgoDH14SHA1, - } - - // supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods - // of authenticating servers) in preference order. - var supportedHostKeyAlgos = []string{ -+ CertAlgoRSASHA512v01, CertAlgoRSASHA256v01, - CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, - CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, - - KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, -+ KeyAlgoRSASHA512, KeyAlgoRSASHA256, - KeyAlgoRSA, KeyAlgoDSA, - - KeyAlgoED25519, -@@ -87,19 +89,33 @@ var supportedMACs = []string{ - - var supportedCompressions = []string{compressionNone} - --// hashFuncs keeps the mapping of supported algorithms to their respective --// hashes needed for signature verification. -+// hashFuncs keeps the mapping of supported signature algorithms to their -+// respective hashes needed for signing and verification. - var hashFuncs = map[string]crypto.Hash{ -- KeyAlgoRSA: crypto.SHA1, -- KeyAlgoDSA: crypto.SHA1, -- KeyAlgoECDSA256: crypto.SHA256, -- KeyAlgoECDSA384: crypto.SHA384, -- KeyAlgoECDSA521: crypto.SHA512, -- CertAlgoRSAv01: crypto.SHA1, -- CertAlgoDSAv01: crypto.SHA1, -- CertAlgoECDSA256v01: crypto.SHA256, -- CertAlgoECDSA384v01: crypto.SHA384, -- CertAlgoECDSA521v01: crypto.SHA512, -+ KeyAlgoRSA: crypto.SHA1, -+ KeyAlgoRSASHA256: crypto.SHA256, -+ KeyAlgoRSASHA512: crypto.SHA512, -+ KeyAlgoDSA: crypto.SHA1, -+ KeyAlgoECDSA256: crypto.SHA256, -+ KeyAlgoECDSA384: crypto.SHA384, -+ KeyAlgoECDSA521: crypto.SHA512, -+ // KeyAlgoED25519 doesn't pre-hash. -+ KeyAlgoSKECDSA256: crypto.SHA256, -+ KeyAlgoSKED25519: crypto.SHA256, -+} -+ -+// algorithmsForKeyFormat returns the supported signature algorithms for a given -+// public key format (PublicKey.Type), in order of preference. See RFC 8332, -+// Section 2. See also the note in sendKexInit on backwards compatibility. -+func algorithmsForKeyFormat(keyFormat string) []string { -+ switch keyFormat { -+ case KeyAlgoRSA: -+ return []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA} -+ case CertAlgoRSAv01: -+ return []string{CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, CertAlgoRSAv01} -+ default: -+ return []string{keyFormat} -+ } - } - - // unexpectedMessageError results when the SSH message that we received didn't -@@ -146,6 +162,11 @@ func (a *directionAlgorithms) rekeyBytes() int64 { - return 1 << 30 - } - -+var aeadCiphers = map[string]bool{ -+ gcmCipherID: true, -+ chacha20Poly1305ID: true, -+} -+ - type algorithms struct { - kex string - hostKey string -@@ -181,14 +202,18 @@ func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMs - return - } - -- ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) -- if err != nil { -- return -+ if !aeadCiphers[ctos.Cipher] { -+ ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) -+ if err != nil { -+ return -+ } - } - -- stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) -- if err != nil { -- return -+ if !aeadCiphers[stoc.Cipher] { -+ stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) -+ if err != nil { -+ return -+ } - } - - ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) -@@ -272,8 +297,9 @@ func (c *Config) SetDefaults() { - } - - // buildDataSignedForAuth returns the data that is signed in order to prove --// possession of a private key. See RFC 4252, section 7. --func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { -+// possession of a private key. See RFC 4252, section 7. algo is the advertised -+// algorithm, and may be a certificate type. -+func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo string, pubKey []byte) []byte { - data := struct { - Session []byte - Type byte -@@ -281,7 +307,7 @@ func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubK - Service string - Method string - Sign bool -- Algo []byte -+ Algo string - PubKey []byte - }{ - sessionID, -diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go -index 2b10b05a498c..f815cdb4c945 100644 ---- a/vendor/golang.org/x/crypto/ssh/handshake.go -+++ b/vendor/golang.org/x/crypto/ssh/handshake.go -@@ -455,14 +455,36 @@ func (t *handshakeTransport) sendKexInit() error { - } - io.ReadFull(rand.Reader, msg.Cookie[:]) - -- if len(t.hostKeys) > 0 { -+ isServer := len(t.hostKeys) > 0 -+ if isServer { - for _, k := range t.hostKeys { -- msg.ServerHostKeyAlgos = append( -- msg.ServerHostKeyAlgos, k.PublicKey().Type()) -+ // If k is an AlgorithmSigner, presume it supports all signature algorithms -+ // associated with the key format. (Ideally AlgorithmSigner would have a -+ // method to advertise supported algorithms, but it doesn't. This means that -+ // adding support for a new algorithm is a breaking change, as we will -+ // immediately negotiate it even if existing implementations don't support -+ // it. If that ever happens, we'll have to figure something out.) -+ // If k is not an AlgorithmSigner, we can only assume it only supports the -+ // algorithms that matches the key format. (This means that Sign can't pick -+ // a different default.) -+ keyFormat := k.PublicKey().Type() -+ if _, ok := k.(AlgorithmSigner); ok { -+ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...) -+ } else { -+ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat) -+ } - } - } else { - msg.ServerHostKeyAlgos = t.hostKeyAlgorithms -+ -+ // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what -+ // algorithms the server supports for public key authentication. See RFC -+ // 8303, Section 2.1. -+ msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1) -+ msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...) -+ msg.KexAlgos = append(msg.KexAlgos, "ext-info-c") - } -+ - packet := Marshal(msg) - - // writePacket destroys the contents, so save a copy. -@@ -582,9 +604,9 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { - - var result *kexResult - if len(t.hostKeys) > 0 { -- result, err = t.server(kex, t.algorithms, &magics) -+ result, err = t.server(kex, &magics) - } else { -- result, err = t.client(kex, t.algorithms, &magics) -+ result, err = t.client(kex, &magics) - } - - if err != nil { -@@ -611,19 +633,52 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { - return nil - } - --func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { -- var hostKey Signer -- for _, k := range t.hostKeys { -- if algs.hostKey == k.PublicKey().Type() { -- hostKey = k -+// algorithmSignerWrapper is an AlgorithmSigner that only supports the default -+// key format algorithm. -+// -+// This is technically a violation of the AlgorithmSigner interface, but it -+// should be unreachable given where we use this. Anyway, at least it returns an -+// error instead of panicing or producing an incorrect signature. -+type algorithmSignerWrapper struct { -+ Signer -+} -+ -+func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -+ if algorithm != underlyingAlgo(a.PublicKey().Type()) { -+ return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm") -+ } -+ return a.Sign(rand, data) -+} -+ -+func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner { -+ for _, k := range hostKeys { -+ if algo == k.PublicKey().Type() { -+ return algorithmSignerWrapper{k} - } -+ k, ok := k.(AlgorithmSigner) -+ if !ok { -+ continue -+ } -+ for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) { -+ if algo == a { -+ return k -+ } -+ } -+ } -+ return nil -+} -+ -+func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { -+ hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey) -+ if hostKey == nil { -+ return nil, errors.New("ssh: internal error: negotiated unsupported signature type") - } - -- r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey) -+ r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey) - return r, err - } - --func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { -+func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { - result, err := kex.Client(t.conn, t.config.Rand, magics) - if err != nil { - return nil, err -@@ -634,7 +689,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics * - return nil, err - } - -- if err := verifyHostKeySignature(hostKey, result); err != nil { -+ if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil { - return nil, err - } - -diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go -index 766e9293975e..927a90cd46f8 100644 ---- a/vendor/golang.org/x/crypto/ssh/kex.go -+++ b/vendor/golang.org/x/crypto/ssh/kex.go -@@ -20,12 +20,14 @@ import ( - ) - - const ( -- kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" -- kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" -- kexAlgoECDH256 = "ecdh-sha2-nistp256" -- kexAlgoECDH384 = "ecdh-sha2-nistp384" -- kexAlgoECDH521 = "ecdh-sha2-nistp521" -- kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" -+ kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" -+ kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" -+ kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256" -+ kexAlgoECDH256 = "ecdh-sha2-nistp256" -+ kexAlgoECDH384 = "ecdh-sha2-nistp384" -+ kexAlgoECDH521 = "ecdh-sha2-nistp521" -+ kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org" -+ kexAlgoCurve25519SHA256 = "curve25519-sha256" - - // For the following kex only the client half contains a production - // ready implementation. The server half only consists of a minimal -@@ -75,8 +77,9 @@ func (m *handshakeMagics) write(w io.Writer) { - // kexAlgorithm abstracts different key exchange algorithms. - type kexAlgorithm interface { - // Server runs server-side key agreement, signing the result -- // with a hostkey. -- Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error) -+ // with a hostkey. algo is the negotiated algorithm, and may -+ // be a certificate type. -+ Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error) - - // Client runs the client-side key agreement. Caller is - // responsible for verifying the host key signature. -@@ -86,6 +89,7 @@ type kexAlgorithm interface { - // dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. - type dhGroup struct { - g, p, pMinus1 *big.Int -+ hashFunc crypto.Hash - } - - func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { -@@ -96,8 +100,6 @@ func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, - } - - func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { -- hashFunc := crypto.SHA1 -- - var x *big.Int - for { - var err error -@@ -132,7 +134,7 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha - return nil, err - } - -- h := hashFunc.New() -+ h := group.hashFunc.New() - magics.write(h) - writeString(h, kexDHReply.HostKey) - writeInt(h, X) -@@ -146,12 +148,11 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha - K: K, - HostKey: kexDHReply.HostKey, - Signature: kexDHReply.Signature, -- Hash: crypto.SHA1, -+ Hash: group.hashFunc, - }, nil - } - --func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { -- hashFunc := crypto.SHA1 -+func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { - packet, err := c.readPacket() - if err != nil { - return -@@ -179,7 +180,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha - - hostKeyBytes := priv.PublicKey().Marshal() - -- h := hashFunc.New() -+ h := group.hashFunc.New() - magics.write(h) - writeString(h, hostKeyBytes) - writeInt(h, kexDHInit.X) -@@ -193,7 +194,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha - - // H is already a hash, but the hostkey signing will apply its - // own key-specific hash algorithm. -- sig, err := signAndMarshal(priv, randSource, H) -+ sig, err := signAndMarshal(priv, randSource, H, algo) - if err != nil { - return nil, err - } -@@ -211,7 +212,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha - K: K, - HostKey: hostKeyBytes, - Signature: sig, -- Hash: crypto.SHA1, -+ Hash: group.hashFunc, - }, err - } - -@@ -314,7 +315,7 @@ func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { - return true - } - --func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { -+func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { - packet, err := c.readPacket() - if err != nil { - return nil, err -@@ -359,7 +360,7 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p - - // H is already a hash, but the hostkey signing will apply its - // own key-specific hash algorithm. -- sig, err := signAndMarshal(priv, rand, H) -+ sig, err := signAndMarshal(priv, rand, H, algo) - if err != nil { - return nil, err - } -@@ -384,39 +385,62 @@ func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, p - }, nil - } - -+// ecHash returns the hash to match the given elliptic curve, see RFC -+// 5656, section 6.2.1 -+func ecHash(curve elliptic.Curve) crypto.Hash { -+ bitSize := curve.Params().BitSize -+ switch { -+ case bitSize <= 256: -+ return crypto.SHA256 -+ case bitSize <= 384: -+ return crypto.SHA384 -+ } -+ return crypto.SHA512 -+} -+ - var kexAlgoMap = map[string]kexAlgorithm{} - - func init() { -- // This is the group called diffie-hellman-group1-sha1 in RFC -- // 4253 and Oakley Group 2 in RFC 2409. -+ // This is the group called diffie-hellman-group1-sha1 in -+ // RFC 4253 and Oakley Group 2 in RFC 2409. - p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) - kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ -- g: new(big.Int).SetInt64(2), -- p: p, -- pMinus1: new(big.Int).Sub(p, bigOne), -+ g: new(big.Int).SetInt64(2), -+ p: p, -+ pMinus1: new(big.Int).Sub(p, bigOne), -+ hashFunc: crypto.SHA1, - } - -- // This is the group called diffie-hellman-group14-sha1 in RFC -- // 4253 and Oakley Group 14 in RFC 3526. -+ // This are the groups called diffie-hellman-group14-sha1 and -+ // diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268, -+ // and Oakley Group 14 in RFC 3526. - p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) -- -- kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ -+ group14 := &dhGroup{ - g: new(big.Int).SetInt64(2), - p: p, - pMinus1: new(big.Int).Sub(p, bigOne), - } - -+ kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ -+ g: group14.g, p: group14.p, pMinus1: group14.pMinus1, -+ hashFunc: crypto.SHA1, -+ } -+ kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{ -+ g: group14.g, p: group14.p, pMinus1: group14.pMinus1, -+ hashFunc: crypto.SHA256, -+ } -+ - kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} - kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} - kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} - kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} -+ kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{} - kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} - kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} - } - --// curve25519sha256 implements the curve25519-sha256@libssh.org key --// agreement protocol, as described in --// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt -+// curve25519sha256 implements the curve25519-sha256 (formerly known as -+// curve25519-sha256@libssh.org) key exchange method, as described in RFC 8731. - type curve25519sha256 struct{} - - type curve25519KeyPair struct { -@@ -486,7 +510,7 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh - }, nil - } - --func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { -+func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { - packet, err := c.readPacket() - if err != nil { - return -@@ -527,7 +551,7 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh - - H := h.Sum(nil) - -- sig, err := signAndMarshal(priv, rand, H) -+ sig, err := signAndMarshal(priv, rand, H, algo) - if err != nil { - return nil, err - } -@@ -553,7 +577,6 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh - // diffie-hellman-group-exchange-sha256 key agreement protocols, - // as described in RFC 4419 - type dhGEXSHA struct { -- g, p *big.Int - hashFunc crypto.Hash - } - -@@ -563,14 +586,7 @@ const ( - dhGroupExchangeMaximumBits = 8192 - ) - --func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { -- if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 { -- return nil, fmt.Errorf("ssh: DH parameter out of bounds") -- } -- return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil --} -- --func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { -+func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { - // Send GexRequest - kexDHGexRequest := kexDHGexRequestMsg{ - MinBits: dhGroupExchangeMinimumBits, -@@ -587,35 +603,29 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake - return nil, err - } - -- var kexDHGexGroup kexDHGexGroupMsg -- if err = Unmarshal(packet, &kexDHGexGroup); err != nil { -+ var msg kexDHGexGroupMsg -+ if err = Unmarshal(packet, &msg); err != nil { - return nil, err - } - - // reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits -- if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits { -- return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen()) -+ if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits { -+ return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen()) - } - -- gex.p = kexDHGexGroup.P -- gex.g = kexDHGexGroup.G -- -- // Check if g is safe by verifing that g > 1 and g < p - 1 -- one := big.NewInt(1) -- var pMinusOne = &big.Int{} -- pMinusOne.Sub(gex.p, one) -- if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 { -+ // Check if g is safe by verifying that 1 < g < p-1 -+ pMinusOne := new(big.Int).Sub(msg.P, bigOne) -+ if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 { - return nil, fmt.Errorf("ssh: server provided gex g is not safe") - } - - // Send GexInit -- var pHalf = &big.Int{} -- pHalf.Rsh(gex.p, 1) -+ pHalf := new(big.Int).Rsh(msg.P, 1) - x, err := rand.Int(randSource, pHalf) - if err != nil { - return nil, err - } -- X := new(big.Int).Exp(gex.g, x, gex.p) -+ X := new(big.Int).Exp(msg.G, x, msg.P) - kexDHGexInit := kexDHGexInitMsg{ - X: X, - } -@@ -634,13 +644,13 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake - return nil, err - } - -- kInt, err := gex.diffieHellman(kexDHGexReply.Y, x) -- if err != nil { -- return nil, err -+ if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 { -+ return nil, errors.New("ssh: DH parameter out of bounds") - } -+ kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P) - -- // Check if k is safe by verifing that k > 1 and k < p - 1 -- if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 { -+ // Check if k is safe by verifying that k > 1 and k < p - 1 -+ if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 { - return nil, fmt.Errorf("ssh: derived k is not safe") - } - -@@ -650,8 +660,8 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) -- writeInt(h, gex.p) -- writeInt(h, gex.g) -+ writeInt(h, msg.P) -+ writeInt(h, msg.G) - writeInt(h, X) - writeInt(h, kexDHGexReply.Y) - K := make([]byte, intLength(kInt)) -@@ -670,7 +680,7 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake - // Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256. - // - // This is a minimal implementation to satisfy the automated tests. --func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { -+func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { - // Receive GexRequest - packet, err := c.readPacket() - if err != nil { -@@ -681,35 +691,17 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake - return - } - -- // smoosh the user's preferred size into our own limits -- if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits { -- kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits -- } -- if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits { -- kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits -- } -- // fix min/max if they're inconsistent. technically, we could just pout -- // and hang up, but there's no harm in giving them the benefit of the -- // doubt and just picking a bitsize for them. -- if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits { -- kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits -- } -- if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits { -- kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits -- } -- - // Send GexGroup - // This is the group called diffie-hellman-group14-sha1 in RFC - // 4253 and Oakley Group 14 in RFC 3526. - p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) -- gex.p = p -- gex.g = big.NewInt(2) -+ g := big.NewInt(2) - -- kexDHGexGroup := kexDHGexGroupMsg{ -- P: gex.p, -- G: gex.g, -+ msg := &kexDHGexGroupMsg{ -+ P: p, -+ G: g, - } -- if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil { -+ if err := c.writePacket(Marshal(msg)); err != nil { - return nil, err - } - -@@ -723,19 +715,19 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake - return - } - -- var pHalf = &big.Int{} -- pHalf.Rsh(gex.p, 1) -+ pHalf := new(big.Int).Rsh(p, 1) - - y, err := rand.Int(randSource, pHalf) - if err != nil { - return - } -+ Y := new(big.Int).Exp(g, y, p) - -- Y := new(big.Int).Exp(gex.g, y, gex.p) -- kInt, err := gex.diffieHellman(kexDHGexInit.X, y) -- if err != nil { -- return nil, err -+ pMinusOne := new(big.Int).Sub(p, bigOne) -+ if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 { -+ return nil, errors.New("ssh: DH parameter out of bounds") - } -+ kInt := new(big.Int).Exp(kexDHGexInit.X, y, p) - - hostKeyBytes := priv.PublicKey().Marshal() - -@@ -745,8 +737,8 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) - binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) -- writeInt(h, gex.p) -- writeInt(h, gex.g) -+ writeInt(h, p) -+ writeInt(h, g) - writeInt(h, kexDHGexInit.X) - writeInt(h, Y) - -@@ -758,7 +750,7 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake - - // H is already a hash, but the hostkey signing will apply its - // own key-specific hash algorithm. -- sig, err := signAndMarshal(priv, randSource, H) -+ sig, err := signAndMarshal(priv, randSource, H, algo) - if err != nil { - return nil, err - } -diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go -index 31f26349a05f..1c7de1a6dd79 100644 ---- a/vendor/golang.org/x/crypto/ssh/keys.go -+++ b/vendor/golang.org/x/crypto/ssh/keys.go -@@ -30,8 +30,9 @@ import ( - "golang.org/x/crypto/ssh/internal/bcrypt_pbkdf" - ) - --// These constants represent the algorithm names for key types supported by this --// package. -+// Public key algorithms names. These values can appear in PublicKey.Type, -+// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner -+// arguments. - const ( - KeyAlgoRSA = "ssh-rsa" - KeyAlgoDSA = "ssh-dss" -@@ -41,16 +42,21 @@ const ( - KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" - KeyAlgoED25519 = "ssh-ed25519" - KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com" -+ -+ // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not -+ // public key formats, so they can't appear as a PublicKey.Type. The -+ // corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2. -+ KeyAlgoRSASHA256 = "rsa-sha2-256" -+ KeyAlgoRSASHA512 = "rsa-sha2-512" - ) - --// These constants represent non-default signature algorithms that are supported --// as algorithm parameters to AlgorithmSigner.SignWithAlgorithm methods. See --// [PROTOCOL.agent] section 4.5.1 and --// https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-10 - const ( -- SigAlgoRSA = "ssh-rsa" -- SigAlgoRSASHA2256 = "rsa-sha2-256" -- SigAlgoRSASHA2512 = "rsa-sha2-512" -+ // Deprecated: use KeyAlgoRSA. -+ SigAlgoRSA = KeyAlgoRSA -+ // Deprecated: use KeyAlgoRSASHA256. -+ SigAlgoRSASHA2256 = KeyAlgoRSASHA256 -+ // Deprecated: use KeyAlgoRSASHA512. -+ SigAlgoRSASHA2512 = KeyAlgoRSASHA512 - ) - - // parsePubKey parses a public key of the given algorithm. -@@ -70,7 +76,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err - case KeyAlgoSKED25519: - return parseSKEd25519(in) - case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: -- cert, err := parseCert(in, certToPrivAlgo(algo)) -+ cert, err := parseCert(in, certKeyAlgoNames[algo]) - if err != nil { - return nil, nil, err - } -@@ -289,18 +295,21 @@ func MarshalAuthorizedKey(key PublicKey) []byte { - return b.Bytes() - } - --// PublicKey is an abstraction of different types of public keys. -+// PublicKey represents a public key using an unspecified algorithm. -+// -+// Some PublicKeys provided by this package also implement CryptoPublicKey. - type PublicKey interface { -- // Type returns the key's type, e.g. "ssh-rsa". -+ // Type returns the key format name, e.g. "ssh-rsa". - Type() string - -- // Marshal returns the serialized key data in SSH wire format, -- // with the name prefix. To unmarshal the returned data, use -- // the ParsePublicKey function. -+ // Marshal returns the serialized key data in SSH wire format, with the name -+ // prefix. To unmarshal the returned data, use the ParsePublicKey function. - Marshal() []byte - -- // Verify that sig is a signature on the given data using this -- // key. This function will hash the data appropriately first. -+ // Verify that sig is a signature on the given data using this key. This -+ // method will hash the data appropriately first. sig.Format is allowed to -+ // be any signature algorithm compatible with the key type, the caller -+ // should check if it has more stringent requirements. - Verify(data []byte, sig *Signature) error - } - -@@ -311,25 +320,32 @@ type CryptoPublicKey interface { - } - - // A Signer can create signatures that verify against a public key. -+// -+// Some Signers provided by this package also implement AlgorithmSigner. - type Signer interface { -- // PublicKey returns an associated PublicKey instance. -+ // PublicKey returns the associated PublicKey. - PublicKey() PublicKey - -- // Sign returns raw signature for the given data. This method -- // will apply the hash specified for the keytype to the data. -+ // Sign returns a signature for the given data. This method will hash the -+ // data appropriately first. The signature algorithm is expected to match -+ // the key format returned by the PublicKey.Type method (and not to be any -+ // alternative algorithm supported by the key format). - Sign(rand io.Reader, data []byte) (*Signature, error) - } - --// A AlgorithmSigner is a Signer that also supports specifying a specific --// algorithm to use for signing. -+// An AlgorithmSigner is a Signer that also supports specifying an algorithm to -+// use for signing. -+// -+// An AlgorithmSigner can't advertise the algorithms it supports, so it should -+// be prepared to be invoked with every algorithm supported by the public key -+// format. - type AlgorithmSigner interface { - Signer - -- // SignWithAlgorithm is like Signer.Sign, but allows specification of a -- // non-default signing algorithm. See the SigAlgo* constants in this -- // package for signature algorithms supported by this package. Callers may -- // pass an empty string for the algorithm in which case the AlgorithmSigner -- // will use its default algorithm. -+ // SignWithAlgorithm is like Signer.Sign, but allows specifying a desired -+ // signing algorithm. Callers may pass an empty string for the algorithm in -+ // which case the AlgorithmSigner will use a default algorithm. This default -+ // doesn't currently control any behavior in this package. - SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) - } - -@@ -381,17 +397,11 @@ func (r *rsaPublicKey) Marshal() []byte { - } - - func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { -- var hash crypto.Hash -- switch sig.Format { -- case SigAlgoRSA: -- hash = crypto.SHA1 -- case SigAlgoRSASHA2256: -- hash = crypto.SHA256 -- case SigAlgoRSASHA2512: -- hash = crypto.SHA512 -- default: -+ supportedAlgos := algorithmsForKeyFormat(r.Type()) -+ if !contains(supportedAlgos, sig.Format) { - return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) - } -+ hash := hashFuncs[sig.Format] - h := hash.New() - h.Write(data) - digest := h.Sum(nil) -@@ -466,7 +476,7 @@ func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { - if sig.Format != k.Type() { - return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) - } -- h := crypto.SHA1.New() -+ h := hashFuncs[sig.Format].New() - h.Write(data) - digest := h.Sum(nil) - -@@ -499,7 +509,7 @@ func (k *dsaPrivateKey) PublicKey() PublicKey { - } - - func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { -- return k.SignWithAlgorithm(rand, data, "") -+ return k.SignWithAlgorithm(rand, data, k.PublicKey().Type()) - } - - func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -@@ -507,7 +517,7 @@ func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm - return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) - } - -- h := crypto.SHA1.New() -+ h := hashFuncs[k.PublicKey().Type()].New() - h.Write(data) - digest := h.Sum(nil) - r, s, err := dsa.Sign(rand, k.PrivateKey, digest) -@@ -603,19 +613,6 @@ func supportedEllipticCurve(curve elliptic.Curve) bool { - return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() - } - --// ecHash returns the hash to match the given elliptic curve, see RFC --// 5656, section 6.2.1 --func ecHash(curve elliptic.Curve) crypto.Hash { -- bitSize := curve.Params().BitSize -- switch { -- case bitSize <= 256: -- return crypto.SHA256 -- case bitSize <= 384: -- return crypto.SHA384 -- } -- return crypto.SHA512 --} -- - // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. - func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { - var w struct { -@@ -671,7 +668,7 @@ func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { - return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) - } - -- h := ecHash(k.Curve).New() -+ h := hashFuncs[sig.Format].New() - h.Write(data) - digest := h.Sum(nil) - -@@ -775,7 +772,7 @@ func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error { - return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) - } - -- h := ecHash(k.Curve).New() -+ h := hashFuncs[sig.Format].New() - h.Write([]byte(k.application)) - appDigest := h.Sum(nil) - -@@ -874,7 +871,7 @@ func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error { - return fmt.Errorf("invalid size %d for Ed25519 public key", l) - } - -- h := sha256.New() -+ h := hashFuncs[sig.Format].New() - h.Write([]byte(k.application)) - appDigest := h.Sum(nil) - -@@ -961,44 +958,20 @@ func (s *wrappedSigner) PublicKey() PublicKey { - } - - func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { -- return s.SignWithAlgorithm(rand, data, "") -+ return s.SignWithAlgorithm(rand, data, s.pubKey.Type()) - } - - func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -- var hashFunc crypto.Hash -- -- if _, ok := s.pubKey.(*rsaPublicKey); ok { -- // RSA keys support a few hash functions determined by the requested signature algorithm -- switch algorithm { -- case "", SigAlgoRSA: -- algorithm = SigAlgoRSA -- hashFunc = crypto.SHA1 -- case SigAlgoRSASHA2256: -- hashFunc = crypto.SHA256 -- case SigAlgoRSASHA2512: -- hashFunc = crypto.SHA512 -- default: -- return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) -- } -- } else { -- // The only supported algorithm for all other key types is the same as the type of the key -- if algorithm == "" { -- algorithm = s.pubKey.Type() -- } else if algorithm != s.pubKey.Type() { -- return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) -- } -+ if algorithm == "" { -+ algorithm = s.pubKey.Type() -+ } - -- switch key := s.pubKey.(type) { -- case *dsaPublicKey: -- hashFunc = crypto.SHA1 -- case *ecdsaPublicKey: -- hashFunc = ecHash(key.Curve) -- case ed25519PublicKey: -- default: -- return nil, fmt.Errorf("ssh: unsupported key type %T", key) -- } -+ supportedAlgos := algorithmsForKeyFormat(s.pubKey.Type()) -+ if !contains(supportedAlgos, algorithm) { -+ return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type()) - } - -+ hashFunc := hashFuncs[algorithm] - var digest []byte - if hashFunc != 0 { - h := hashFunc.New() -diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go -new file mode 100644 -index 000000000000..260cfe58c654 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go -@@ -0,0 +1,540 @@ -+// 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 knownhosts implements a parser for the OpenSSH known_hosts -+// host key database, and provides utility functions for writing -+// OpenSSH compliant known_hosts files. -+package knownhosts -+ -+import ( -+ "bufio" -+ "bytes" -+ "crypto/hmac" -+ "crypto/rand" -+ "crypto/sha1" -+ "encoding/base64" -+ "errors" -+ "fmt" -+ "io" -+ "net" -+ "os" -+ "strings" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+// See the sshd manpage -+// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for -+// background. -+ -+type addr struct{ host, port string } -+ -+func (a *addr) String() string { -+ h := a.host -+ if strings.Contains(h, ":") { -+ h = "[" + h + "]" -+ } -+ return h + ":" + a.port -+} -+ -+type matcher interface { -+ match(addr) bool -+} -+ -+type hostPattern struct { -+ negate bool -+ addr addr -+} -+ -+func (p *hostPattern) String() string { -+ n := "" -+ if p.negate { -+ n = "!" -+ } -+ -+ return n + p.addr.String() -+} -+ -+type hostPatterns []hostPattern -+ -+func (ps hostPatterns) match(a addr) bool { -+ matched := false -+ for _, p := range ps { -+ if !p.match(a) { -+ continue -+ } -+ if p.negate { -+ return false -+ } -+ matched = true -+ } -+ return matched -+} -+ -+// See -+// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c -+// The matching of * has no regard for separators, unlike filesystem globs -+func wildcardMatch(pat []byte, str []byte) bool { -+ for { -+ if len(pat) == 0 { -+ return len(str) == 0 -+ } -+ if len(str) == 0 { -+ return false -+ } -+ -+ if pat[0] == '*' { -+ if len(pat) == 1 { -+ return true -+ } -+ -+ for j := range str { -+ if wildcardMatch(pat[1:], str[j:]) { -+ return true -+ } -+ } -+ return false -+ } -+ -+ if pat[0] == '?' || pat[0] == str[0] { -+ pat = pat[1:] -+ str = str[1:] -+ } else { -+ return false -+ } -+ } -+} -+ -+func (p *hostPattern) match(a addr) bool { -+ return wildcardMatch([]byte(p.addr.host), []byte(a.host)) && p.addr.port == a.port -+} -+ -+type keyDBLine struct { -+ cert bool -+ matcher matcher -+ knownKey KnownKey -+} -+ -+func serialize(k ssh.PublicKey) string { -+ return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal()) -+} -+ -+func (l *keyDBLine) match(a addr) bool { -+ return l.matcher.match(a) -+} -+ -+type hostKeyDB struct { -+ // Serialized version of revoked keys -+ revoked map[string]*KnownKey -+ lines []keyDBLine -+} -+ -+func newHostKeyDB() *hostKeyDB { -+ db := &hostKeyDB{ -+ revoked: make(map[string]*KnownKey), -+ } -+ -+ return db -+} -+ -+func keyEq(a, b ssh.PublicKey) bool { -+ return bytes.Equal(a.Marshal(), b.Marshal()) -+} -+ -+// IsAuthorityForHost can be used as a callback in ssh.CertChecker -+func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool { -+ h, p, err := net.SplitHostPort(address) -+ if err != nil { -+ return false -+ } -+ a := addr{host: h, port: p} -+ -+ for _, l := range db.lines { -+ if l.cert && keyEq(l.knownKey.Key, remote) && l.match(a) { -+ return true -+ } -+ } -+ return false -+} -+ -+// IsRevoked can be used as a callback in ssh.CertChecker -+func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool { -+ _, ok := db.revoked[string(key.Marshal())] -+ return ok -+} -+ -+const markerCert = "@cert-authority" -+const markerRevoked = "@revoked" -+ -+func nextWord(line []byte) (string, []byte) { -+ i := bytes.IndexAny(line, "\t ") -+ if i == -1 { -+ return string(line), nil -+ } -+ -+ return string(line[:i]), bytes.TrimSpace(line[i:]) -+} -+ -+func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error) { -+ if w, next := nextWord(line); w == markerCert || w == markerRevoked { -+ marker = w -+ line = next -+ } -+ -+ host, line = nextWord(line) -+ if len(line) == 0 { -+ return "", "", nil, errors.New("knownhosts: missing host pattern") -+ } -+ -+ // ignore the keytype as it's in the key blob anyway. -+ _, line = nextWord(line) -+ if len(line) == 0 { -+ return "", "", nil, errors.New("knownhosts: missing key type pattern") -+ } -+ -+ keyBlob, _ := nextWord(line) -+ -+ keyBytes, err := base64.StdEncoding.DecodeString(keyBlob) -+ if err != nil { -+ return "", "", nil, err -+ } -+ key, err = ssh.ParsePublicKey(keyBytes) -+ if err != nil { -+ return "", "", nil, err -+ } -+ -+ return marker, host, key, nil -+} -+ -+func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error { -+ marker, pattern, key, err := parseLine(line) -+ if err != nil { -+ return err -+ } -+ -+ if marker == markerRevoked { -+ db.revoked[string(key.Marshal())] = &KnownKey{ -+ Key: key, -+ Filename: filename, -+ Line: linenum, -+ } -+ -+ return nil -+ } -+ -+ entry := keyDBLine{ -+ cert: marker == markerCert, -+ knownKey: KnownKey{ -+ Filename: filename, -+ Line: linenum, -+ Key: key, -+ }, -+ } -+ -+ if pattern[0] == '|' { -+ entry.matcher, err = newHashedHost(pattern) -+ } else { -+ entry.matcher, err = newHostnameMatcher(pattern) -+ } -+ -+ if err != nil { -+ return err -+ } -+ -+ db.lines = append(db.lines, entry) -+ return nil -+} -+ -+func newHostnameMatcher(pattern string) (matcher, error) { -+ var hps hostPatterns -+ for _, p := range strings.Split(pattern, ",") { -+ if len(p) == 0 { -+ continue -+ } -+ -+ var a addr -+ var negate bool -+ if p[0] == '!' { -+ negate = true -+ p = p[1:] -+ } -+ -+ if len(p) == 0 { -+ return nil, errors.New("knownhosts: negation without following hostname") -+ } -+ -+ var err error -+ if p[0] == '[' { -+ a.host, a.port, err = net.SplitHostPort(p) -+ if err != nil { -+ return nil, err -+ } -+ } else { -+ a.host, a.port, err = net.SplitHostPort(p) -+ if err != nil { -+ a.host = p -+ a.port = "22" -+ } -+ } -+ hps = append(hps, hostPattern{ -+ negate: negate, -+ addr: a, -+ }) -+ } -+ return hps, nil -+} -+ -+// KnownKey represents a key declared in a known_hosts file. -+type KnownKey struct { -+ Key ssh.PublicKey -+ Filename string -+ Line int -+} -+ -+func (k *KnownKey) String() string { -+ return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key)) -+} -+ -+// KeyError is returned if we did not find the key in the host key -+// database, or there was a mismatch. Typically, in batch -+// applications, this should be interpreted as failure. Interactive -+// applications can offer an interactive prompt to the user. -+type KeyError struct { -+ // Want holds the accepted host keys. For each key algorithm, -+ // there can be one hostkey. If Want is empty, the host is -+ // unknown. If Want is non-empty, there was a mismatch, which -+ // can signify a MITM attack. -+ Want []KnownKey -+} -+ -+func (u *KeyError) Error() string { -+ if len(u.Want) == 0 { -+ return "knownhosts: key is unknown" -+ } -+ return "knownhosts: key mismatch" -+} -+ -+// RevokedError is returned if we found a key that was revoked. -+type RevokedError struct { -+ Revoked KnownKey -+} -+ -+func (r *RevokedError) Error() string { -+ return "knownhosts: key is revoked" -+} -+ -+// check checks a key against the host database. This should not be -+// used for verifying certificates. -+func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error { -+ if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil { -+ return &RevokedError{Revoked: *revoked} -+ } -+ -+ host, port, err := net.SplitHostPort(remote.String()) -+ if err != nil { -+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err) -+ } -+ -+ hostToCheck := addr{host, port} -+ if address != "" { -+ // Give preference to the hostname if available. -+ host, port, err := net.SplitHostPort(address) -+ if err != nil { -+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err) -+ } -+ -+ hostToCheck = addr{host, port} -+ } -+ -+ return db.checkAddr(hostToCheck, remoteKey) -+} -+ -+// checkAddr checks if we can find the given public key for the -+// given address. If we only find an entry for the IP address, -+// or only the hostname, then this still succeeds. -+func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { -+ // TODO(hanwen): are these the right semantics? What if there -+ // is just a key for the IP address, but not for the -+ // hostname? -+ -+ // Algorithm => key. -+ knownKeys := map[string]KnownKey{} -+ for _, l := range db.lines { -+ if l.match(a) { -+ typ := l.knownKey.Key.Type() -+ if _, ok := knownKeys[typ]; !ok { -+ knownKeys[typ] = l.knownKey -+ } -+ } -+ } -+ -+ keyErr := &KeyError{} -+ for _, v := range knownKeys { -+ keyErr.Want = append(keyErr.Want, v) -+ } -+ -+ // Unknown remote host. -+ if len(knownKeys) == 0 { -+ return keyErr -+ } -+ -+ // If the remote host starts using a different, unknown key type, we -+ // also interpret that as a mismatch. -+ if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) { -+ return keyErr -+ } -+ -+ return nil -+} -+ -+// The Read function parses file contents. -+func (db *hostKeyDB) Read(r io.Reader, filename string) error { -+ scanner := bufio.NewScanner(r) -+ -+ lineNum := 0 -+ for scanner.Scan() { -+ lineNum++ -+ line := scanner.Bytes() -+ line = bytes.TrimSpace(line) -+ if len(line) == 0 || line[0] == '#' { -+ continue -+ } -+ -+ if err := db.parseLine(line, filename, lineNum); err != nil { -+ return fmt.Errorf("knownhosts: %s:%d: %v", filename, lineNum, err) -+ } -+ } -+ return scanner.Err() -+} -+ -+// New creates a host key callback from the given OpenSSH host key -+// files. The returned callback is for use in -+// ssh.ClientConfig.HostKeyCallback. By preference, the key check -+// operates on the hostname if available, i.e. if a server changes its -+// IP address, the host key check will still succeed, even though a -+// record of the new IP address is not available. -+func New(files ...string) (ssh.HostKeyCallback, error) { -+ db := newHostKeyDB() -+ for _, fn := range files { -+ f, err := os.Open(fn) -+ if err != nil { -+ return nil, err -+ } -+ defer f.Close() -+ if err := db.Read(f, fn); err != nil { -+ return nil, err -+ } -+ } -+ -+ var certChecker ssh.CertChecker -+ certChecker.IsHostAuthority = db.IsHostAuthority -+ certChecker.IsRevoked = db.IsRevoked -+ certChecker.HostKeyFallback = db.check -+ -+ return certChecker.CheckHostKey, nil -+} -+ -+// Normalize normalizes an address into the form used in known_hosts -+func Normalize(address string) string { -+ host, port, err := net.SplitHostPort(address) -+ if err != nil { -+ host = address -+ port = "22" -+ } -+ entry := host -+ if port != "22" { -+ entry = "[" + entry + "]:" + port -+ } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { -+ entry = "[" + entry + "]" -+ } -+ return entry -+} -+ -+// Line returns a line to add append to the known_hosts files. -+func Line(addresses []string, key ssh.PublicKey) string { -+ var trimmed []string -+ for _, a := range addresses { -+ trimmed = append(trimmed, Normalize(a)) -+ } -+ -+ return strings.Join(trimmed, ",") + " " + serialize(key) -+} -+ -+// HashHostname hashes the given hostname. The hostname is not -+// normalized before hashing. -+func HashHostname(hostname string) string { -+ // TODO(hanwen): check if we can safely normalize this always. -+ salt := make([]byte, sha1.Size) -+ -+ _, err := rand.Read(salt) -+ if err != nil { -+ panic(fmt.Sprintf("crypto/rand failure %v", err)) -+ } -+ -+ hash := hashHost(hostname, salt) -+ return encodeHash(sha1HashType, salt, hash) -+} -+ -+func decodeHash(encoded string) (hashType string, salt, hash []byte, err error) { -+ if len(encoded) == 0 || encoded[0] != '|' { -+ err = errors.New("knownhosts: hashed host must start with '|'") -+ return -+ } -+ components := strings.Split(encoded, "|") -+ if len(components) != 4 { -+ err = fmt.Errorf("knownhosts: got %d components, want 3", len(components)) -+ return -+ } -+ -+ hashType = components[1] -+ if salt, err = base64.StdEncoding.DecodeString(components[2]); err != nil { -+ return -+ } -+ if hash, err = base64.StdEncoding.DecodeString(components[3]); err != nil { -+ return -+ } -+ return -+} -+ -+func encodeHash(typ string, salt []byte, hash []byte) string { -+ return strings.Join([]string{"", -+ typ, -+ base64.StdEncoding.EncodeToString(salt), -+ base64.StdEncoding.EncodeToString(hash), -+ }, "|") -+} -+ -+// See https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 -+func hashHost(hostname string, salt []byte) []byte { -+ mac := hmac.New(sha1.New, salt) -+ mac.Write([]byte(hostname)) -+ return mac.Sum(nil) -+} -+ -+type hashedHost struct { -+ salt []byte -+ hash []byte -+} -+ -+const sha1HashType = "1" -+ -+func newHashedHost(encoded string) (*hashedHost, error) { -+ typ, salt, hash, err := decodeHash(encoded) -+ if err != nil { -+ return nil, err -+ } -+ -+ // The type field seems for future algorithm agility, but it's -+ // actually hardcoded in openssh currently, see -+ // https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 -+ if typ != sha1HashType { -+ return nil, fmt.Errorf("knownhosts: got hash type %s, must be '1'", typ) -+ } -+ -+ return &hashedHost{salt: salt, hash: hash}, nil -+} -+ -+func (h *hashedHost) match(a addr) bool { -+ return bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) -+} -diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go -index ac41a4168bfe..19bc67c46422 100644 ---- a/vendor/golang.org/x/crypto/ssh/messages.go -+++ b/vendor/golang.org/x/crypto/ssh/messages.go -@@ -141,6 +141,14 @@ type serviceAcceptMsg struct { - Service string `sshtype:"6"` - } - -+// See RFC 8308, section 2.3 -+const msgExtInfo = 7 -+ -+type extInfoMsg struct { -+ NumExtensions uint32 `sshtype:"7"` -+ Payload []byte `ssh:"rest"` -+} -+ - // See RFC 4252, section 5. - const msgUserAuthRequest = 50 - -@@ -180,11 +188,11 @@ const msgUserAuthInfoRequest = 60 - const msgUserAuthInfoResponse = 61 - - type userAuthInfoRequestMsg struct { -- User string `sshtype:"60"` -- Instruction string -- DeprecatedLanguage string -- NumPrompts uint32 -- Prompts []byte `ssh:"rest"` -+ Name string `sshtype:"60"` -+ Instruction string -+ Language string -+ NumPrompts uint32 -+ Prompts []byte `ssh:"rest"` - } - - // See RFC 4254, section 5.1. -@@ -782,6 +790,8 @@ func decode(packet []byte) (interface{}, error) { - msg = new(serviceRequestMsg) - case msgServiceAccept: - msg = new(serviceAcceptMsg) -+ case msgExtInfo: -+ msg = new(extInfoMsg) - case msgKexInit: - msg = new(kexInitMsg) - case msgKexDHInit: -@@ -843,6 +853,7 @@ var packetTypeNames = map[byte]string{ - msgDisconnect: "disconnectMsg", - msgServiceRequest: "serviceRequestMsg", - msgServiceAccept: "serviceAcceptMsg", -+ msgExtInfo: "extInfoMsg", - msgKexInit: "kexInitMsg", - msgKexDHInit: "kexDHInitMsg", - msgKexDHReply: "kexDHReplyMsg", -diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go -index 7d42a8c88d26..70045bdfd82d 100644 ---- a/vendor/golang.org/x/crypto/ssh/server.go -+++ b/vendor/golang.org/x/crypto/ssh/server.go -@@ -120,7 +120,7 @@ type ServerConfig struct { - } - - // AddHostKey adds a private key as a host key. If an existing host --// key exists with the same algorithm, it is overwritten. Each server -+// key exists with the same public key format, it is replaced. Each server - // config must have at least one host key. - func (s *ServerConfig) AddHostKey(key Signer) { - for i, k := range s.hostKeys { -@@ -212,9 +212,10 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha - } - - // signAndMarshal signs the data with the appropriate algorithm, --// and serializes the result in SSH wire format. --func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) { -- sig, err := k.Sign(rand, data) -+// and serializes the result in SSH wire format. algo is the negotiate -+// algorithm and may be a certificate type. -+func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) { -+ sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) - if err != nil { - return nil, err - } -@@ -284,7 +285,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) - - func isAcceptableAlgo(algo string) bool { - switch algo { -- case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519, -+ case KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519, - CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: - return true - } -@@ -553,6 +554,7 @@ userAuthLoop: - if !ok || len(payload) > 0 { - return nil, parseError(msgUserAuthRequest) - } -+ - // Ensure the public key algo and signature algo - // are supported. Compare the private key - // algorithm name that corresponds to algo with -@@ -562,7 +564,12 @@ userAuthLoop: - authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format) - break - } -- signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData) -+ if underlyingAlgo(algo) != sig.Format { -+ authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo) -+ break -+ } -+ -+ signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData) - - if err := pubKey.Verify(signedData, sig); err != nil { - return nil, err -@@ -572,6 +579,10 @@ userAuthLoop: - perms = candidate.perms - } - case "gssapi-with-mic": -+ if config.GSSAPIWithMICConfig == nil { -+ authErr = errors.New("ssh: gssapi-with-mic auth not configured") -+ break -+ } - gssapiConfig := config.GSSAPIWithMICConfig - userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload) - if err != nil { -@@ -629,6 +640,30 @@ userAuthLoop: - } - - authFailures++ -+ if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries { -+ // If we have hit the max attempts, don't bother sending the -+ // final SSH_MSG_USERAUTH_FAILURE message, since there are -+ // no more authentication methods which can be attempted, -+ // and this message may cause the client to re-attempt -+ // authentication while we send the disconnect message. -+ // Continue, and trigger the disconnect at the start of -+ // the loop. -+ // -+ // The SSH specification is somewhat confusing about this, -+ // RFC 4252 Section 5.1 requires each authentication failure -+ // be responded to with a respective SSH_MSG_USERAUTH_FAILURE -+ // message, but Section 4 says the server should disconnect -+ // after some number of attempts, but it isn't explicit which -+ // message should take precedence (i.e. should there be a failure -+ // message than a disconnect message, or if we are going to -+ // disconnect, should we only send that message.) -+ // -+ // Either way, OpenSSH disconnects immediately after the last -+ // failed authnetication attempt, and given they are typically -+ // considered the golden implementation it seems reasonable -+ // to match that behavior. -+ continue -+ } - - var failureMsg userAuthFailureMsg - if config.PasswordCallback != nil { -@@ -666,7 +701,7 @@ type sshClientKeyboardInteractive struct { - *connection - } - --func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) { -+func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) { - if len(questions) != len(echos) { - return nil, errors.New("ssh: echos and questions must have equal length") - } -@@ -678,6 +713,7 @@ func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, quest - } - - if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ -+ Name: name, - Instruction: instruction, - NumPrompts: uint32(len(questions)), - Prompts: prompts, -diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go -index d3321f6b784b..eca31a22d593 100644 ---- a/vendor/golang.org/x/crypto/ssh/session.go -+++ b/vendor/golang.org/x/crypto/ssh/session.go -@@ -85,6 +85,7 @@ const ( - IXANY = 39 - IXOFF = 40 - IMAXBEL = 41 -+ IUTF8 = 42 // RFC 8160 - ISIG = 50 - ICANON = 51 - XCASE = 52 -diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go -new file mode 100644 -index 000000000000..a4d1919a9e7d ---- /dev/null -+++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go -@@ -0,0 +1,76 @@ -+// 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 terminal provides support functions for dealing with terminals, as -+// commonly found on UNIX systems. -+// -+// Deprecated: this package moved to golang.org/x/term. -+package terminal -+ -+import ( -+ "io" -+ -+ "golang.org/x/term" -+) -+ -+// EscapeCodes contains escape sequences that can be written to the terminal in -+// order to achieve different styles of text. -+type EscapeCodes = term.EscapeCodes -+ -+// Terminal contains the state for running a VT100 terminal that is capable of -+// reading lines of input. -+type Terminal = term.Terminal -+ -+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is -+// a local terminal, that terminal must first have been put into raw mode. -+// prompt is a string that is written at the start of each input line (i.e. -+// "> "). -+func NewTerminal(c io.ReadWriter, prompt string) *Terminal { -+ return term.NewTerminal(c, prompt) -+} -+ -+// ErrPasteIndicator may be returned from ReadLine as the error, in addition -+// to valid line data. It indicates that bracketed paste mode is enabled and -+// that the returned line consists only of pasted data. Programs may wish to -+// interpret pasted data more literally than typed data. -+var ErrPasteIndicator = term.ErrPasteIndicator -+ -+// State contains the state of a terminal. -+type State = term.State -+ -+// IsTerminal returns whether the given file descriptor is a terminal. -+func IsTerminal(fd int) bool { -+ return term.IsTerminal(fd) -+} -+ -+// ReadPassword reads a line of input from a terminal without local echo. This -+// is commonly used for inputting passwords and other sensitive data. The slice -+// returned does not include the \n. -+func ReadPassword(fd int) ([]byte, error) { -+ return term.ReadPassword(fd) -+} -+ -+// MakeRaw puts the terminal connected to the given file descriptor into raw -+// mode and returns the previous state of the terminal so that it can be -+// restored. -+func MakeRaw(fd int) (*State, error) { -+ return term.MakeRaw(fd) -+} -+ -+// Restore restores the terminal connected to the given file descriptor to a -+// previous state. -+func Restore(fd int, oldState *State) error { -+ return term.Restore(fd, oldState) -+} -+ -+// GetState returns the current state of a terminal which may be useful to -+// restore the terminal after a signal. -+func GetState(fd int) (*State, error) { -+ return term.GetState(fd) -+} -+ -+// GetSize returns the dimensions of the given terminal. -+func GetSize(fd int) (width, height int, err error) { -+ return term.GetSize(fd) -+} -diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go -index 49ddc2e7de46..acf5a21bbb0e 100644 ---- a/vendor/golang.org/x/crypto/ssh/transport.go -+++ b/vendor/golang.org/x/crypto/ssh/transport.go -@@ -238,15 +238,19 @@ var ( - // (to setup server->client keys) or clientKeys (for client->server keys). - func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { - cipherMode := cipherModes[algs.Cipher] -- macMode := macModes[algs.MAC] - - iv := make([]byte, cipherMode.ivSize) - key := make([]byte, cipherMode.keySize) -- macKey := make([]byte, macMode.keySize) - - generateKeyMaterial(iv, d.ivTag, kex) - generateKeyMaterial(key, d.keyTag, kex) -- generateKeyMaterial(macKey, d.macKeyTag, kex) -+ -+ var macKey []byte -+ if !aeadCiphers[algs.Cipher] { -+ macMode := macModes[algs.MAC] -+ macKey = make([]byte, macMode.keySize) -+ generateKeyMaterial(macKey, d.macKeyTag, kex) -+ } - - return cipherModes[algs.Cipher].create(key, iv, macKey, algs) - } -diff --git a/vendor/golang.org/x/crypto/tea/cipher.go b/vendor/golang.org/x/crypto/tea/cipher.go -new file mode 100644 -index 000000000000..c1ff90e048d0 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/tea/cipher.go -@@ -0,0 +1,116 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package tea implements the TEA algorithm, as defined in Needham and -+// Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithm”. See -+// http://www.cix.co.uk/~klockstone/tea.pdf for details. -+// -+// TEA is a legacy cipher and its short block size makes it vulnerable to -+// birthday bound attacks (see https://sweet32.info). It should only be used -+// where compatibility with legacy systems, not security, is the goal. -+// -+// Deprecated: any new system should use AES (from crypto/aes, if necessary in -+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package tea -+ -+import ( -+ "crypto/cipher" -+ "encoding/binary" -+ "errors" -+) -+ -+const ( -+ // BlockSize is the size of a TEA block, in bytes. -+ BlockSize = 8 -+ -+ // KeySize is the size of a TEA key, in bytes. -+ KeySize = 16 -+ -+ // delta is the TEA key schedule constant. -+ delta = 0x9e3779b9 -+ -+ // numRounds is the standard number of rounds in TEA. -+ numRounds = 64 -+) -+ -+// tea is an instance of the TEA cipher with a particular key. -+type tea struct { -+ key [16]byte -+ rounds int -+} -+ -+// NewCipher returns an instance of the TEA cipher with the standard number of -+// rounds. The key argument must be 16 bytes long. -+func NewCipher(key []byte) (cipher.Block, error) { -+ return NewCipherWithRounds(key, numRounds) -+} -+ -+// NewCipherWithRounds returns an instance of the TEA cipher with a given -+// number of rounds, which must be even. The key argument must be 16 bytes -+// long. -+func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) { -+ if len(key) != 16 { -+ return nil, errors.New("tea: incorrect key size") -+ } -+ -+ if rounds&1 != 0 { -+ return nil, errors.New("tea: odd number of rounds specified") -+ } -+ -+ c := &tea{ -+ rounds: rounds, -+ } -+ copy(c.key[:], key) -+ -+ return c, nil -+} -+ -+// BlockSize returns the TEA block size, which is eight bytes. It is necessary -+// to satisfy the Block interface in the package "crypto/cipher". -+func (*tea) BlockSize() int { -+ return BlockSize -+} -+ -+// Encrypt encrypts the 8 byte buffer src using the key in t and stores the -+// result in dst. Note that for amounts of data larger than a block, it is not -+// safe to just call Encrypt on successive blocks; instead, use an encryption -+// mode like CBC (see crypto/cipher/cbc.go). -+func (t *tea) Encrypt(dst, src []byte) { -+ e := binary.BigEndian -+ v0, v1 := e.Uint32(src), e.Uint32(src[4:]) -+ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) -+ -+ sum := uint32(0) -+ delta := uint32(delta) -+ -+ for i := 0; i < t.rounds/2; i++ { -+ sum += delta -+ v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) -+ v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) -+ } -+ -+ e.PutUint32(dst, v0) -+ e.PutUint32(dst[4:], v1) -+} -+ -+// Decrypt decrypts the 8 byte buffer src using the key in t and stores the -+// result in dst. -+func (t *tea) Decrypt(dst, src []byte) { -+ e := binary.BigEndian -+ v0, v1 := e.Uint32(src), e.Uint32(src[4:]) -+ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) -+ -+ delta := uint32(delta) -+ sum := delta * uint32(t.rounds/2) // in general, sum = delta * n -+ -+ for i := 0; i < t.rounds/2; i++ { -+ v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) -+ v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) -+ sum -= delta -+ } -+ -+ e.PutUint32(dst, v0) -+ e.PutUint32(dst[4:], v1) -+} -diff --git a/vendor/golang.org/x/crypto/twofish/twofish.go b/vendor/golang.org/x/crypto/twofish/twofish.go -new file mode 100644 -index 000000000000..1197d7513227 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/twofish/twofish.go -@@ -0,0 +1,348 @@ -+// 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 twofish implements Bruce Schneier's Twofish encryption algorithm. -+// -+// Deprecated: Twofish is a legacy cipher and should not be used for new -+// applications. Also, this package does not and will not provide an optimized -+// implementation. Instead, use AES (from crypto/aes, if necessary in an AEAD -+// mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package twofish // import "golang.org/x/crypto/twofish" -+ -+// Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH] -+ -+// This code is a port of the LibTom C implementation. -+// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt. -+// LibTomCrypt is free for all purposes under the public domain. -+// It was heavily inspired by the go blowfish package. -+ -+import "strconv" -+ -+// BlockSize is the constant block size of Twofish. -+const BlockSize = 16 -+ -+const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2 -+const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3 -+ -+// A Cipher is an instance of Twofish encryption using a particular key. -+type Cipher struct { -+ s [4][256]uint32 -+ k [40]uint32 -+} -+ -+type KeySizeError int -+ -+func (k KeySizeError) Error() string { -+ return "crypto/twofish: invalid key size " + strconv.Itoa(int(k)) -+} -+ -+// NewCipher creates and returns a Cipher. -+// The key argument should be the Twofish key, 16, 24 or 32 bytes. -+func NewCipher(key []byte) (*Cipher, error) { -+ keylen := len(key) -+ -+ if keylen != 16 && keylen != 24 && keylen != 32 { -+ return nil, KeySizeError(keylen) -+ } -+ -+ // k is the number of 64 bit words in key -+ k := keylen / 8 -+ -+ // Create the S[..] words -+ var S [4 * 4]byte -+ for i := 0; i < k; i++ { -+ // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] -+ for j, rsRow := range rs { -+ for k, rsVal := range rsRow { -+ S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial) -+ } -+ } -+ } -+ -+ // Calculate subkeys -+ c := new(Cipher) -+ var tmp [4]byte -+ for i := byte(0); i < 20; i++ { -+ // A = h(p * 2x, Me) -+ for j := range tmp { -+ tmp[j] = 2 * i -+ } -+ A := h(tmp[:], key, 0) -+ -+ // B = rolc(h(p * (2x + 1), Mo), 8) -+ for j := range tmp { -+ tmp[j] = 2*i + 1 -+ } -+ B := h(tmp[:], key, 1) -+ B = rol(B, 8) -+ -+ c.k[2*i] = A + B -+ -+ // K[2i+1] = (A + 2B) <<< 9 -+ c.k[2*i+1] = rol(2*B+A, 9) -+ } -+ -+ // Calculate sboxes -+ switch k { -+ case 2: -+ for i := range c.s[0] { -+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0) -+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1) -+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2) -+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3) -+ } -+ case 3: -+ for i := range c.s[0] { -+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0) -+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1) -+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2) -+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3) -+ } -+ default: -+ for i := range c.s[0] { -+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) -+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) -+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) -+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3) -+ } -+ } -+ -+ return c, nil -+} -+ -+// BlockSize returns the Twofish block size, 16 bytes. -+func (c *Cipher) BlockSize() int { return BlockSize } -+ -+// store32l stores src in dst in little-endian form. -+func store32l(dst []byte, src uint32) { -+ dst[0] = byte(src) -+ dst[1] = byte(src >> 8) -+ dst[2] = byte(src >> 16) -+ dst[3] = byte(src >> 24) -+ return -+} -+ -+// load32l reads a little-endian uint32 from src. -+func load32l(src []byte) uint32 { -+ return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24 -+} -+ -+// rol returns x after a left circular rotation of y bits. -+func rol(x, y uint32) uint32 { -+ return (x << (y & 31)) | (x >> (32 - (y & 31))) -+} -+ -+// ror returns x after a right circular rotation of y bits. -+func ror(x, y uint32) uint32 { -+ return (x >> (y & 31)) | (x << (32 - (y & 31))) -+} -+ -+// The RS matrix. See [TWOFISH] 4.3 -+var rs = [4][8]byte{ -+ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E}, -+ {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5}, -+ {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19}, -+ {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03}, -+} -+ -+// sbox tables -+var sbox = [2][256]byte{ -+ { -+ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, -+ 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, -+ 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, -+ 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61, -+ 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, -+ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, -+ 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, -+ 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, -+ 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, -+ 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, -+ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, -+ 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a, -+ 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, -+ 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, -+ 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, -+ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0, -+ }, -+ { -+ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, -+ 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f, -+ 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, -+ 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, -+ 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, -+ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, -+ 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, -+ 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, -+ 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, -+ 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, -+ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, -+ 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64, -+ 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, -+ 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, -+ 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, -+ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91, -+ }, -+} -+ -+// gfMult returns a·b in GF(2^8)/p -+func gfMult(a, b byte, p uint32) byte { -+ B := [2]uint32{0, uint32(b)} -+ P := [2]uint32{0, p} -+ var result uint32 -+ -+ // branchless GF multiplier -+ for i := 0; i < 7; i++ { -+ result ^= B[a&1] -+ a >>= 1 -+ B[1] = P[B[1]>>7] ^ (B[1] << 1) -+ } -+ result ^= B[a&1] -+ return byte(result) -+} -+ -+// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0] -+func mdsColumnMult(in byte, col int) uint32 { -+ mul01 := in -+ mul5B := gfMult(in, 0x5B, mdsPolynomial) -+ mulEF := gfMult(in, 0xEF, mdsPolynomial) -+ -+ switch col { -+ case 0: -+ return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24 -+ case 1: -+ return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24 -+ case 2: -+ return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24 -+ case 3: -+ return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24 -+ } -+ -+ panic("unreachable") -+} -+ -+// h implements the S-box generation function. See [TWOFISH] 4.3.5 -+func h(in, key []byte, offset int) uint32 { -+ var y [4]byte -+ for x := range y { -+ y[x] = in[x] -+ } -+ switch len(key) / 8 { -+ case 4: -+ y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0] -+ y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1] -+ y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2] -+ y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3] -+ fallthrough -+ case 3: -+ y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0] -+ y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1] -+ y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2] -+ y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3] -+ fallthrough -+ case 2: -+ y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]] -+ y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]] -+ y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]] -+ y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]] -+ } -+ // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] -+ var mdsMult uint32 -+ for i := range y { -+ mdsMult ^= mdsColumnMult(y[i], i) -+ } -+ return mdsMult -+} -+ -+// Encrypt encrypts a 16-byte block from src to dst, which may overlap. -+// Note that for amounts of data larger than a block, -+// it is not safe to just call Encrypt on successive blocks; -+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -+func (c *Cipher) Encrypt(dst, src []byte) { -+ S1 := c.s[0] -+ S2 := c.s[1] -+ S3 := c.s[2] -+ S4 := c.s[3] -+ -+ // Load input -+ ia := load32l(src[0:4]) -+ ib := load32l(src[4:8]) -+ ic := load32l(src[8:12]) -+ id := load32l(src[12:16]) -+ -+ // Pre-whitening -+ ia ^= c.k[0] -+ ib ^= c.k[1] -+ ic ^= c.k[2] -+ id ^= c.k[3] -+ -+ for i := 0; i < 8; i++ { -+ k := c.k[8+i*4 : 12+i*4] -+ t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] -+ t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 -+ ic = ror(ic^(t1+k[0]), 1) -+ id = rol(id, 1) ^ (t2 + t1 + k[1]) -+ -+ t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] -+ t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 -+ ia = ror(ia^(t1+k[2]), 1) -+ ib = rol(ib, 1) ^ (t2 + t1 + k[3]) -+ } -+ -+ // Output with "undo last swap" -+ ta := ic ^ c.k[4] -+ tb := id ^ c.k[5] -+ tc := ia ^ c.k[6] -+ td := ib ^ c.k[7] -+ -+ store32l(dst[0:4], ta) -+ store32l(dst[4:8], tb) -+ store32l(dst[8:12], tc) -+ store32l(dst[12:16], td) -+} -+ -+// Decrypt decrypts a 16-byte block from src to dst, which may overlap. -+func (c *Cipher) Decrypt(dst, src []byte) { -+ S1 := c.s[0] -+ S2 := c.s[1] -+ S3 := c.s[2] -+ S4 := c.s[3] -+ -+ // Load input -+ ta := load32l(src[0:4]) -+ tb := load32l(src[4:8]) -+ tc := load32l(src[8:12]) -+ td := load32l(src[12:16]) -+ -+ // Undo undo final swap -+ ia := tc ^ c.k[6] -+ ib := td ^ c.k[7] -+ ic := ta ^ c.k[4] -+ id := tb ^ c.k[5] -+ -+ for i := 8; i > 0; i-- { -+ k := c.k[4+i*4 : 8+i*4] -+ t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] -+ t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 -+ ia = rol(ia, 1) ^ (t1 + k[2]) -+ ib = ror(ib^(t2+t1+k[3]), 1) -+ -+ t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] -+ t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 -+ ic = rol(ic, 1) ^ (t1 + k[0]) -+ id = ror(id^(t2+t1+k[1]), 1) -+ } -+ -+ // Undo pre-whitening -+ ia ^= c.k[0] -+ ib ^= c.k[1] -+ ic ^= c.k[2] -+ id ^= c.k[3] -+ -+ store32l(dst[0:4], ia) -+ store32l(dst[4:8], ib) -+ store32l(dst[8:12], ic) -+ store32l(dst[12:16], id) -+} -diff --git a/vendor/golang.org/x/crypto/xtea/block.go b/vendor/golang.org/x/crypto/xtea/block.go -new file mode 100644 -index 000000000000..fcb4e4d0003c ---- /dev/null -+++ b/vendor/golang.org/x/crypto/xtea/block.go -@@ -0,0 +1,66 @@ -+// Copyright 2009 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. -+ -+/* -+ Implementation adapted from Needham and Wheeler's paper: -+ http://www.cix.co.uk/~klockstone/xtea.pdf -+ -+ A precalculated look up table is used during encryption/decryption for values that are based purely on the key. -+*/ -+ -+package xtea -+ -+// XTEA is based on 64 rounds. -+const numRounds = 64 -+ -+// blockToUint32 reads an 8 byte slice into two uint32s. -+// The block is treated as big endian. -+func blockToUint32(src []byte) (uint32, uint32) { -+ r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ return r0, r1 -+} -+ -+// uint32ToBlock writes two uint32s into an 8 byte data block. -+// Values are written as big endian. -+func uint32ToBlock(v0, v1 uint32, dst []byte) { -+ dst[0] = byte(v0 >> 24) -+ dst[1] = byte(v0 >> 16) -+ dst[2] = byte(v0 >> 8) -+ dst[3] = byte(v0) -+ dst[4] = byte(v1 >> 24) -+ dst[5] = byte(v1 >> 16) -+ dst[6] = byte(v1 >> 8) -+ dst[7] = byte(v1 >> 0) -+} -+ -+// encryptBlock encrypts a single 8 byte block using XTEA. -+func encryptBlock(c *Cipher, dst, src []byte) { -+ v0, v1 := blockToUint32(src) -+ -+ // Two rounds of XTEA applied per loop -+ for i := 0; i < numRounds; { -+ v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] -+ i++ -+ v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] -+ i++ -+ } -+ -+ uint32ToBlock(v0, v1, dst) -+} -+ -+// decryptBlock decrypts a single 8 byte block using XTEA. -+func decryptBlock(c *Cipher, dst, src []byte) { -+ v0, v1 := blockToUint32(src) -+ -+ // Two rounds of XTEA applied per loop -+ for i := numRounds; i > 0; { -+ i-- -+ v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] -+ i-- -+ v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] -+ } -+ -+ uint32ToBlock(v0, v1, dst) -+} -diff --git a/vendor/golang.org/x/crypto/xtea/cipher.go b/vendor/golang.org/x/crypto/xtea/cipher.go -new file mode 100644 -index 000000000000..a4c2fd02b320 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/xtea/cipher.go -@@ -0,0 +1,90 @@ -+// Copyright 2009 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 xtea implements XTEA encryption, as defined in Needham and Wheeler's -+// 1997 technical report, "Tea extensions." -+// -+// XTEA is a legacy cipher and its short block size makes it vulnerable to -+// birthday bound attacks (see https://sweet32.info). It should only be used -+// where compatibility with legacy systems, not security, is the goal. -+// -+// Deprecated: any new system should use AES (from crypto/aes, if necessary in -+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package xtea // import "golang.org/x/crypto/xtea" -+ -+// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf -+ -+import "strconv" -+ -+// The XTEA block size in bytes. -+const BlockSize = 8 -+ -+// A Cipher is an instance of an XTEA cipher using a particular key. -+type Cipher struct { -+ // table contains a series of precalculated values that are used each round. -+ table [64]uint32 -+} -+ -+type KeySizeError int -+ -+func (k KeySizeError) Error() string { -+ return "crypto/xtea: invalid key size " + strconv.Itoa(int(k)) -+} -+ -+// NewCipher creates and returns a new Cipher. -+// The key argument should be the XTEA key. -+// XTEA only supports 128 bit (16 byte) keys. -+func NewCipher(key []byte) (*Cipher, error) { -+ k := len(key) -+ switch k { -+ default: -+ return nil, KeySizeError(k) -+ case 16: -+ break -+ } -+ -+ c := new(Cipher) -+ initCipher(c, key) -+ -+ return c, nil -+} -+ -+// BlockSize returns the XTEA block size, 8 bytes. -+// It is necessary to satisfy the Block interface in the -+// package "crypto/cipher". -+func (c *Cipher) BlockSize() int { return BlockSize } -+ -+// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst. -+// Note that for amounts of data larger than a block, -+// it is not safe to just call Encrypt on successive blocks; -+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -+func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) } -+ -+// Decrypt decrypts the 8 byte buffer src using the key and stores the result in dst. -+func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) } -+ -+// initCipher initializes the cipher context by creating a look up table -+// of precalculated values that are based on the key. -+func initCipher(c *Cipher, key []byte) { -+ // Load the key into four uint32s -+ var k [4]uint32 -+ for i := 0; i < len(k); i++ { -+ j := i << 2 // Multiply by 4 -+ k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3]) -+ } -+ -+ // Precalculate the table -+ const delta = 0x9E3779B9 -+ var sum uint32 -+ -+ // Two rounds of XTEA applied per loop -+ for i := 0; i < numRounds; { -+ c.table[i] = sum + k[sum&3] -+ i++ -+ sum += delta -+ c.table[i] = sum + k[(sum>>11)&3] -+ i++ -+ } -+} -diff --git a/vendor/golang.org/x/crypto/xts/xts.go b/vendor/golang.org/x/crypto/xts/xts.go -new file mode 100644 -index 000000000000..b51308e95e52 ---- /dev/null -+++ b/vendor/golang.org/x/crypto/xts/xts.go -@@ -0,0 +1,164 @@ -+// Copyright 2012 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 xts implements the XTS cipher mode as specified in IEEE P1619/D16. -+// -+// XTS mode is typically used for disk encryption, which presents a number of -+// novel problems that make more common modes inapplicable. The disk is -+// conceptually an array of sectors and we must be able to encrypt and decrypt -+// a sector in isolation. However, an attacker must not be able to transpose -+// two sectors of plaintext by transposing their ciphertext. -+// -+// XTS wraps a block cipher with Rogaway's XEX mode in order to build a -+// tweakable block cipher. This allows each sector to have a unique tweak and -+// effectively create a unique key for each sector. -+// -+// XTS does not provide any authentication. An attacker can manipulate the -+// ciphertext and randomise a block (16 bytes) of the plaintext. This package -+// does not implement ciphertext-stealing so sectors must be a multiple of 16 -+// bytes. -+// -+// Note that XTS is usually not appropriate for any use besides disk encryption. -+// Most users should use an AEAD mode like GCM (from crypto/cipher.NewGCM) instead. -+package xts // import "golang.org/x/crypto/xts" -+ -+import ( -+ "crypto/cipher" -+ "encoding/binary" -+ "errors" -+ "sync" -+ -+ "golang.org/x/crypto/internal/subtle" -+) -+ -+// Cipher contains an expanded key structure. It is safe for concurrent use if -+// the underlying block cipher is safe for concurrent use. -+type Cipher struct { -+ k1, k2 cipher.Block -+} -+ -+// blockSize is the block size that the underlying cipher must have. XTS is -+// only defined for 16-byte ciphers. -+const blockSize = 16 -+ -+var tweakPool = sync.Pool{ -+ New: func() interface{} { -+ return new([blockSize]byte) -+ }, -+} -+ -+// NewCipher creates a Cipher given a function for creating the underlying -+// block cipher (which must have a block size of 16 bytes). The key must be -+// twice the length of the underlying cipher's key. -+func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) { -+ c = new(Cipher) -+ if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil { -+ return -+ } -+ c.k2, err = cipherFunc(key[len(key)/2:]) -+ -+ if c.k1.BlockSize() != blockSize { -+ err = errors.New("xts: cipher does not have a block size of 16") -+ } -+ -+ return -+} -+ -+// Encrypt encrypts a sector of plaintext and puts the result into ciphertext. -+// Plaintext and ciphertext must overlap entirely or not at all. -+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. -+func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { -+ if len(ciphertext) < len(plaintext) { -+ panic("xts: ciphertext is smaller than plaintext") -+ } -+ if len(plaintext)%blockSize != 0 { -+ panic("xts: plaintext is not a multiple of the block size") -+ } -+ if subtle.InexactOverlap(ciphertext[:len(plaintext)], plaintext) { -+ panic("xts: invalid buffer overlap") -+ } -+ -+ tweak := tweakPool.Get().(*[blockSize]byte) -+ for i := range tweak { -+ tweak[i] = 0 -+ } -+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum) -+ -+ c.k2.Encrypt(tweak[:], tweak[:]) -+ -+ for len(plaintext) > 0 { -+ for j := range tweak { -+ ciphertext[j] = plaintext[j] ^ tweak[j] -+ } -+ c.k1.Encrypt(ciphertext, ciphertext) -+ for j := range tweak { -+ ciphertext[j] ^= tweak[j] -+ } -+ plaintext = plaintext[blockSize:] -+ ciphertext = ciphertext[blockSize:] -+ -+ mul2(tweak) -+ } -+ -+ tweakPool.Put(tweak) -+} -+ -+// Decrypt decrypts a sector of ciphertext and puts the result into plaintext. -+// Plaintext and ciphertext must overlap entirely or not at all. -+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. -+func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { -+ if len(plaintext) < len(ciphertext) { -+ panic("xts: plaintext is smaller than ciphertext") -+ } -+ if len(ciphertext)%blockSize != 0 { -+ panic("xts: ciphertext is not a multiple of the block size") -+ } -+ if subtle.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) { -+ panic("xts: invalid buffer overlap") -+ } -+ -+ tweak := tweakPool.Get().(*[blockSize]byte) -+ for i := range tweak { -+ tweak[i] = 0 -+ } -+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum) -+ -+ c.k2.Encrypt(tweak[:], tweak[:]) -+ -+ for len(ciphertext) > 0 { -+ for j := range tweak { -+ plaintext[j] = ciphertext[j] ^ tweak[j] -+ } -+ c.k1.Decrypt(plaintext, plaintext) -+ for j := range tweak { -+ plaintext[j] ^= tweak[j] -+ } -+ plaintext = plaintext[blockSize:] -+ ciphertext = ciphertext[blockSize:] -+ -+ mul2(tweak) -+ } -+ -+ tweakPool.Put(tweak) -+} -+ -+// mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of -+// x¹²⁸ + x⁷ + x² + x + 1. -+func mul2(tweak *[blockSize]byte) { -+ var carryIn byte -+ for j := range tweak { -+ carryOut := tweak[j] >> 7 -+ tweak[j] = (tweak[j] << 1) + carryIn -+ carryIn = carryOut -+ } -+ if carryIn != 0 { -+ // If we have a carry bit then we need to subtract a multiple -+ // of the irreducible polynomial (x¹²⁸ + x⁷ + x² + x + 1). -+ // By dropping the carry bit, we're subtracting the x^128 term -+ // so all that remains is to subtract x⁷ + x² + x + 1. -+ // Subtraction (and addition) in this representation is just -+ // XOR. -+ tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1 -+ } -+} --- -2.38.1 - diff --git a/0007-bsc1200022-fifo.Close-prevent-possible-panic-if-fifo.patch b/0007-bsc1200022-fifo.Close-prevent-possible-panic-if-fifo.patch deleted file mode 100644 index a6b7acb..0000000 --- a/0007-bsc1200022-fifo.Close-prevent-possible-panic-if-fifo.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 6451aa1559ce5a135f599682ab33721e116925bd Mon Sep 17 00:00:00 2001 -From: Sebastiaan van Stijn -Date: Fri, 29 Jan 2021 14:55:08 +0100 -Subject: [PATCH 7/7] bsc1200022: fifo.Close(): prevent possible panic if fifo - is nil - -I'm not sure if this is the right approach, and synchronisation should probably -be added elsewhere to fix the underlying issue. - -Trying to prevent a panic that was seen on container restore in th docker daemon: - - panic: runtime error: invalid memory address or nil pointer dereference - [signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x5586c892a7a4] - - goroutine 420 [running]: - github.com/docker/docker/vendor/github.com/containerd/fifo.(*fifo).Close(0x0, 0x0, 0x0) - /go/src/github.com/docker/docker/vendor/github.com/containerd/fifo/fifo.go:208 +0x44 - github.com/docker/docker/vendor/github.com/containerd/containerd/cio.(*cio).Close(0xc000d06f60, 0x5586cb5654d0, 0xc000d8e9e8) - /go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/cio/io.go:203 +0x90 - github.com/docker/docker/libcontainerd/remote.(*client).Restore.func1(0xc0008bf820, 0xc0008a2040) - /go/src/github.com/docker/docker/libcontainerd/remote/client.go:86 +0x5a - github.com/docker/docker/libcontainerd/remote.(*client).Restore(0xc00098e5b0, 0x5586cb61c7c0, 0xc000052088, 0xc0011b6500, 0x40, 0xc0008bf810, 0x5586cb05cf00, 0xffffffffffffffff, 0x0, 0x0, ...) - /go/src/github.com/docker/docker/libcontainerd/remote/client.go:107 +0x923 - github.com/docker/docker/daemon.(*Daemon).restore.func3(0xc00079d9e0, 0xc000a38230, 0xc00000c1e0, 0xc00079d9a8, 0xc000d84f00, 0xc000d84ed0, 0xc000d84ea0, 0xc00128a280) - /go/src/github.com/docker/docker/daemon/daemon.go:351 +0x48a - created by github.com/docker/docker/daemon.(*Daemon).restore - /go/src/github.com/docker/docker/daemon/daemon.go:319 +0x4b3 - -If the fifo is nil, there's nothing to be done in Close(), so returning early -in that situation. - -Backport: -SUSE-Bugs: bsc#1200022 -Signed-off-by: Sebastiaan van Stijn ---- - vendor/github.com/containerd/fifo/fifo.go | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/vendor/github.com/containerd/fifo/fifo.go b/vendor/github.com/containerd/fifo/fifo.go -index 96c214f270bf..c3eec295b578 100644 ---- a/vendor/github.com/containerd/fifo/fifo.go -+++ b/vendor/github.com/containerd/fifo/fifo.go -@@ -204,6 +204,10 @@ func (f *fifo) Write(b []byte) (int, error) { - // before open(2) has returned and fifo was never opened. - func (f *fifo) Close() (retErr error) { - for { -+ if f == nil { -+ return -+ } -+ - select { - case <-f.closed: - f.handle.Close() --- -2.38.1 - diff --git a/_service b/_service index 8c0e48d..d3b3a76 100644 --- a/_service +++ b/_service @@ -3,26 +3,18 @@ https://github.com/moby/moby.git git .git - 20.10.23_ce_%h - v20.10.23 + 23.0.5_ce_%h + v23.0.5 docker https://github.com/docker/cli.git git .git - 20.10.23_ce - v20.10.23 + 23.0.5_ce + v23.0.5 docker-cli - - https://github.com/docker/libnetwork.git - git - .git - %H - 05b93e0d3a95952f70c113b0bc5bdb538d7afdd7 - docker-libnetwork - docker-*.tar xz diff --git a/cli-0001-docs-include-required-tools-in-source-tree.patch b/cli-0001-docs-include-required-tools-in-source-tree.patch new file mode 100644 index 0000000..edfa78c --- /dev/null +++ b/cli-0001-docs-include-required-tools-in-source-tree.patch @@ -0,0 +1,23756 @@ +From 0c35d956eb289bd6186e2865a779d2615c471b94 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Wed, 26 Apr 2023 10:13:48 +1000 +Subject: [PATCH] docs: include required tools in source tree + +In order to be able to build the documentation without internet access +(as is required by some distribution build systems), all of the source +code needed for the build needs to be available in the source tarball. + +This used to be possible with the docker-cli sources but was +accidentally broken with some CI changes that switched to downloading +the tools (by modifying go.mod as part of the docs build script). + +This pattern also maked documentation builds less reproducible since the +tool version used was not based on the source code version. + +Fixes: commit 7dc35c03fca5 ("validate manpages target") +Fixes: commit a650f4ddd008 ("switch to cli-docs-tool for yaml docs generation") +Signed-off-by: Aleksa Sarai +--- + docs/generate/go.mod | 13 - + docs/generate/tools.go | 8 - + import.go | 17 + + man/go.mod | 15 - + man/tools.go | 11 - + scripts/docs/generate-man.sh | 32 +- + scripts/docs/generate-md.sh | 23 +- + scripts/docs/generate-yaml.sh | 28 +- + vendor.mod | 4 + + vendor.sum | 4 + + .../cpuguy83/go-md2man/v2/.gitignore | 2 + + .../cpuguy83/go-md2man/v2/Dockerfile | 20 + + .../cpuguy83/go-md2man/v2/LICENSE.md | 21 + + .../github.com/cpuguy83/go-md2man/v2/Makefile | 35 + + .../cpuguy83/go-md2man/v2/README.md | 15 + + .../cpuguy83/go-md2man/v2/go-md2man.1.md | 23 + + .../cpuguy83/go-md2man/v2/md2man.go | 51 + + .../cpuguy83/go-md2man/v2/md2man/md2man.go | 14 + + .../cpuguy83/go-md2man/v2/md2man/roff.go | 336 ++ + .../docker/cli-docs-tool/.dockerignore | 2 + + .../docker/cli-docs-tool/.gitignore | 2 + + .../docker/cli-docs-tool/.golangci.yml | 37 + + .../docker/cli-docs-tool/Dockerfile | 86 + + .../github.com/docker/cli-docs-tool/LICENSE | 202 ++ + .../github.com/docker/cli-docs-tool/README.md | 67 + + .../cli-docs-tool/annotation/annotation.go | 25 + + .../docker/cli-docs-tool/clidocstool.go | 123 + + .../docker/cli-docs-tool/clidocstool_md.go | 271 ++ + .../docker/cli-docs-tool/clidocstool_yaml.go | 433 +++ + .../docker/cli-docs-tool/docker-bake.hcl | 51 + + .../docker/cli-docs-tool/markdown.go | 87 + + .../russross/blackfriday/v2/.gitignore | 8 + + .../russross/blackfriday/v2/.travis.yml | 17 + + .../russross/blackfriday/v2/LICENSE.txt | 29 + + .../russross/blackfriday/v2/README.md | 335 ++ + .../russross/blackfriday/v2/block.go | 1612 +++++++++ + .../github.com/russross/blackfriday/v2/doc.go | 46 + + .../russross/blackfriday/v2/entities.go | 2236 ++++++++++++ + .../github.com/russross/blackfriday/v2/esc.go | 70 + + .../russross/blackfriday/v2/html.go | 952 ++++++ + .../russross/blackfriday/v2/inline.go | 1228 +++++++ + .../russross/blackfriday/v2/markdown.go | 950 ++++++ + .../russross/blackfriday/v2/node.go | 360 ++ + .../russross/blackfriday/v2/smartypants.go | 457 +++ + vendor/github.com/spf13/cobra/doc/README.md | 17 + + vendor/github.com/spf13/cobra/doc/man_docs.go | 246 ++ + vendor/github.com/spf13/cobra/doc/man_docs.md | 31 + + vendor/github.com/spf13/cobra/doc/md_docs.go | 156 + + vendor/github.com/spf13/cobra/doc/md_docs.md | 115 + + .../github.com/spf13/cobra/doc/rest_docs.go | 186 + + .../github.com/spf13/cobra/doc/rest_docs.md | 114 + + vendor/github.com/spf13/cobra/doc/util.go | 52 + + .../github.com/spf13/cobra/doc/yaml_docs.go | 175 + + .../github.com/spf13/cobra/doc/yaml_docs.md | 112 + + vendor/gopkg.in/yaml.v3/LICENSE | 50 + + vendor/gopkg.in/yaml.v3/NOTICE | 13 + + vendor/gopkg.in/yaml.v3/README.md | 150 + + vendor/gopkg.in/yaml.v3/apic.go | 747 ++++ + vendor/gopkg.in/yaml.v3/decode.go | 1000 ++++++ + vendor/gopkg.in/yaml.v3/emitterc.go | 2020 +++++++++++ + vendor/gopkg.in/yaml.v3/encode.go | 577 ++++ + vendor/gopkg.in/yaml.v3/parserc.go | 1258 +++++++ + vendor/gopkg.in/yaml.v3/readerc.go | 434 +++ + vendor/gopkg.in/yaml.v3/resolve.go | 326 ++ + vendor/gopkg.in/yaml.v3/scannerc.go | 3038 +++++++++++++++++ + vendor/gopkg.in/yaml.v3/sorter.go | 134 + + vendor/gopkg.in/yaml.v3/writerc.go | 48 + + vendor/gopkg.in/yaml.v3/yaml.go | 698 ++++ + vendor/gopkg.in/yaml.v3/yamlh.go | 807 +++++ + vendor/gopkg.in/yaml.v3/yamlprivateh.go | 198 ++ + vendor/modules.txt | 15 + + 71 files changed, 22956 insertions(+), 119 deletions(-) + delete mode 100644 docs/generate/go.mod + delete mode 100644 docs/generate/tools.go + create mode 100644 import.go + delete mode 100644 man/go.mod + delete mode 100644 man/tools.go + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/.gitignore + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/Makefile + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/README.md + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man.go + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go + create mode 100644 vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/.dockerignore + create mode 100644 vendor/github.com/docker/cli-docs-tool/.gitignore + create mode 100644 vendor/github.com/docker/cli-docs-tool/.golangci.yml + create mode 100644 vendor/github.com/docker/cli-docs-tool/Dockerfile + create mode 100644 vendor/github.com/docker/cli-docs-tool/LICENSE + create mode 100644 vendor/github.com/docker/cli-docs-tool/README.md + create mode 100644 vendor/github.com/docker/cli-docs-tool/annotation/annotation.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/clidocstool.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/clidocstool_md.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go + create mode 100644 vendor/github.com/docker/cli-docs-tool/docker-bake.hcl + create mode 100644 vendor/github.com/docker/cli-docs-tool/markdown.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/.gitignore + create mode 100644 vendor/github.com/russross/blackfriday/v2/.travis.yml + create mode 100644 vendor/github.com/russross/blackfriday/v2/LICENSE.txt + create mode 100644 vendor/github.com/russross/blackfriday/v2/README.md + create mode 100644 vendor/github.com/russross/blackfriday/v2/block.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/doc.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/entities.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/esc.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/html.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/inline.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/markdown.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/node.go + create mode 100644 vendor/github.com/russross/blackfriday/v2/smartypants.go + create mode 100644 vendor/github.com/spf13/cobra/doc/README.md + create mode 100644 vendor/github.com/spf13/cobra/doc/man_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/man_docs.md + create mode 100644 vendor/github.com/spf13/cobra/doc/md_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/md_docs.md + create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.md + create mode 100644 vendor/github.com/spf13/cobra/doc/util.go + create mode 100644 vendor/github.com/spf13/cobra/doc/yaml_docs.go + create mode 100644 vendor/github.com/spf13/cobra/doc/yaml_docs.md + create mode 100644 vendor/gopkg.in/yaml.v3/LICENSE + create mode 100644 vendor/gopkg.in/yaml.v3/NOTICE + create mode 100644 vendor/gopkg.in/yaml.v3/README.md + create mode 100644 vendor/gopkg.in/yaml.v3/apic.go + create mode 100644 vendor/gopkg.in/yaml.v3/decode.go + create mode 100644 vendor/gopkg.in/yaml.v3/emitterc.go + create mode 100644 vendor/gopkg.in/yaml.v3/encode.go + create mode 100644 vendor/gopkg.in/yaml.v3/parserc.go + create mode 100644 vendor/gopkg.in/yaml.v3/readerc.go + create mode 100644 vendor/gopkg.in/yaml.v3/resolve.go + create mode 100644 vendor/gopkg.in/yaml.v3/scannerc.go + create mode 100644 vendor/gopkg.in/yaml.v3/sorter.go + create mode 100644 vendor/gopkg.in/yaml.v3/writerc.go + create mode 100644 vendor/gopkg.in/yaml.v3/yaml.go + create mode 100644 vendor/gopkg.in/yaml.v3/yamlh.go + create mode 100644 vendor/gopkg.in/yaml.v3/yamlprivateh.go + +diff --git a/docs/generate/go.mod b/docs/generate/go.mod +deleted file mode 100644 +index d62ff455713a..000000000000 +--- a/docs/generate/go.mod ++++ /dev/null +@@ -1,13 +0,0 @@ +-module github.com/docker/cli/docs/generate +- +-// dummy go.mod to avoid dealing with dependencies specific +-// to docs generation and not really part of the project. +- +-go 1.16 +- +-//require ( +-// github.com/docker/cli v0.0.0+incompatible +-// github.com/docker/cli-docs-tool v0.5.0 +-//) +-// +-//replace github.com/docker/cli v0.0.0+incompatible => ../../ +diff --git a/docs/generate/tools.go b/docs/generate/tools.go +deleted file mode 100644 +index 47510bc49a89..000000000000 +--- a/docs/generate/tools.go ++++ /dev/null +@@ -1,8 +0,0 @@ +-//go:build tools +-// +build tools +- +-package main +- +-import ( +- _ "github.com/docker/cli-docs-tool" +-) +diff --git a/import.go b/import.go +new file mode 100644 +index 000000000000..16ef6ef60c0e +--- /dev/null ++++ b/import.go +@@ -0,0 +1,17 @@ ++// This is only used to define inports we need for doc generation. ++ ++//go:build never ++// +build never ++ ++package cli ++ ++import ( ++ // Used for md and yaml doc generation. ++ _ "github.com/docker/cli-docs-tool" ++ ++ // Used for man page generation. ++ _ "github.com/cpuguy83/go-md2man/v2" ++ _ "github.com/spf13/cobra" ++ _ "github.com/spf13/cobra/doc" ++ _ "github.com/spf13/pflag" ++) +diff --git a/man/go.mod b/man/go.mod +deleted file mode 100644 +index 4615c7c9a59b..000000000000 +--- a/man/go.mod ++++ /dev/null +@@ -1,15 +0,0 @@ +-module github.com/docker/cli/man +- +-// dummy go.mod to avoid dealing with dependencies specific +-// to manpages generation and not really part of the project. +- +-go 1.16 +- +-//require ( +-// github.com/docker/cli v0.0.0+incompatible +-// github.com/cpuguy83/go-md2man/v2 v2.0.1 +-// github.com/spf13/cobra v1.2.1 +-// github.com/spf13/pflag v1.0.5 +-//) +-// +-//replace github.com/docker/cli v0.0.0+incompatible => ../ +diff --git a/man/tools.go b/man/tools.go +deleted file mode 100644 +index 3cafe6533aff..000000000000 +--- a/man/tools.go ++++ /dev/null +@@ -1,11 +0,0 @@ +-//go:build tools +-// +build tools +- +-package main +- +-import ( +- _ "github.com/cpuguy83/go-md2man/v2" +- _ "github.com/spf13/cobra" +- _ "github.com/spf13/cobra/doc" +- _ "github.com/spf13/pflag" +-) +diff --git a/scripts/docs/generate-man.sh b/scripts/docs/generate-man.sh +index 6afed3fa8708..128828f50342 100755 +--- a/scripts/docs/generate-man.sh ++++ b/scripts/docs/generate-man.sh +@@ -1,35 +1,13 @@ + #!/usr/bin/env bash + +-set -eu +- +-: "${MD2MAN_VERSION=v2.0.1}" ++set -Eeuo pipefail + + export GO111MODULE=auto + +-function clean { +- rm -rf "$buildir" +-} +- +-buildir=$(mktemp -d -t docker-cli-docsgen.XXXXXXXXXX) +-trap clean EXIT +- +-( +- set -x +- cp -r . "$buildir/" +- cd "$buildir" +- # init dummy go.mod +- ./scripts/vendor init +- # install go-md2man and copy man/tools.go in root folder +- # to be able to fetch the required dependencies +- go mod edit -modfile=vendor.mod -require=github.com/cpuguy83/go-md2man/v2@${MD2MAN_VERSION} +- cp man/tools.go . +- # update vendor +- ./scripts/vendor update +- # build gen-manpages +- go build -mod=vendor -modfile=vendor.mod -tags manpages -o /tmp/gen-manpages ./man/generate.go +- # build go-md2man +- go build -mod=vendor -modfile=vendor.mod -o /tmp/go-md2man ./vendor/github.com/cpuguy83/go-md2man/v2 +-) ++# build gen-manpages ++go build -mod=vendor -modfile=vendor.mod -tags manpages -o /tmp/gen-manpages ./man/generate.go ++# build go-md2man ++go build -mod=vendor -modfile=vendor.mod -o /tmp/go-md2man ./vendor/github.com/cpuguy83/go-md2man/v2 + + mkdir -p man/man1 + (set -x ; /tmp/gen-manpages --root "." --target "$(pwd)/man/man1") +diff --git a/scripts/docs/generate-md.sh b/scripts/docs/generate-md.sh +index a947bb969673..327a06aa4c24 100755 +--- a/scripts/docs/generate-md.sh ++++ b/scripts/docs/generate-md.sh +@@ -1,36 +1,19 @@ + #!/usr/bin/env bash + +-set -eu +- +-: "${CLI_DOCS_TOOL_VERSION=v0.5.1}" ++set -Eeuo pipefail + + export GO111MODULE=auto + + function clean { +- rm -rf "$buildir" + if [ -f "$(pwd)/docs/reference/commandline/docker.md" ]; then + mv "$(pwd)/docs/reference/commandline/docker.md" "$(pwd)/docs/reference/commandline/cli.md" + fi + } + +-buildir=$(mktemp -d -t docker-cli-docsgen.XXXXXXXXXX) + trap clean EXIT + +-( +- set -x +- cp -r . "$buildir/" +- cd "$buildir" +- # init dummy go.mod +- ./scripts/vendor init +- # install cli-docs-tool and copy docs/tools.go in root folder +- # to be able to fetch the required depedencies +- go mod edit -modfile=vendor.mod -require=github.com/docker/cli-docs-tool@${CLI_DOCS_TOOL_VERSION} +- cp docs/generate/tools.go . +- # update vendor +- ./scripts/vendor update +- # build docsgen +- go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go +-) ++# build docsgen ++go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go + + # yaml generation on docs repo needs the cli.md file: https://github.com/docker/cli/pull/3924#discussion_r1059986605 + # but markdown generation docker.md atm. While waiting for a fix in cli-docs-tool +diff --git a/scripts/docs/generate-yaml.sh b/scripts/docs/generate-yaml.sh +index 4d0006e43e79..3f3f7df8b140 100755 +--- a/scripts/docs/generate-yaml.sh ++++ b/scripts/docs/generate-yaml.sh +@@ -1,33 +1,11 @@ + #!/usr/bin/env bash + +-set -eu +- +-: "${CLI_DOCS_TOOL_VERSION=v0.5.1}" ++set -Eeuo pipefail + + export GO111MODULE=auto + +-function clean { +- rm -rf "$buildir" +-} +- +-buildir=$(mktemp -d -t docker-cli-docsgen.XXXXXXXXXX) +-trap clean EXIT +- +-( +- set -x +- cp -r . "$buildir/" +- cd "$buildir" +- # init dummy go.mod +- ./scripts/vendor init +- # install cli-docs-tool and copy docs/tools.go in root folder +- # to be able to fetch the required depedencies +- go mod edit -modfile=vendor.mod -require=github.com/docker/cli-docs-tool@${CLI_DOCS_TOOL_VERSION} +- cp docs/generate/tools.go . +- # update vendor +- ./scripts/vendor update +- # build docsgen +- go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go +-) ++# build docsgen ++go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go + + mkdir -p docs/yaml + set -x +diff --git a/vendor.mod b/vendor.mod +index da1d033bff0b..61034043c05e 100644 +--- a/vendor.mod ++++ b/vendor.mod +@@ -8,7 +8,9 @@ go 1.18 + + require ( + github.com/containerd/containerd v1.6.19 ++ github.com/cpuguy83/go-md2man/v2 v2.0.2 + github.com/creack/pty v1.1.11 ++ github.com/docker/cli-docs-tool v0.5.1 + github.com/docker/distribution v2.8.1+incompatible + github.com/docker/docker v23.0.4+incompatible + github.com/docker/docker-credential-helpers v0.7.0 +@@ -67,6 +69,7 @@ require ( + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect ++ github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + go.etcd.io/etcd/raft/v3 v3.5.6 // indirect +@@ -76,4 +79,5 @@ require ( + google.golang.org/genproto v0.0.0-20220706185917-7780775163c4 // indirect + google.golang.org/grpc v1.48.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect ++ gopkg.in/yaml.v3 v3.0.1 // indirect + ) +diff --git a/vendor.sum b/vendor.sum +index 91aae7c1487c..ad0005735231 100644 +--- a/vendor.sum ++++ b/vendor.sum +@@ -89,6 +89,7 @@ github.com/containerd/containerd v1.6.19/go.mod h1:HZCDMn4v/Xl2579/MvtOC2M206i+J + github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= + github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= ++github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= + github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= + github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= + github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= +@@ -98,6 +99,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs + github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= + github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= ++github.com/docker/cli-docs-tool v0.5.1 h1:jIk/cCZurZERhALPVKhqlNxTQGxn2kcI+56gE57PQXg= ++github.com/docker/cli-docs-tool v0.5.1/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o= + github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= + github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= + github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +@@ -366,6 +369,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L + github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= + github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= + github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= ++github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= + github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= + github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/.gitignore b/vendor/github.com/cpuguy83/go-md2man/v2/.gitignore +new file mode 100644 +index 000000000000..30f97c3d73ab +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/.gitignore +@@ -0,0 +1,2 @@ ++go-md2man ++bin +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile b/vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile +new file mode 100644 +index 000000000000..7181c5306f41 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/Dockerfile +@@ -0,0 +1,20 @@ ++ARG GO_VERSION=1.18 ++ARG GO_IMAGE=golang:${GO_VERSION} ++ ++FROM --platform=$BUILDPLATFORM $GO_IMAGE AS build ++COPY . /go/src/github.com/cpuguy83/go-md2man ++WORKDIR /go/src/github.com/cpuguy83/go-md2man ++ARG TARGETOS ++ARG TARGETARCH ++ARG TARGETVARIANT ++RUN \ ++ export GOOS="${TARGETOS}"; \ ++ export GOARCH="${TARGETARCH}"; \ ++ if [ "${TARGETARCH}" = "arm" ] && [ "${TARGETVARIANT}" ]; then \ ++ export GOARM="${TARGETVARIANT#v}"; \ ++ fi; \ ++ CGO_ENABLED=0 go build ++ ++FROM scratch ++COPY --from=build /go/src/github.com/cpuguy83/go-md2man/go-md2man /go-md2man ++ENTRYPOINT ["/go-md2man"] +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md b/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md +new file mode 100644 +index 000000000000..1cade6cef6a1 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md +@@ -0,0 +1,21 @@ ++The MIT License (MIT) ++ ++Copyright (c) 2014 Brian Goff ++ ++Permission is hereby granted, free of charge, to any person obtaining a copy ++of this software and associated documentation files (the "Software"), to deal ++in the Software without restriction, including without limitation the rights ++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++copies of the Software, and to permit persons to whom the Software is ++furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in all ++copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++SOFTWARE. +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/Makefile b/vendor/github.com/cpuguy83/go-md2man/v2/Makefile +new file mode 100644 +index 000000000000..437fc9997926 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/Makefile +@@ -0,0 +1,35 @@ ++GO111MODULE ?= on ++LINTER_BIN ?= golangci-lint ++ ++export GO111MODULE ++ ++.PHONY: ++build: bin/go-md2man ++ ++.PHONY: clean ++clean: ++ @rm -rf bin/* ++ ++.PHONY: test ++test: ++ @go test $(TEST_FLAGS) ./... ++ ++bin/go-md2man: actual_build_flags := $(BUILD_FLAGS) -o bin/go-md2man ++bin/go-md2man: bin ++ @CGO_ENABLED=0 go build $(actual_build_flags) ++ ++bin: ++ @mkdir ./bin ++ ++.PHONY: mod ++mod: ++ @go mod tidy ++ ++.PHONY: check-mod ++check-mod: # verifies that module changes for go.mod and go.sum are checked in ++ @hack/ci/check_mods.sh ++ ++.PHONY: vendor ++vendor: mod ++ @go mod vendor -v ++ +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/README.md b/vendor/github.com/cpuguy83/go-md2man/v2/README.md +new file mode 100644 +index 000000000000..0e30d341483c +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/README.md +@@ -0,0 +1,15 @@ ++go-md2man ++========= ++ ++Converts markdown into roff (man pages). ++ ++Uses blackfriday to process markdown into man pages. ++ ++### Usage ++ ++./md2man -in /path/to/markdownfile.md -out /manfile/output/path ++ ++### How to contribute ++ ++We use go modules to manage dependencies. ++As such you must be using at lest go1.11. +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md b/vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md +new file mode 100644 +index 000000000000..16d1133aa1de +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/go-md2man.1.md +@@ -0,0 +1,23 @@ ++go-md2man 1 "January 2015" go-md2man "User Manual" ++================================================== ++ ++# NAME ++ go-md2man - Convert markdown files into manpages ++ ++# SYNOPSIS ++ go-md2man -in=[/path/to/md/file] -out=[/path/to/output] ++ ++# Description ++ go-md2man converts standard markdown formatted documents into manpages. It is ++ written purely in Go so as to reduce dependencies on 3rd party libs. ++ ++ By default, the input is stdin and the output is stdout. ++ ++# Example ++ Convert the markdown file "go-md2man.1.md" into a manpage. ++ ++ go-md2man -in=go-md2man.1.md -out=go-md2man.1.out ++ ++# HISTORY ++ January 2015, Originally compiled by Brian Goff( cpuguy83@gmail.com ) ++ +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man.go +new file mode 100644 +index 000000000000..6078864a3cd9 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man.go +@@ -0,0 +1,51 @@ ++package main ++ ++import ( ++ "flag" ++ "fmt" ++ "io/ioutil" ++ "os" ++ ++ "github.com/cpuguy83/go-md2man/v2/md2man" ++) ++ ++var inFilePath = flag.String("in", "", "Path to file to be processed (default: stdin)") ++var outFilePath = flag.String("out", "", "Path to output processed file (default: stdout)") ++ ++func main() { ++ var err error ++ flag.Parse() ++ ++ inFile := os.Stdin ++ if *inFilePath != "" { ++ inFile, err = os.Open(*inFilePath) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ } ++ defer inFile.Close() // nolint: errcheck ++ ++ doc, err := ioutil.ReadAll(inFile) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ ++ out := md2man.Render(doc) ++ ++ outFile := os.Stdout ++ if *outFilePath != "" { ++ outFile, err = os.Create(*outFilePath) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ defer outFile.Close() // nolint: errcheck ++ } ++ _, err = outFile.Write(out) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++} +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go +new file mode 100644 +index 000000000000..b48005673455 +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go +@@ -0,0 +1,14 @@ ++package md2man ++ ++import ( ++ "github.com/russross/blackfriday/v2" ++) ++ ++// Render converts a markdown document into a roff formatted document. ++func Render(doc []byte) []byte { ++ renderer := NewRoffRenderer() ++ ++ return blackfriday.Run(doc, ++ []blackfriday.Option{blackfriday.WithRenderer(renderer), ++ blackfriday.WithExtensions(renderer.GetExtensions())}...) ++} +diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go +new file mode 100644 +index 000000000000..be2b3436062d +--- /dev/null ++++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go +@@ -0,0 +1,336 @@ ++package md2man ++ ++import ( ++ "fmt" ++ "io" ++ "os" ++ "strings" ++ ++ "github.com/russross/blackfriday/v2" ++) ++ ++// roffRenderer implements the blackfriday.Renderer interface for creating ++// roff format (manpages) from markdown text ++type roffRenderer struct { ++ extensions blackfriday.Extensions ++ listCounters []int ++ firstHeader bool ++ firstDD bool ++ listDepth int ++} ++ ++const ( ++ titleHeader = ".TH " ++ topLevelHeader = "\n\n.SH " ++ secondLevelHdr = "\n.SH " ++ otherHeader = "\n.SS " ++ crTag = "\n" ++ emphTag = "\\fI" ++ emphCloseTag = "\\fP" ++ strongTag = "\\fB" ++ strongCloseTag = "\\fP" ++ breakTag = "\n.br\n" ++ paraTag = "\n.PP\n" ++ hruleTag = "\n.ti 0\n\\l'\\n(.lu'\n" ++ linkTag = "\n\\[la]" ++ linkCloseTag = "\\[ra]" ++ codespanTag = "\\fB\\fC" ++ codespanCloseTag = "\\fR" ++ codeTag = "\n.PP\n.RS\n\n.nf\n" ++ codeCloseTag = "\n.fi\n.RE\n" ++ quoteTag = "\n.PP\n.RS\n" ++ quoteCloseTag = "\n.RE\n" ++ listTag = "\n.RS\n" ++ listCloseTag = "\n.RE\n" ++ dtTag = "\n.TP\n" ++ dd2Tag = "\n" ++ tableStart = "\n.TS\nallbox;\n" ++ tableEnd = ".TE\n" ++ tableCellStart = "T{\n" ++ tableCellEnd = "\nT}\n" ++) ++ ++// NewRoffRenderer creates a new blackfriday Renderer for generating roff documents ++// from markdown ++func NewRoffRenderer() *roffRenderer { // nolint: golint ++ var extensions blackfriday.Extensions ++ ++ extensions |= blackfriday.NoIntraEmphasis ++ extensions |= blackfriday.Tables ++ extensions |= blackfriday.FencedCode ++ extensions |= blackfriday.SpaceHeadings ++ extensions |= blackfriday.Footnotes ++ extensions |= blackfriday.Titleblock ++ extensions |= blackfriday.DefinitionLists ++ return &roffRenderer{ ++ extensions: extensions, ++ } ++} ++ ++// GetExtensions returns the list of extensions used by this renderer implementation ++func (r *roffRenderer) GetExtensions() blackfriday.Extensions { ++ return r.extensions ++} ++ ++// RenderHeader handles outputting the header at document start ++func (r *roffRenderer) RenderHeader(w io.Writer, ast *blackfriday.Node) { ++ // disable hyphenation ++ out(w, ".nh\n") ++} ++ ++// RenderFooter handles outputting the footer at the document end; the roff ++// renderer has no footer information ++func (r *roffRenderer) RenderFooter(w io.Writer, ast *blackfriday.Node) { ++} ++ ++// RenderNode is called for each node in a markdown document; based on the node ++// type the equivalent roff output is sent to the writer ++func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus { ++ ++ var walkAction = blackfriday.GoToNext ++ ++ switch node.Type { ++ case blackfriday.Text: ++ escapeSpecialChars(w, node.Literal) ++ case blackfriday.Softbreak: ++ out(w, crTag) ++ case blackfriday.Hardbreak: ++ out(w, breakTag) ++ case blackfriday.Emph: ++ if entering { ++ out(w, emphTag) ++ } else { ++ out(w, emphCloseTag) ++ } ++ case blackfriday.Strong: ++ if entering { ++ out(w, strongTag) ++ } else { ++ out(w, strongCloseTag) ++ } ++ case blackfriday.Link: ++ if !entering { ++ out(w, linkTag+string(node.LinkData.Destination)+linkCloseTag) ++ } ++ case blackfriday.Image: ++ // ignore images ++ walkAction = blackfriday.SkipChildren ++ case blackfriday.Code: ++ out(w, codespanTag) ++ escapeSpecialChars(w, node.Literal) ++ out(w, codespanCloseTag) ++ case blackfriday.Document: ++ break ++ case blackfriday.Paragraph: ++ // roff .PP markers break lists ++ if r.listDepth > 0 { ++ return blackfriday.GoToNext ++ } ++ if entering { ++ out(w, paraTag) ++ } else { ++ out(w, crTag) ++ } ++ case blackfriday.BlockQuote: ++ if entering { ++ out(w, quoteTag) ++ } else { ++ out(w, quoteCloseTag) ++ } ++ case blackfriday.Heading: ++ r.handleHeading(w, node, entering) ++ case blackfriday.HorizontalRule: ++ out(w, hruleTag) ++ case blackfriday.List: ++ r.handleList(w, node, entering) ++ case blackfriday.Item: ++ r.handleItem(w, node, entering) ++ case blackfriday.CodeBlock: ++ out(w, codeTag) ++ escapeSpecialChars(w, node.Literal) ++ out(w, codeCloseTag) ++ case blackfriday.Table: ++ r.handleTable(w, node, entering) ++ case blackfriday.TableHead: ++ case blackfriday.TableBody: ++ case blackfriday.TableRow: ++ // no action as cell entries do all the nroff formatting ++ return blackfriday.GoToNext ++ case blackfriday.TableCell: ++ r.handleTableCell(w, node, entering) ++ case blackfriday.HTMLSpan: ++ // ignore other HTML tags ++ default: ++ fmt.Fprintln(os.Stderr, "WARNING: go-md2man does not handle node type "+node.Type.String()) ++ } ++ return walkAction ++} ++ ++func (r *roffRenderer) handleHeading(w io.Writer, node *blackfriday.Node, entering bool) { ++ if entering { ++ switch node.Level { ++ case 1: ++ if !r.firstHeader { ++ out(w, titleHeader) ++ r.firstHeader = true ++ break ++ } ++ out(w, topLevelHeader) ++ case 2: ++ out(w, secondLevelHdr) ++ default: ++ out(w, otherHeader) ++ } ++ } ++} ++ ++func (r *roffRenderer) handleList(w io.Writer, node *blackfriday.Node, entering bool) { ++ openTag := listTag ++ closeTag := listCloseTag ++ if node.ListFlags&blackfriday.ListTypeDefinition != 0 { ++ // tags for definition lists handled within Item node ++ openTag = "" ++ closeTag = "" ++ } ++ if entering { ++ r.listDepth++ ++ if node.ListFlags&blackfriday.ListTypeOrdered != 0 { ++ r.listCounters = append(r.listCounters, 1) ++ } ++ out(w, openTag) ++ } else { ++ if node.ListFlags&blackfriday.ListTypeOrdered != 0 { ++ r.listCounters = r.listCounters[:len(r.listCounters)-1] ++ } ++ out(w, closeTag) ++ r.listDepth-- ++ } ++} ++ ++func (r *roffRenderer) handleItem(w io.Writer, node *blackfriday.Node, entering bool) { ++ if entering { ++ if node.ListFlags&blackfriday.ListTypeOrdered != 0 { ++ out(w, fmt.Sprintf(".IP \"%3d.\" 5\n", r.listCounters[len(r.listCounters)-1])) ++ r.listCounters[len(r.listCounters)-1]++ ++ } else if node.ListFlags&blackfriday.ListTypeTerm != 0 { ++ // DT (definition term): line just before DD (see below). ++ out(w, dtTag) ++ r.firstDD = true ++ } else if node.ListFlags&blackfriday.ListTypeDefinition != 0 { ++ // DD (definition description): line that starts with ": ". ++ // ++ // We have to distinguish between the first DD and the ++ // subsequent ones, as there should be no vertical ++ // whitespace between the DT and the first DD. ++ if r.firstDD { ++ r.firstDD = false ++ } else { ++ out(w, dd2Tag) ++ } ++ } else { ++ out(w, ".IP \\(bu 2\n") ++ } ++ } else { ++ out(w, "\n") ++ } ++} ++ ++func (r *roffRenderer) handleTable(w io.Writer, node *blackfriday.Node, entering bool) { ++ if entering { ++ out(w, tableStart) ++ // call walker to count cells (and rows?) so format section can be produced ++ columns := countColumns(node) ++ out(w, strings.Repeat("l ", columns)+"\n") ++ out(w, strings.Repeat("l ", columns)+".\n") ++ } else { ++ out(w, tableEnd) ++ } ++} ++ ++func (r *roffRenderer) handleTableCell(w io.Writer, node *blackfriday.Node, entering bool) { ++ if entering { ++ var start string ++ if node.Prev != nil && node.Prev.Type == blackfriday.TableCell { ++ start = "\t" ++ } ++ if node.IsHeader { ++ start += codespanTag ++ } else if nodeLiteralSize(node) > 30 { ++ start += tableCellStart ++ } ++ out(w, start) ++ } else { ++ var end string ++ if node.IsHeader { ++ end = codespanCloseTag ++ } else if nodeLiteralSize(node) > 30 { ++ end = tableCellEnd ++ } ++ if node.Next == nil && end != tableCellEnd { ++ // Last cell: need to carriage return if we are at the end of the ++ // header row and content isn't wrapped in a "tablecell" ++ end += crTag ++ } ++ out(w, end) ++ } ++} ++ ++func nodeLiteralSize(node *blackfriday.Node) int { ++ total := 0 ++ for n := node.FirstChild; n != nil; n = n.FirstChild { ++ total += len(n.Literal) ++ } ++ return total ++} ++ ++// because roff format requires knowing the column count before outputting any table ++// data we need to walk a table tree and count the columns ++func countColumns(node *blackfriday.Node) int { ++ var columns int ++ ++ node.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus { ++ switch node.Type { ++ case blackfriday.TableRow: ++ if !entering { ++ return blackfriday.Terminate ++ } ++ case blackfriday.TableCell: ++ if entering { ++ columns++ ++ } ++ default: ++ } ++ return blackfriday.GoToNext ++ }) ++ return columns ++} ++ ++func out(w io.Writer, output string) { ++ io.WriteString(w, output) // nolint: errcheck ++} ++ ++func escapeSpecialChars(w io.Writer, text []byte) { ++ for i := 0; i < len(text); i++ { ++ // escape initial apostrophe or period ++ if len(text) >= 1 && (text[0] == '\'' || text[0] == '.') { ++ out(w, "\\&") ++ } ++ ++ // directly copy normal characters ++ org := i ++ ++ for i < len(text) && text[i] != '\\' { ++ i++ ++ } ++ if i > org { ++ w.Write(text[org:i]) // nolint: errcheck ++ } ++ ++ // escape a character ++ if i >= len(text) { ++ break ++ } ++ ++ w.Write([]byte{'\\', text[i]}) // nolint: errcheck ++ } ++} +diff --git a/vendor/github.com/docker/cli-docs-tool/.dockerignore b/vendor/github.com/docker/cli-docs-tool/.dockerignore +new file mode 100644 +index 000000000000..c8c323c89663 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/.dockerignore +@@ -0,0 +1,2 @@ ++/coverage.txt ++/example/docs +diff --git a/vendor/github.com/docker/cli-docs-tool/.gitignore b/vendor/github.com/docker/cli-docs-tool/.gitignore +new file mode 100644 +index 000000000000..c8c323c89663 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/.gitignore +@@ -0,0 +1,2 @@ ++/coverage.txt ++/example/docs +diff --git a/vendor/github.com/docker/cli-docs-tool/.golangci.yml b/vendor/github.com/docker/cli-docs-tool/.golangci.yml +new file mode 100644 +index 000000000000..6c6557176b28 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/.golangci.yml +@@ -0,0 +1,37 @@ ++run: ++ timeout: 10m ++ ++linters: ++ enable: ++ - deadcode ++ - depguard ++ - gofmt ++ - goimports ++ - revive ++ - govet ++ - importas ++ - ineffassign ++ - misspell ++ - typecheck ++ - varcheck ++ - errname ++ - makezero ++ - whitespace ++ disable-all: true ++ ++linters-settings: ++ depguard: ++ list-type: blacklist ++ include-go-root: true ++ packages: ++ # The io/ioutil package has been deprecated. ++ # https://go.dev/doc/go1.16#ioutil ++ - io/ioutil ++ importas: ++ no-unaliased: true ++ ++issues: ++ exclude-rules: ++ - linters: ++ - revive ++ text: "stutters" +diff --git a/vendor/github.com/docker/cli-docs-tool/Dockerfile b/vendor/github.com/docker/cli-docs-tool/Dockerfile +new file mode 100644 +index 000000000000..f0e2739faa7c +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/Dockerfile +@@ -0,0 +1,86 @@ ++# syntax=docker/dockerfile:1 ++ ++# Copyright 2021 cli-docs-tool authors ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++ ++ARG GO_VERSION="1.18" ++ARG GOLANGCI_LINT_VERSION="v1.45" ++ARG ADDLICENSE_VERSION="v1.0.0" ++ ++ARG LICENSE_ARGS="-c cli-docs-tool -l apache" ++ARG LICENSE_FILES=".*\(Dockerfile\|\.go\|\.hcl\|\.sh\)" ++ ++FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint ++FROM ghcr.io/google/addlicense:${ADDLICENSE_VERSION} AS addlicense ++ ++FROM golang:${GO_VERSION}-alpine AS base ++RUN apk add --no-cache cpio findutils git linux-headers ++ENV CGO_ENABLED=0 ++WORKDIR /src ++ ++FROM base AS vendored ++RUN --mount=type=bind,target=.,rw \ ++ --mount=type=cache,target=/go/pkg/mod \ ++ go mod tidy && go mod download && \ ++ mkdir /out && cp go.mod go.sum /out ++ ++FROM scratch AS vendor-update ++COPY --from=vendored /out / ++ ++FROM vendored AS vendor-validate ++RUN --mount=type=bind,target=.,rw <&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"' ++ echo "$diff" ++ exit 1 ++fi ++EOT ++ ++FROM base AS lint ++RUN --mount=type=bind,target=. \ ++ --mount=type=cache,target=/root/.cache \ ++ --mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \ ++ golangci-lint run ./... ++ ++FROM base AS license-set ++ARG LICENSE_ARGS ++ARG LICENSE_FILES ++RUN --mount=type=bind,target=.,rw \ ++ --mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \ ++ find . -regex "${LICENSE_FILES}" | xargs addlicense ${LICENSE_ARGS} \ ++ && mkdir /out \ ++ && find . -regex "${LICENSE_FILES}" | cpio -pdm /out ++ ++FROM scratch AS license-update ++COPY --from=set /out / ++ ++FROM base AS license-validate ++ARG LICENSE_ARGS ++ARG LICENSE_FILES ++RUN --mount=type=bind,target=. \ ++ --mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \ ++ find . -regex "${LICENSE_FILES}" | xargs addlicense -check ${LICENSE_ARGS} ++ ++FROM vendored AS test ++RUN --mount=type=bind,target=. \ ++ --mount=type=cache,target=/root/.cache \ ++ --mount=type=cache,target=/go/pkg/mod \ ++ go test -v -coverprofile=/tmp/coverage.txt -covermode=atomic ./... ++ ++FROM scratch AS test-coverage ++COPY --from=test /tmp/coverage.txt /coverage.txt +diff --git a/vendor/github.com/docker/cli-docs-tool/LICENSE b/vendor/github.com/docker/cli-docs-tool/LICENSE +new file mode 100644 +index 000000000000..d64569567334 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/LICENSE +@@ -0,0 +1,202 @@ ++ ++ Apache License ++ Version 2.0, January 2004 ++ http://www.apache.org/licenses/ ++ ++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ++ ++ 1. Definitions. ++ ++ "License" shall mean the terms and conditions for use, reproduction, ++ and distribution as defined by Sections 1 through 9 of this document. ++ ++ "Licensor" shall mean the copyright owner or entity authorized by ++ the copyright owner that is granting the License. ++ ++ "Legal Entity" shall mean the union of the acting entity and all ++ other entities that control, are controlled by, or are under common ++ control with that entity. For the purposes of this definition, ++ "control" means (i) the power, direct or indirect, to cause the ++ direction or management of such entity, whether by contract or ++ otherwise, or (ii) ownership of fifty percent (50%) or more of the ++ outstanding shares, or (iii) beneficial ownership of such entity. ++ ++ "You" (or "Your") shall mean an individual or Legal Entity ++ exercising permissions granted by this License. ++ ++ "Source" form shall mean the preferred form for making modifications, ++ including but not limited to software source code, documentation ++ source, and configuration files. ++ ++ "Object" form shall mean any form resulting from mechanical ++ transformation or translation of a Source form, including but ++ not limited to compiled object code, generated documentation, ++ and conversions to other media types. ++ ++ "Work" shall mean the work of authorship, whether in Source or ++ Object form, made available under the License, as indicated by a ++ copyright notice that is included in or attached to the work ++ (an example is provided in the Appendix below). ++ ++ "Derivative Works" shall mean any work, whether in Source or Object ++ form, that is based on (or derived from) the Work and for which the ++ editorial revisions, annotations, elaborations, or other modifications ++ represent, as a whole, an original work of authorship. For the purposes ++ of this License, Derivative Works shall not include works that remain ++ separable from, or merely link (or bind by name) to the interfaces of, ++ the Work and Derivative Works thereof. ++ ++ "Contribution" shall mean any work of authorship, including ++ the original version of the Work and any modifications or additions ++ to that Work or Derivative Works thereof, that is intentionally ++ submitted to Licensor for inclusion in the Work by the copyright owner ++ or by an individual or Legal Entity authorized to submit on behalf of ++ the copyright owner. For the purposes of this definition, "submitted" ++ means any form of electronic, verbal, or written communication sent ++ to the Licensor or its representatives, including but not limited to ++ communication on electronic mailing lists, source code control systems, ++ and issue tracking systems that are managed by, or on behalf of, the ++ Licensor for the purpose of discussing and improving the Work, but ++ excluding communication that is conspicuously marked or otherwise ++ designated in writing by the copyright owner as "Not a Contribution." ++ ++ "Contributor" shall mean Licensor and any individual or Legal Entity ++ on behalf of whom a Contribution has been received by Licensor and ++ subsequently incorporated within the Work. ++ ++ 2. Grant of Copyright License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ copyright license to reproduce, prepare Derivative Works of, ++ publicly display, publicly perform, sublicense, and distribute the ++ Work and such Derivative Works in Source or Object form. ++ ++ 3. Grant of Patent License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ (except as stated in this section) patent license to make, have made, ++ use, offer to sell, sell, import, and otherwise transfer the Work, ++ where such license applies only to those patent claims licensable ++ by such Contributor that are necessarily infringed by their ++ Contribution(s) alone or by combination of their Contribution(s) ++ with the Work to which such Contribution(s) was submitted. If You ++ institute patent litigation against any entity (including a ++ cross-claim or counterclaim in a lawsuit) alleging that the Work ++ or a Contribution incorporated within the Work constitutes direct ++ or contributory patent infringement, then any patent licenses ++ granted to You under this License for that Work shall terminate ++ as of the date such litigation is filed. ++ ++ 4. Redistribution. You may reproduce and distribute copies of the ++ Work or Derivative Works thereof in any medium, with or without ++ modifications, and in Source or Object form, provided that You ++ meet the following conditions: ++ ++ (a) You must give any other recipients of the Work or ++ Derivative Works a copy of this License; and ++ ++ (b) You must cause any modified files to carry prominent notices ++ stating that You changed the files; and ++ ++ (c) You must retain, in the Source form of any Derivative Works ++ that You distribute, all copyright, patent, trademark, and ++ attribution notices from the Source form of the Work, ++ excluding those notices that do not pertain to any part of ++ the Derivative Works; and ++ ++ (d) If the Work includes a "NOTICE" text file as part of its ++ distribution, then any Derivative Works that You distribute must ++ include a readable copy of the attribution notices contained ++ within such NOTICE file, excluding those notices that do not ++ pertain to any part of the Derivative Works, in at least one ++ of the following places: within a NOTICE text file distributed ++ as part of the Derivative Works; within the Source form or ++ documentation, if provided along with the Derivative Works; or, ++ within a display generated by the Derivative Works, if and ++ wherever such third-party notices normally appear. The contents ++ of the NOTICE file are for informational purposes only and ++ do not modify the License. You may add Your own attribution ++ notices within Derivative Works that You distribute, alongside ++ or as an addendum to the NOTICE text from the Work, provided ++ that such additional attribution notices cannot be construed ++ as modifying the License. ++ ++ You may add Your own copyright statement to Your modifications and ++ may provide additional or different license terms and conditions ++ for use, reproduction, or distribution of Your modifications, or ++ for any such Derivative Works as a whole, provided Your use, ++ reproduction, and distribution of the Work otherwise complies with ++ the conditions stated in this License. ++ ++ 5. Submission of Contributions. Unless You explicitly state otherwise, ++ any Contribution intentionally submitted for inclusion in the Work ++ by You to the Licensor shall be under the terms and conditions of ++ this License, without any additional terms or conditions. ++ Notwithstanding the above, nothing herein shall supersede or modify ++ the terms of any separate license agreement you may have executed ++ with Licensor regarding such Contributions. ++ ++ 6. Trademarks. This License does not grant permission to use the trade ++ names, trademarks, service marks, or product names of the Licensor, ++ except as required for reasonable and customary use in describing the ++ origin of the Work and reproducing the content of the NOTICE file. ++ ++ 7. Disclaimer of Warranty. Unless required by applicable law or ++ agreed to in writing, Licensor provides the Work (and each ++ Contributor provides its Contributions) on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ++ implied, including, without limitation, any warranties or conditions ++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A ++ PARTICULAR PURPOSE. You are solely responsible for determining the ++ appropriateness of using or redistributing the Work and assume any ++ risks associated with Your exercise of permissions under this License. ++ ++ 8. Limitation of Liability. In no event and under no legal theory, ++ whether in tort (including negligence), contract, or otherwise, ++ unless required by applicable law (such as deliberate and grossly ++ negligent acts) or agreed to in writing, shall any Contributor be ++ liable to You for damages, including any direct, indirect, special, ++ incidental, or consequential damages of any character arising as a ++ result of this License or out of the use or inability to use the ++ Work (including but not limited to damages for loss of goodwill, ++ work stoppage, computer failure or malfunction, or any and all ++ other commercial damages or losses), even if such Contributor ++ has been advised of the possibility of such damages. ++ ++ 9. Accepting Warranty or Additional Liability. While redistributing ++ the Work or Derivative Works thereof, You may choose to offer, ++ and charge a fee for, acceptance of support, warranty, indemnity, ++ or other liability obligations and/or rights consistent with this ++ License. However, in accepting such obligations, You may act only ++ on Your own behalf and on Your sole responsibility, not on behalf ++ of any other Contributor, and only if You agree to indemnify, ++ defend, and hold each Contributor harmless for any liability ++ incurred by, or claims asserted against, such Contributor by reason ++ of your accepting any such warranty or additional liability. ++ ++ END OF TERMS AND CONDITIONS ++ ++ APPENDIX: How to apply the Apache License to your work. ++ ++ To apply the Apache License to your work, attach the following ++ boilerplate notice, with the fields enclosed by brackets "[]" ++ replaced with your own identifying information. (Don't include ++ the brackets!) The text should be enclosed in the appropriate ++ comment syntax for the file format. We also recommend that a ++ file or class name and description of purpose be included on the ++ same "printed page" as the copyright notice for easier ++ identification within third-party archives. ++ ++ Copyright [yyyy] [name of copyright owner] ++ ++ Licensed under the Apache License, Version 2.0 (the "License"); ++ you may not use this file except in compliance with the License. ++ You may obtain a copy of the License at ++ ++ http://www.apache.org/licenses/LICENSE-2.0 ++ ++ Unless required by applicable law or agreed to in writing, software ++ distributed under the License is distributed on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ See the License for the specific language governing permissions and ++ limitations under the License. +diff --git a/vendor/github.com/docker/cli-docs-tool/README.md b/vendor/github.com/docker/cli-docs-tool/README.md +new file mode 100644 +index 000000000000..4d5ee6474f8f +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/README.md +@@ -0,0 +1,67 @@ ++[![PkgGoDev](https://img.shields.io/badge/go.dev-docs-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/docker/cli-docs-tool) ++[![Test Status](https://img.shields.io/github/actions/workflow/status/docker/cli-docs-tool/test.yml?branch=main&label=test&logo=github&style=flat-square)](https://github.com/docker/cli-docs-tool/actions?query=workflow%3Atest) ++[![Go Report Card](https://goreportcard.com/badge/github.com/docker/cli-docs-tool)](https://goreportcard.com/report/github.com/docker/cli-docs-tool) ++ ++## About ++ ++This is a library containing utilities to generate (reference) documentation ++for the [`docker` CLI](https://github.com/docker/cli) on [docs.docker.com](https://docs.docker.com/reference/). ++ ++## Disclaimer ++ ++This library is intended for use by Docker's CLIs, and is not intended to be a ++general-purpose utility. Various bits are hard-coded or make assumptions that ++are very specific to our use-case. Contributions are welcome, but we will not ++accept contributions to make this a general-purpose module. ++ ++## Usage ++ ++To generate the documentation it's recommended to do so using a Go submodule ++in your repository. ++ ++We will use the example of `docker/buildx` and create a Go submodule in a ++`docs` folder (recommended): ++ ++```console ++$ mkdir docs ++$ cd ./docs ++$ go mod init github.com/docker/buildx/docs ++$ go get github.com/docker/cli-docs-tool ++``` ++ ++Your `go.mod` should look like this: ++ ++```text ++module github.com/docker/buildx/docs ++ ++go 1.16 ++ ++require ( ++ github.com/docker/cli-docs-tool v0.0.0 ++) ++``` ++ ++Next, create a file named `main.go` inside that directory containing the ++following Go code from [`example/main.go`](example/main.go). ++ ++Running this example should produce the following output: ++ ++```console ++$ go run main.go ++INFO: Generating Markdown for "docker buildx bake" ++INFO: Generating Markdown for "docker buildx build" ++INFO: Generating Markdown for "docker buildx create" ++INFO: Generating Markdown for "docker buildx du" ++... ++INFO: Generating YAML for "docker buildx uninstall" ++INFO: Generating YAML for "docker buildx use" ++INFO: Generating YAML for "docker buildx version" ++INFO: Generating YAML for "docker buildx" ++``` ++ ++Generated docs will be available in the `./docs` folder of the project. ++ ++## Contributing ++ ++Want to contribute? Awesome! You can find information about contributing to ++this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md) +diff --git a/vendor/github.com/docker/cli-docs-tool/annotation/annotation.go b/vendor/github.com/docker/cli-docs-tool/annotation/annotation.go +new file mode 100644 +index 000000000000..021846af6e07 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/annotation/annotation.go +@@ -0,0 +1,25 @@ ++// Copyright 2021 cli-docs-tool authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package annotation ++ ++const ( ++ // ExternalURL specifies an external link annotation ++ ExternalURL = "docs.external.url" ++ // CodeDelimiter specifies the char that will be converted as code backtick. ++ // Can be used on cmd for inheritance or a specific flag. ++ CodeDelimiter = "docs.code-delimiter" ++ // DefaultValue specifies the default value for a flag. ++ DefaultValue = "docs.default-value" ++) +diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool.go b/vendor/github.com/docker/cli-docs-tool/clidocstool.go +new file mode 100644 +index 000000000000..d4aeaba3f126 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/clidocstool.go +@@ -0,0 +1,123 @@ ++// Copyright 2017 cli-docs-tool authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package clidocstool ++ ++import ( ++ "errors" ++ "io" ++ "os" ++ "strings" ++ ++ "github.com/spf13/cobra" ++) ++ ++// Options defines options for cli-docs-tool ++type Options struct { ++ Root *cobra.Command ++ SourceDir string ++ TargetDir string ++ Plugin bool ++} ++ ++// Client represents an active cli-docs-tool object ++type Client struct { ++ root *cobra.Command ++ source string ++ target string ++ plugin bool ++} ++ ++// New initializes a new cli-docs-tool client ++func New(opts Options) (*Client, error) { ++ if opts.Root == nil { ++ return nil, errors.New("root cmd required") ++ } ++ if len(opts.SourceDir) == 0 { ++ return nil, errors.New("source dir required") ++ } ++ c := &Client{ ++ root: opts.Root, ++ source: opts.SourceDir, ++ plugin: opts.Plugin, ++ } ++ if len(opts.TargetDir) == 0 { ++ c.target = c.source ++ } else { ++ c.target = opts.TargetDir ++ } ++ if err := os.MkdirAll(c.target, 0755); err != nil { ++ return nil, err ++ } ++ return c, nil ++} ++ ++// GenAllTree creates all structured ref files for this command and ++// all descendants in the directory given. ++func (c *Client) GenAllTree() error { ++ var err error ++ if err = c.GenMarkdownTree(c.root); err != nil { ++ return err ++ } ++ if err = c.GenYamlTree(c.root); err != nil { ++ return err ++ } ++ return nil ++} ++ ++func fileExists(f string) bool { ++ info, err := os.Stat(f) ++ if os.IsNotExist(err) { ++ return false ++ } ++ return !info.IsDir() ++} ++ ++func copyFile(src string, dst string) error { ++ sf, err := os.Open(src) ++ if err != nil { ++ return err ++ } ++ defer sf.Close() ++ df, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0o600) ++ if err != nil { ++ return err ++ } ++ defer df.Close() ++ _, err = io.Copy(df, sf) ++ return err ++} ++ ++func getAliases(cmd *cobra.Command) []string { ++ if a := cmd.Annotations["aliases"]; a != "" { ++ aliases := strings.Split(a, ",") ++ for i := 0; i < len(aliases); i++ { ++ aliases[i] = strings.TrimSpace(aliases[i]) ++ } ++ return aliases ++ } ++ if len(cmd.Aliases) == 0 { ++ return cmd.Aliases ++ } ++ ++ var parentPath string ++ if cmd.HasParent() { ++ parentPath = cmd.Parent().CommandPath() + " " ++ } ++ aliases := []string{cmd.CommandPath()} ++ for _, a := range cmd.Aliases { ++ aliases = append(aliases, parentPath+a) ++ } ++ return aliases ++} +diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go b/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go +new file mode 100644 +index 000000000000..73d05c8a722a +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go +@@ -0,0 +1,271 @@ ++// Copyright 2021 cli-docs-tool authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package clidocstool ++ ++import ( ++ "bytes" ++ "fmt" ++ "log" ++ "os" ++ "path/filepath" ++ "regexp" ++ "strings" ++ "text/tabwriter" ++ "text/template" ++ ++ "github.com/docker/cli-docs-tool/annotation" ++ "github.com/spf13/cobra" ++ "github.com/spf13/pflag" ++) ++ ++var ( ++ nlRegexp = regexp.MustCompile(`\r?\n`) ++ adjustSep = regexp.MustCompile(`\|:---(\s+)`) ++) ++ ++// GenMarkdownTree will generate a markdown page for this command and all ++// descendants in the directory given. ++func (c *Client) GenMarkdownTree(cmd *cobra.Command) error { ++ for _, sc := range cmd.Commands() { ++ if err := c.GenMarkdownTree(sc); err != nil { ++ return err ++ } ++ } ++ ++ // always disable the addition of [flags] to the usage ++ cmd.DisableFlagsInUseLine = true ++ ++ // Skip the root command altogether, to prevent generating a useless ++ // md file for plugins. ++ if c.plugin && !cmd.HasParent() { ++ return nil ++ } ++ ++ log.Printf("INFO: Generating Markdown for %q", cmd.CommandPath()) ++ mdFile := mdFilename(cmd) ++ sourcePath := filepath.Join(c.source, mdFile) ++ targetPath := filepath.Join(c.target, mdFile) ++ ++ // check recursively to handle inherited annotations ++ for curr := cmd; curr != nil; curr = curr.Parent() { ++ if _, ok := cmd.Annotations[annotation.CodeDelimiter]; !ok { ++ if cd, cok := curr.Annotations[annotation.CodeDelimiter]; cok { ++ if cmd.Annotations == nil { ++ cmd.Annotations = map[string]string{} ++ } ++ cmd.Annotations[annotation.CodeDelimiter] = cd ++ } ++ } ++ } ++ ++ if !fileExists(sourcePath) { ++ var icBuf bytes.Buffer ++ icTpl, err := template.New("ic").Option("missingkey=error").Parse(`# {{ .Command }} ++ ++ ++ ++ ++`) ++ if err != nil { ++ return err ++ } ++ if err = icTpl.Execute(&icBuf, struct { ++ Command string ++ }{ ++ Command: cmd.CommandPath(), ++ }); err != nil { ++ return err ++ } ++ if err = os.WriteFile(targetPath, icBuf.Bytes(), 0644); err != nil { ++ return err ++ } ++ } else if err := copyFile(sourcePath, targetPath); err != nil { ++ return err ++ } ++ ++ content, err := os.ReadFile(targetPath) ++ if err != nil { ++ return err ++ } ++ ++ cs := string(content) ++ ++ start := strings.Index(cs, "") ++ end := strings.Index(cs, "") ++ ++ if start == -1 { ++ return fmt.Errorf("no start marker in %s", mdFile) ++ } ++ if end == -1 { ++ return fmt.Errorf("no end marker in %s", mdFile) ++ } ++ ++ out, err := mdCmdOutput(cmd, cs) ++ if err != nil { ++ return err ++ } ++ cont := cs[:start] + "" + "\n" + out + "\n" + cs[end:] ++ ++ fi, err := os.Stat(targetPath) ++ if err != nil { ++ return err ++ } ++ if err = os.WriteFile(targetPath, []byte(cont), fi.Mode()); err != nil { ++ return fmt.Errorf("failed to write %s: %w", targetPath, err) ++ } ++ ++ return nil ++} ++ ++func mdFilename(cmd *cobra.Command) string { ++ name := cmd.CommandPath() ++ if i := strings.Index(name, " "); i >= 0 { ++ name = name[i+1:] ++ } ++ return strings.ReplaceAll(name, " ", "_") + ".md" ++} ++ ++func mdMakeLink(txt, link string, f *pflag.Flag, isAnchor bool) string { ++ link = "#" + link ++ annotations, ok := f.Annotations[annotation.ExternalURL] ++ if ok && len(annotations) > 0 { ++ link = annotations[0] ++ } else { ++ if !isAnchor { ++ return txt ++ } ++ } ++ ++ return "[" + txt + "](" + link + ")" ++} ++ ++type mdTable struct { ++ out *strings.Builder ++ tabWriter *tabwriter.Writer ++} ++ ++func newMdTable(headers ...string) *mdTable { ++ w := &strings.Builder{} ++ t := &mdTable{ ++ out: w, ++ // Using tabwriter.Debug, which uses "|" as separator instead of tabs, ++ // which is what we want. It's a bit of a hack, but does the job :) ++ tabWriter: tabwriter.NewWriter(w, 5, 5, 1, ' ', tabwriter.Debug), ++ } ++ t.addHeader(headers...) ++ return t ++} ++ ++func (t *mdTable) addHeader(cols ...string) { ++ t.AddRow(cols...) ++ _, _ = t.tabWriter.Write([]byte("|" + strings.Repeat(":---\t", len(cols)) + "\n")) ++} ++ ++func (t *mdTable) AddRow(cols ...string) { ++ for i := range cols { ++ cols[i] = mdEscapePipe(cols[i]) ++ } ++ _, _ = t.tabWriter.Write([]byte("| " + strings.Join(cols, "\t ") + "\t\n")) ++} ++ ++func (t *mdTable) String() string { ++ _ = t.tabWriter.Flush() ++ return adjustSep.ReplaceAllStringFunc(t.out.String()+"\n", func(in string) string { ++ return strings.ReplaceAll(in, " ", "-") ++ }) ++} ++ ++func mdCmdOutput(cmd *cobra.Command, old string) (string, error) { ++ b := &strings.Builder{} ++ ++ desc := cmd.Short ++ if cmd.Long != "" { ++ desc = cmd.Long ++ } ++ if desc != "" { ++ b.WriteString(desc + "\n\n") ++ } ++ ++ if aliases := getAliases(cmd); len(aliases) != 0 { ++ b.WriteString("### Aliases\n\n") ++ b.WriteString("`" + strings.Join(aliases, "`, `") + "`") ++ b.WriteString("\n\n") ++ } ++ ++ if len(cmd.Commands()) != 0 { ++ b.WriteString("### Subcommands\n\n") ++ table := newMdTable("Name", "Description") ++ for _, c := range cmd.Commands() { ++ table.AddRow(fmt.Sprintf("[`%s`](%s)", c.Name(), mdFilename(c)), c.Short) ++ } ++ b.WriteString(table.String() + "\n") ++ } ++ ++ // add inherited flags before checking for flags availability ++ cmd.Flags().AddFlagSet(cmd.InheritedFlags()) ++ ++ if cmd.Flags().HasAvailableFlags() { ++ b.WriteString("### Options\n\n") ++ table := newMdTable("Name", "Type", "Default", "Description") ++ cmd.Flags().VisitAll(func(f *pflag.Flag) { ++ if f.Hidden { ++ return ++ } ++ isLink := strings.Contains(old, "") ++ var name string ++ if f.Shorthand != "" { ++ name = mdMakeLink("`-"+f.Shorthand+"`", f.Name, f, isLink) ++ name += ", " ++ } ++ name += mdMakeLink("`--"+f.Name+"`", f.Name, f, isLink) ++ ++ var ftype string ++ if f.Value.Type() != "bool" { ++ ftype = "`" + f.Value.Type() + "`" ++ } ++ ++ var defval string ++ if v, ok := f.Annotations[annotation.DefaultValue]; ok && len(v) > 0 { ++ defval = v[0] ++ if cd, ok := f.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd, "`") ++ } ++ } else if f.DefValue != "" && (f.Value.Type() != "bool" && f.DefValue != "true") && f.DefValue != "[]" { ++ defval = "`" + f.DefValue + "`" ++ } ++ ++ usage := f.Usage ++ if cd, ok := f.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd, "`") ++ } ++ table.AddRow(name, ftype, defval, mdReplaceNewline(usage)) ++ }) ++ b.WriteString(table.String()) ++ } ++ ++ return b.String(), nil ++} ++ ++func mdEscapePipe(s string) string { ++ return strings.ReplaceAll(s, `|`, `\|`) ++} ++ ++func mdReplaceNewline(s string) string { ++ return nlRegexp.ReplaceAllString(s, "
") ++} +diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go +new file mode 100644 +index 000000000000..f6ae6b853bfc +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go +@@ -0,0 +1,433 @@ ++// Copyright 2017 cli-docs-tool authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package clidocstool ++ ++import ( ++ "fmt" ++ "io" ++ "log" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ ++ "github.com/docker/cli-docs-tool/annotation" ++ "github.com/spf13/cobra" ++ "github.com/spf13/pflag" ++ "gopkg.in/yaml.v3" ++) ++ ++type cmdOption struct { ++ Option string ++ Shorthand string `yaml:",omitempty"` ++ ValueType string `yaml:"value_type,omitempty"` ++ DefaultValue string `yaml:"default_value,omitempty"` ++ Description string `yaml:",omitempty"` ++ DetailsURL string `yaml:"details_url,omitempty"` // DetailsURL contains an anchor-id or link for more information on this flag ++ Deprecated bool ++ Hidden bool ++ MinAPIVersion string `yaml:"min_api_version,omitempty"` ++ Experimental bool ++ ExperimentalCLI bool ++ Kubernetes bool ++ Swarm bool ++ OSType string `yaml:"os_type,omitempty"` ++} ++ ++type cmdDoc struct { ++ Name string `yaml:"command"` ++ SeeAlso []string `yaml:"parent,omitempty"` ++ Version string `yaml:"engine_version,omitempty"` ++ Aliases string `yaml:",omitempty"` ++ Short string `yaml:",omitempty"` ++ Long string `yaml:",omitempty"` ++ Usage string `yaml:",omitempty"` ++ Pname string `yaml:",omitempty"` ++ Plink string `yaml:",omitempty"` ++ Cname []string `yaml:",omitempty"` ++ Clink []string `yaml:",omitempty"` ++ Options []cmdOption `yaml:",omitempty"` ++ InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` ++ Example string `yaml:"examples,omitempty"` ++ Deprecated bool ++ MinAPIVersion string `yaml:"min_api_version,omitempty"` ++ Experimental bool ++ ExperimentalCLI bool ++ Kubernetes bool ++ Swarm bool ++ OSType string `yaml:"os_type,omitempty"` ++} ++ ++// GenYamlTree creates yaml structured ref files for this command and all descendants ++// in the directory given. This function may not work ++// correctly if your command names have `-` in them. If you have `cmd` with two ++// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` ++// it is undefined which help output will be in the file `cmd-sub-third.1`. ++func (c *Client) GenYamlTree(cmd *cobra.Command) error { ++ emptyStr := func(s string) string { return "" } ++ if err := c.loadLongDescription(cmd); err != nil { ++ return err ++ } ++ return c.genYamlTreeCustom(cmd, emptyStr) ++} ++ ++// genYamlTreeCustom creates yaml structured ref files. ++func (c *Client) genYamlTreeCustom(cmd *cobra.Command, filePrepender func(string) string) error { ++ for _, sc := range cmd.Commands() { ++ if !sc.Runnable() && !sc.HasAvailableSubCommands() { ++ // skip non-runnable commands without subcommands ++ // but *do* generate YAML for hidden and deprecated commands ++ // the YAML will have those included as metadata, so that the ++ // documentation repository can decide whether or not to present them ++ continue ++ } ++ if err := c.genYamlTreeCustom(sc, filePrepender); err != nil { ++ return err ++ } ++ } ++ ++ // always disable the addition of [flags] to the usage ++ cmd.DisableFlagsInUseLine = true ++ ++ // The "root" command used in the generator is just a "stub", and only has a ++ // list of subcommands, but not (e.g.) global options/flags. We should fix ++ // that, so that the YAML file for the docker "root" command contains the ++ // global flags. ++ ++ // Skip the root command altogether, to prevent generating a useless ++ // YAML file for plugins. ++ if c.plugin && !cmd.HasParent() { ++ return nil ++ } ++ ++ log.Printf("INFO: Generating YAML for %q", cmd.CommandPath()) ++ basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml" ++ target := filepath.Join(c.target, basename) ++ f, err := os.Create(target) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(target)); err != nil { ++ return err ++ } ++ return c.genYamlCustom(cmd, f) ++} ++ ++// genYamlCustom creates custom yaml output. ++// nolint: gocyclo ++func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error { ++ const ( ++ // shortMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace ('short: '). ++ shortMaxWidth = 73 ++ ++ // longMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace ('long: '). ++ longMaxWidth = 74 ++ ) ++ ++ // necessary to add inherited flags otherwise some ++ // fields are not properly declared like usage ++ cmd.Flags().AddFlagSet(cmd.InheritedFlags()) ++ ++ cliDoc := cmdDoc{ ++ Name: cmd.CommandPath(), ++ Aliases: strings.Join(getAliases(cmd), ", "), ++ Short: forceMultiLine(cmd.Short, shortMaxWidth), ++ Long: forceMultiLine(cmd.Long, longMaxWidth), ++ Example: cmd.Example, ++ Deprecated: len(cmd.Deprecated) > 0, ++ } ++ ++ if len(cliDoc.Long) == 0 { ++ cliDoc.Long = cliDoc.Short ++ } ++ ++ if cmd.Runnable() { ++ cliDoc.Usage = cmd.UseLine() ++ } ++ ++ // check recursively to handle inherited annotations ++ for curr := cmd; curr != nil; curr = curr.Parent() { ++ if v, ok := curr.Annotations["version"]; ok && cliDoc.MinAPIVersion == "" { ++ cliDoc.MinAPIVersion = v ++ } ++ if _, ok := curr.Annotations["experimental"]; ok && !cliDoc.Experimental { ++ cliDoc.Experimental = true ++ } ++ if _, ok := curr.Annotations["experimentalCLI"]; ok && !cliDoc.ExperimentalCLI { ++ cliDoc.ExperimentalCLI = true ++ } ++ if _, ok := curr.Annotations["kubernetes"]; ok && !cliDoc.Kubernetes { ++ cliDoc.Kubernetes = true ++ } ++ if _, ok := curr.Annotations["swarm"]; ok && !cliDoc.Swarm { ++ cliDoc.Swarm = true ++ } ++ if o, ok := curr.Annotations["ostype"]; ok && cliDoc.OSType == "" { ++ cliDoc.OSType = o ++ } ++ if _, ok := cmd.Annotations[annotation.CodeDelimiter]; !ok { ++ if cd, cok := curr.Annotations[annotation.CodeDelimiter]; cok { ++ if cmd.Annotations == nil { ++ cmd.Annotations = map[string]string{} ++ } ++ cmd.Annotations[annotation.CodeDelimiter] = cd ++ } ++ } ++ } ++ ++ anchors := make(map[string]struct{}) ++ if a, ok := cmd.Annotations["anchors"]; ok && a != "" { ++ for _, anchor := range strings.Split(a, ",") { ++ anchors[anchor] = struct{}{} ++ } ++ } ++ ++ flags := cmd.NonInheritedFlags() ++ if flags.HasFlags() { ++ cliDoc.Options = genFlagResult(cmd, flags, anchors) ++ } ++ flags = cmd.InheritedFlags() ++ if flags.HasFlags() { ++ cliDoc.InheritedOptions = genFlagResult(cmd, flags, anchors) ++ } ++ ++ if hasSeeAlso(cmd) { ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ cliDoc.Pname = parent.CommandPath() ++ cliDoc.Plink = strings.Replace(cliDoc.Pname, " ", "_", -1) + ".yaml" ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ cliDoc.Cname = append(cliDoc.Cname, cliDoc.Name+" "+child.Name()) ++ cliDoc.Clink = append(cliDoc.Clink, strings.Replace(cliDoc.Name+"_"+child.Name(), " ", "_", -1)+".yaml") ++ } ++ } ++ ++ final, err := yaml.Marshal(&cliDoc) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ if _, err := fmt.Fprintln(w, string(final)); err != nil { ++ return err ++ } ++ return nil ++} ++ ++func genFlagResult(cmd *cobra.Command, flags *pflag.FlagSet, anchors map[string]struct{}) []cmdOption { ++ var ( ++ result []cmdOption ++ opt cmdOption ++ ) ++ ++ const ( ++ // shortMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace (' default_value: '). ++ defaultValueMaxWidth = 64 ++ ++ // longMaxWidth is the maximum width for the "Short" description before ++ // we force YAML to use multi-line syntax. The goal is to make the total ++ // width fit within 80 characters. This value is based on 80 characters ++ // minus the with of the field, colon, and whitespace (' description: '). ++ descriptionMaxWidth = 66 ++ ) ++ ++ flags.VisitAll(func(flag *pflag.Flag) { ++ opt = cmdOption{ ++ Option: flag.Name, ++ ValueType: flag.Value.Type(), ++ Deprecated: len(flag.Deprecated) > 0, ++ Hidden: flag.Hidden, ++ } ++ ++ var defval string ++ if v, ok := flag.Annotations[annotation.DefaultValue]; ok && len(v) > 0 { ++ defval = v[0] ++ if cd, ok := flag.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ defval = strings.ReplaceAll(defval, cd, "`") ++ } ++ } else { ++ defval = flag.DefValue ++ } ++ opt.DefaultValue = forceMultiLine(defval, defaultValueMaxWidth) ++ ++ usage := flag.Usage ++ if cd, ok := flag.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd[0], "`") ++ } else if cd, ok := cmd.Annotations[annotation.CodeDelimiter]; ok { ++ usage = strings.ReplaceAll(usage, cd, "`") ++ } ++ opt.Description = forceMultiLine(usage, descriptionMaxWidth) ++ ++ if v, ok := flag.Annotations[annotation.ExternalURL]; ok && len(v) > 0 { ++ opt.DetailsURL = strings.TrimPrefix(v[0], "https://docs.docker.com") ++ } else if _, ok = anchors[flag.Name]; ok { ++ opt.DetailsURL = "#" + flag.Name ++ } ++ ++ // Todo, when we mark a shorthand is deprecated, but specify an empty message. ++ // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. ++ // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. ++ if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { ++ opt.Shorthand = flag.Shorthand ++ } ++ if _, ok := flag.Annotations["experimental"]; ok { ++ opt.Experimental = true ++ } ++ if _, ok := flag.Annotations["deprecated"]; ok { ++ opt.Deprecated = true ++ } ++ if v, ok := flag.Annotations["version"]; ok { ++ opt.MinAPIVersion = v[0] ++ } ++ if _, ok := flag.Annotations["experimentalCLI"]; ok { ++ opt.ExperimentalCLI = true ++ } ++ if _, ok := flag.Annotations["kubernetes"]; ok { ++ opt.Kubernetes = true ++ } ++ if _, ok := flag.Annotations["swarm"]; ok { ++ opt.Swarm = true ++ } ++ ++ // Note that the annotation can have multiple ostypes set, however, multiple ++ // values are currently not used (and unlikely will). ++ // ++ // To simplify usage of the os_type property in the YAML, and for consistency ++ // with the same property for commands, we're only using the first ostype that's set. ++ if ostypes, ok := flag.Annotations["ostype"]; ok && len(opt.OSType) == 0 && len(ostypes) > 0 { ++ opt.OSType = ostypes[0] ++ } ++ ++ result = append(result, opt) ++ }) ++ ++ return result ++} ++ ++// forceMultiLine appends a newline (\n) to strings that are longer than max ++// to force the yaml lib to use block notation (https://yaml.org/spec/1.2/spec.html#Block) ++// instead of a single-line string with newlines and tabs encoded("string\nline1\nline2"). ++// ++// This makes the generated YAML more readable, and easier to review changes. ++// max can be used to customize the width to keep the whole line < 80 chars. ++func forceMultiLine(s string, max int) string { ++ s = strings.TrimSpace(s) ++ if len(s) > max && !strings.Contains(s, "\n") { ++ s = s + "\n" ++ } ++ return s ++} ++ ++// Small duplication for cobra utils ++func hasSeeAlso(cmd *cobra.Command) bool { ++ if cmd.HasParent() { ++ return true ++ } ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ return true ++ } ++ return false ++} ++ ++// loadLongDescription gets long descriptions and examples from markdown. ++func (c *Client) loadLongDescription(parentCmd *cobra.Command) error { ++ for _, cmd := range parentCmd.Commands() { ++ if cmd.HasSubCommands() { ++ if err := c.loadLongDescription(cmd); err != nil { ++ return err ++ } ++ } ++ name := cmd.CommandPath() ++ if i := strings.Index(name, " "); i >= 0 { ++ // remove root command / binary name ++ name = name[i+1:] ++ } ++ if name == "" { ++ continue ++ } ++ mdFile := strings.ReplaceAll(name, " ", "_") + ".md" ++ sourcePath := filepath.Join(c.source, mdFile) ++ content, err := os.ReadFile(sourcePath) ++ if os.IsNotExist(err) { ++ log.Printf("WARN: %s does not exist, skipping Markdown examples for YAML doc\n", mdFile) ++ continue ++ } ++ if err != nil { ++ return err ++ } ++ applyDescriptionAndExamples(cmd, string(content)) ++ } ++ return nil ++} ++ ++// applyDescriptionAndExamples fills in cmd.Long and cmd.Example with the ++// "Description" and "Examples" H2 sections in mdString (if present). ++func applyDescriptionAndExamples(cmd *cobra.Command, mdString string) { ++ sections := getSections(mdString) ++ var ( ++ anchors []string ++ md string ++ ) ++ if sections["description"] != "" { ++ md, anchors = cleanupMarkDown(sections["description"]) ++ cmd.Long = md ++ anchors = append(anchors, md) ++ } ++ if sections["examples"] != "" { ++ md, anchors = cleanupMarkDown(sections["examples"]) ++ cmd.Example = md ++ anchors = append(anchors, md) ++ } ++ if len(anchors) > 0 { ++ if cmd.Annotations == nil { ++ cmd.Annotations = make(map[string]string) ++ } ++ cmd.Annotations["anchors"] = strings.Join(anchors, ",") ++ } ++} ++ ++type byName []*cobra.Command ++ ++func (s byName) Len() int { return len(s) } ++func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } ++func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } +diff --git a/vendor/github.com/docker/cli-docs-tool/docker-bake.hcl b/vendor/github.com/docker/cli-docs-tool/docker-bake.hcl +new file mode 100644 +index 000000000000..4a5f44f83018 +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/docker-bake.hcl +@@ -0,0 +1,51 @@ ++// Copyright 2021 cli-docs-tool authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++group "default" { ++ targets = ["test"] ++} ++ ++group "validate" { ++ targets = ["lint", "vendor-validate", "license-validate"] ++} ++ ++target "lint" { ++ target = "lint" ++ output = ["type=cacheonly"] ++} ++ ++target "vendor-validate" { ++ target = "vendor-validate" ++ output = ["type=cacheonly"] ++} ++ ++target "vendor-update" { ++ target = "vendor-update" ++ output = ["."] ++} ++ ++target "test" { ++ target = "test-coverage" ++ output = ["."] ++} ++ ++target "license-validate" { ++ target = "license-validate" ++ output = ["type=cacheonly"] ++} ++ ++target "license-update" { ++ target = "license-update" ++ output = ["."] ++} +diff --git a/vendor/github.com/docker/cli-docs-tool/markdown.go b/vendor/github.com/docker/cli-docs-tool/markdown.go +new file mode 100644 +index 000000000000..32849236ed9c +--- /dev/null ++++ b/vendor/github.com/docker/cli-docs-tool/markdown.go +@@ -0,0 +1,87 @@ ++// Copyright 2017 cli-docs-tool authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package clidocstool ++ ++import ( ++ "regexp" ++ "strings" ++ "unicode" ++) ++ ++var ( ++ // mdHeading matches MarkDown H1..h6 headings. Note that this regex may produce ++ // false positives for (e.g.) comments in code-blocks (# this is a comment), ++ // so should not be used as a generic regex for other purposes. ++ mdHeading = regexp.MustCompile(`^([#]{1,6})\s(.*)$`) ++ // htmlAnchor matches inline HTML anchors. This is intended to only match anchors ++ // for our use-case; DO NOT consider using this as a generic regex, or at least ++ // not before reading https://stackoverflow.com/a/1732454/1811501. ++ htmlAnchor = regexp.MustCompile(`\s*`) ++) ++ ++// getSections returns all H2 sections by title (lowercase) ++func getSections(mdString string) map[string]string { ++ parsedContent := strings.Split("\n"+mdString, "\n## ") ++ sections := make(map[string]string, len(parsedContent)) ++ for _, s := range parsedContent { ++ if strings.HasPrefix(s, "#") { ++ // not a H2 Section ++ continue ++ } ++ parts := strings.SplitN(s, "\n", 2) ++ if len(parts) == 2 { ++ sections[strings.ToLower(parts[0])] = parts[1] ++ } ++ } ++ return sections ++} ++ ++// cleanupMarkDown cleans up the MarkDown passed in mdString for inclusion in ++// YAML. It removes trailing whitespace and substitutes tabs for four spaces ++// to prevent YAML switching to use "compact" form; ("line1 \nline\t2\n") ++// which, although equivalent, is hard to read. ++func cleanupMarkDown(mdString string) (md string, anchors []string) { ++ // remove leading/trailing whitespace, and replace tabs in the whole content ++ mdString = strings.TrimSpace(mdString) ++ mdString = strings.ReplaceAll(mdString, "\t", " ") ++ mdString = strings.ReplaceAll(mdString, "https://docs.docker.com", "") ++ ++ var id string ++ // replace trailing whitespace per line, and handle custom anchors ++ lines := strings.Split(mdString, "\n") ++ for i := 0; i < len(lines); i++ { ++ lines[i] = strings.TrimRightFunc(lines[i], unicode.IsSpace) ++ lines[i], id = convertHTMLAnchor(lines[i]) ++ if id != "" { ++ anchors = append(anchors, id) ++ } ++ } ++ return strings.Join(lines, "\n"), anchors ++} ++ ++// convertHTMLAnchor converts inline anchor-tags in headings () ++// to an extended-markdown property ({#myanchor}). Extended Markdown properties ++// are not supported in GitHub Flavored Markdown, but are supported by Jekyll, ++// and lead to cleaner HTML in our docs, and prevents duplicate anchors. ++// It returns the converted MarkDown heading and the custom ID (if present) ++func convertHTMLAnchor(mdLine string) (md string, customID string) { ++ if m := mdHeading.FindStringSubmatch(mdLine); len(m) > 0 { ++ if a := htmlAnchor.FindStringSubmatch(m[2]); len(a) > 0 { ++ customID = a[1] ++ mdLine = m[1] + " " + htmlAnchor.ReplaceAllString(m[2], "") + " {#" + customID + "}" ++ } ++ } ++ return mdLine, customID ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/.gitignore b/vendor/github.com/russross/blackfriday/v2/.gitignore +new file mode 100644 +index 000000000000..75623dcccbb7 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/.gitignore +@@ -0,0 +1,8 @@ ++*.out ++*.swp ++*.8 ++*.6 ++_obj ++_test* ++markdown ++tags +diff --git a/vendor/github.com/russross/blackfriday/v2/.travis.yml b/vendor/github.com/russross/blackfriday/v2/.travis.yml +new file mode 100644 +index 000000000000..b0b525a5a8e1 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/.travis.yml +@@ -0,0 +1,17 @@ ++sudo: false ++language: go ++go: ++ - "1.10.x" ++ - "1.11.x" ++ - tip ++matrix: ++ fast_finish: true ++ allow_failures: ++ - go: tip ++install: ++ - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). ++script: ++ - go get -t -v ./... ++ - diff -u <(echo -n) <(gofmt -d -s .) ++ - go tool vet . ++ - go test -v ./... +diff --git a/vendor/github.com/russross/blackfriday/v2/LICENSE.txt b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt +new file mode 100644 +index 000000000000..2885af3602d8 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt +@@ -0,0 +1,29 @@ ++Blackfriday is distributed under the Simplified BSD License: ++ ++> Copyright © 2011 Russ Ross ++> All rights reserved. ++> ++> Redistribution and use in source and binary forms, with or without ++> modification, are permitted provided that the following conditions ++> are met: ++> ++> 1. Redistributions of source code must retain the above copyright ++> notice, this list of conditions and the following disclaimer. ++> ++> 2. Redistributions in binary form must reproduce the above ++> copyright notice, this list of conditions and the following ++> disclaimer in the documentation and/or other materials provided with ++> the distribution. ++> ++> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ++> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++> POSSIBILITY OF SUCH DAMAGE. +diff --git a/vendor/github.com/russross/blackfriday/v2/README.md b/vendor/github.com/russross/blackfriday/v2/README.md +new file mode 100644 +index 000000000000..d9c08a22fc54 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/README.md +@@ -0,0 +1,335 @@ ++Blackfriday ++[![Build Status][BuildV2SVG]][BuildV2URL] ++[![PkgGoDev][PkgGoDevV2SVG]][PkgGoDevV2URL] ++=========== ++ ++Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It ++is paranoid about its input (so you can safely feed it user-supplied ++data), it is fast, it supports common extensions (tables, smart ++punctuation substitutions, etc.), and it is safe for all utf-8 ++(unicode) input. ++ ++HTML output is currently supported, along with Smartypants ++extensions. ++ ++It started as a translation from C of [Sundown][3]. ++ ++ ++Installation ++------------ ++ ++Blackfriday is compatible with modern Go releases in module mode. ++With Go installed: ++ ++ go get github.com/russross/blackfriday/v2 ++ ++will resolve and add the package to the current development module, ++then build and install it. Alternatively, you can achieve the same ++if you import it in a package: ++ ++ import "github.com/russross/blackfriday/v2" ++ ++and `go get` without parameters. ++ ++Legacy GOPATH mode is unsupported. ++ ++ ++Versions ++-------- ++ ++Currently maintained and recommended version of Blackfriday is `v2`. It's being ++developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the ++documentation is available at ++https://pkg.go.dev/github.com/russross/blackfriday/v2. ++ ++It is `go get`-able in module mode at `github.com/russross/blackfriday/v2`. ++ ++Version 2 offers a number of improvements over v1: ++ ++* Cleaned up API ++* A separate call to [`Parse`][4], which produces an abstract syntax tree for ++ the document ++* Latest bug fixes ++* Flexibility to easily add your own rendering extensions ++ ++Potential drawbacks: ++ ++* Our benchmarks show v2 to be slightly slower than v1. Currently in the ++ ballpark of around 15%. ++* API breakage. If you can't afford modifying your code to adhere to the new API ++ and don't care too much about the new features, v2 is probably not for you. ++* Several bug fixes are trailing behind and still need to be forward-ported to ++ v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for ++ tracking. ++ ++If you are still interested in the legacy `v1`, you can import it from ++`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found ++here: https://pkg.go.dev/github.com/russross/blackfriday. ++ ++ ++Usage ++----- ++ ++For the most sensible markdown processing, it is as simple as getting your input ++into a byte slice and calling: ++ ++```go ++output := blackfriday.Run(input) ++``` ++ ++Your input will be parsed and the output rendered with a set of most popular ++extensions enabled. If you want the most basic feature set, corresponding with ++the bare Markdown specification, use: ++ ++```go ++output := blackfriday.Run(input, blackfriday.WithNoExtensions()) ++``` ++ ++### Sanitize untrusted content ++ ++Blackfriday itself does nothing to protect against malicious content. If you are ++dealing with user-supplied markdown, we recommend running Blackfriday's output ++through HTML sanitizer such as [Bluemonday][5]. ++ ++Here's an example of simple usage of Blackfriday together with Bluemonday: ++ ++```go ++import ( ++ "github.com/microcosm-cc/bluemonday" ++ "github.com/russross/blackfriday/v2" ++) ++ ++// ... ++unsafe := blackfriday.Run(input) ++html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) ++``` ++ ++### Custom options ++ ++If you want to customize the set of options, use `blackfriday.WithExtensions`, ++`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. ++ ++### `blackfriday-tool` ++ ++You can also check out `blackfriday-tool` for a more complete example ++of how to use it. Download and install it using: ++ ++ go get github.com/russross/blackfriday-tool ++ ++This is a simple command-line tool that allows you to process a ++markdown file using a standalone program. You can also browse the ++source directly on github if you are just looking for some example ++code: ++ ++* ++ ++Note that if you have not already done so, installing ++`blackfriday-tool` will be sufficient to download and install ++blackfriday in addition to the tool itself. The tool binary will be ++installed in `$GOPATH/bin`. This is a statically-linked binary that ++can be copied to wherever you need it without worrying about ++dependencies and library versions. ++ ++### Sanitized anchor names ++ ++Blackfriday includes an algorithm for creating sanitized anchor names ++corresponding to a given input text. This algorithm is used to create ++anchors for headings when `AutoHeadingIDs` extension is enabled. The ++algorithm has a specification, so that other packages can create ++compatible anchor names and links to those anchors. ++ ++The specification is located at https://pkg.go.dev/github.com/russross/blackfriday/v2#hdr-Sanitized_Anchor_Names. ++ ++[`SanitizedAnchorName`](https://pkg.go.dev/github.com/russross/blackfriday/v2#SanitizedAnchorName) exposes this functionality, and can be used to ++create compatible links to the anchor names generated by blackfriday. ++This algorithm is also implemented in a small standalone package at ++[`github.com/shurcooL/sanitized_anchor_name`](https://pkg.go.dev/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients ++that want a small package and don't need full functionality of blackfriday. ++ ++ ++Features ++-------- ++ ++All features of Sundown are supported, including: ++ ++* **Compatibility**. The Markdown v1.0.3 test suite passes with ++ the `--tidy` option. Without `--tidy`, the differences are ++ mostly in whitespace and entity escaping, where blackfriday is ++ more consistent and cleaner. ++ ++* **Common extensions**, including table support, fenced code ++ blocks, autolinks, strikethroughs, non-strict emphasis, etc. ++ ++* **Safety**. Blackfriday is paranoid when parsing, making it safe ++ to feed untrusted user input without fear of bad things ++ happening. The test suite stress tests this and there are no ++ known inputs that make it crash. If you find one, please let me ++ know and send me the input that does it. ++ ++ NOTE: "safety" in this context means *runtime safety only*. In order to ++ protect yourself against JavaScript injection in untrusted content, see ++ [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content). ++ ++* **Fast processing**. It is fast enough to render on-demand in ++ most web applications without having to cache the output. ++ ++* **Thread safety**. You can run multiple parsers in different ++ goroutines without ill effect. There is no dependence on global ++ shared state. ++ ++* **Minimal dependencies**. Blackfriday only depends on standard ++ library packages in Go. The source code is pretty ++ self-contained, so it is easy to add to any project, including ++ Google App Engine projects. ++ ++* **Standards compliant**. Output successfully validates using the ++ W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional. ++ ++ ++Extensions ++---------- ++ ++In addition to the standard markdown syntax, this package ++implements the following extensions: ++ ++* **Intra-word emphasis supression**. The `_` character is ++ commonly used inside words when discussing code, so having ++ markdown interpret it as an emphasis command is usually the ++ wrong thing. Blackfriday lets you treat all emphasis markers as ++ normal characters when they occur inside a word. ++ ++* **Tables**. Tables can be created by drawing them in the input ++ using a simple syntax: ++ ++ ``` ++ Name | Age ++ --------|------ ++ Bob | 27 ++ Alice | 23 ++ ``` ++ ++* **Fenced code blocks**. In addition to the normal 4-space ++ indentation to mark code blocks, you can explicitly mark them ++ and supply a language (to make syntax highlighting simple). Just ++ mark it like this: ++ ++ ```go ++ func getTrue() bool { ++ return true ++ } ++ ``` ++ ++ You can use 3 or more backticks to mark the beginning of the ++ block, and the same number to mark the end of the block. ++ ++ To preserve classes of fenced code blocks while using the bluemonday ++ HTML sanitizer, use the following policy: ++ ++ ```go ++ p := bluemonday.UGCPolicy() ++ p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code") ++ html := p.SanitizeBytes(unsafe) ++ ``` ++ ++* **Definition lists**. A simple definition list is made of a single-line ++ term followed by a colon and the definition for that term. ++ ++ Cat ++ : Fluffy animal everyone likes ++ ++ Internet ++ : Vector of transmission for pictures of cats ++ ++ Terms must be separated from the previous definition by a blank line. ++ ++* **Footnotes**. A marker in the text that will become a superscript number; ++ a footnote definition that will be placed in a list of footnotes at the ++ end of the document. A footnote looks like this: ++ ++ This is a footnote.[^1] ++ ++ [^1]: the footnote text. ++ ++* **Autolinking**. Blackfriday can find URLs that have not been ++ explicitly marked as links and turn them into links. ++ ++* **Strikethrough**. Use two tildes (`~~`) to mark text that ++ should be crossed out. ++ ++* **Hard line breaks**. With this extension enabled newlines in the input ++ translate into line breaks in the output. This extension is off by default. ++ ++* **Smart quotes**. Smartypants-style punctuation substitution is ++ supported, turning normal double- and single-quote marks into ++ curly quotes, etc. ++ ++* **LaTeX-style dash parsing** is an additional option, where `--` ++ is translated into `–`, and `---` is translated into ++ `—`. This differs from most smartypants processors, which ++ turn a single hyphen into an ndash and a double hyphen into an ++ mdash. ++ ++* **Smart fractions**, where anything that looks like a fraction ++ is translated into suitable HTML (instead of just a few special ++ cases like most smartypant processors). For example, `4/5` ++ becomes `45`, which renders as ++ 45. ++ ++ ++Other renderers ++--------------- ++ ++Blackfriday is structured to allow alternative rendering engines. Here ++are a few of note: ++ ++* [github_flavored_markdown](https://pkg.go.dev/github.com/shurcooL/github_flavored_markdown): ++ provides a GitHub Flavored Markdown renderer with fenced code block ++ highlighting, clickable heading anchor links. ++ ++ It's not customizable, and its goal is to produce HTML output ++ equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode), ++ except the rendering is performed locally. ++ ++* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, ++ but for markdown. ++ ++* [LaTeX output](https://gitlab.com/ambrevar/blackfriday-latex): ++ renders output as LaTeX. ++ ++* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience ++ integration with the [Chroma](https://github.com/alecthomas/chroma) code ++ highlighting library. bfchroma is only compatible with v2 of Blackfriday and ++ provides a drop-in renderer ready to use with Blackfriday, as well as ++ options and means for further customization. ++ ++* [Blackfriday-Confluence](https://github.com/kentaro-m/blackfriday-confluence): provides a [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) renderer. ++ ++* [Blackfriday-Slack](https://github.com/karriereat/blackfriday-slack): converts markdown to slack message style ++ ++ ++TODO ++---- ++ ++* More unit testing ++* Improve Unicode support. It does not understand all Unicode ++ rules (about what constitutes a letter, a punctuation symbol, ++ etc.), so it may fail to detect word boundaries correctly in ++ some instances. It is safe on all UTF-8 input. ++ ++ ++License ++------- ++ ++[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt) ++ ++ ++ [1]: https://daringfireball.net/projects/markdown/ "Markdown" ++ [2]: https://golang.org/ "Go Language" ++ [3]: https://github.com/vmg/sundown "Sundown" ++ [4]: https://pkg.go.dev/github.com/russross/blackfriday/v2#Parse "Parse func" ++ [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" ++ ++ [BuildV2SVG]: https://travis-ci.org/russross/blackfriday.svg?branch=v2 ++ [BuildV2URL]: https://travis-ci.org/russross/blackfriday ++ [PkgGoDevV2SVG]: https://pkg.go.dev/badge/github.com/russross/blackfriday/v2 ++ [PkgGoDevV2URL]: https://pkg.go.dev/github.com/russross/blackfriday/v2 +diff --git a/vendor/github.com/russross/blackfriday/v2/block.go b/vendor/github.com/russross/blackfriday/v2/block.go +new file mode 100644 +index 000000000000..dcd61e6e35bc +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/block.go +@@ -0,0 +1,1612 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// Functions to parse block-level elements. ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "html" ++ "regexp" ++ "strings" ++ "unicode" ++) ++ ++const ( ++ charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" ++ escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" ++) ++ ++var ( ++ reBackslashOrAmp = regexp.MustCompile("[\\&]") ++ reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + escapable + "|" + charEntity) ++) ++ ++// Parse block-level data. ++// Note: this function and many that it calls assume that ++// the input buffer ends with a newline. ++func (p *Markdown) block(data []byte) { ++ // this is called recursively: enforce a maximum depth ++ if p.nesting >= p.maxNesting { ++ return ++ } ++ p.nesting++ ++ ++ // parse out one block-level construct at a time ++ for len(data) > 0 { ++ // prefixed heading: ++ // ++ // # Heading 1 ++ // ## Heading 2 ++ // ... ++ // ###### Heading 6 ++ if p.isPrefixHeading(data) { ++ data = data[p.prefixHeading(data):] ++ continue ++ } ++ ++ // block of preformatted HTML: ++ // ++ //
++ // ... ++ //
++ if data[0] == '<' { ++ if i := p.html(data, true); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ ++ // title block ++ // ++ // % stuff ++ // % more stuff ++ // % even more stuff ++ if p.extensions&Titleblock != 0 { ++ if data[0] == '%' { ++ if i := p.titleBlock(data, true); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ } ++ ++ // blank lines. note: returns the # of bytes to skip ++ if i := p.isEmpty(data); i > 0 { ++ data = data[i:] ++ continue ++ } ++ ++ // indented code block: ++ // ++ // func max(a, b int) int { ++ // if a > b { ++ // return a ++ // } ++ // return b ++ // } ++ if p.codePrefix(data) > 0 { ++ data = data[p.code(data):] ++ continue ++ } ++ ++ // fenced code block: ++ // ++ // ``` go ++ // func fact(n int) int { ++ // if n <= 1 { ++ // return n ++ // } ++ // return n * fact(n-1) ++ // } ++ // ``` ++ if p.extensions&FencedCode != 0 { ++ if i := p.fencedCodeBlock(data, true); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ ++ // horizontal rule: ++ // ++ // ------ ++ // or ++ // ****** ++ // or ++ // ______ ++ if p.isHRule(data) { ++ p.addBlock(HorizontalRule, nil) ++ var i int ++ for i = 0; i < len(data) && data[i] != '\n'; i++ { ++ } ++ data = data[i:] ++ continue ++ } ++ ++ // block quote: ++ // ++ // > A big quote I found somewhere ++ // > on the web ++ if p.quotePrefix(data) > 0 { ++ data = data[p.quote(data):] ++ continue ++ } ++ ++ // table: ++ // ++ // Name | Age | Phone ++ // ------|-----|--------- ++ // Bob | 31 | 555-1234 ++ // Alice | 27 | 555-4321 ++ if p.extensions&Tables != 0 { ++ if i := p.table(data); i > 0 { ++ data = data[i:] ++ continue ++ } ++ } ++ ++ // an itemized/unordered list: ++ // ++ // * Item 1 ++ // * Item 2 ++ // ++ // also works with + or - ++ if p.uliPrefix(data) > 0 { ++ data = data[p.list(data, 0):] ++ continue ++ } ++ ++ // a numbered/ordered list: ++ // ++ // 1. Item 1 ++ // 2. Item 2 ++ if p.oliPrefix(data) > 0 { ++ data = data[p.list(data, ListTypeOrdered):] ++ continue ++ } ++ ++ // definition lists: ++ // ++ // Term 1 ++ // : Definition a ++ // : Definition b ++ // ++ // Term 2 ++ // : Definition c ++ if p.extensions&DefinitionLists != 0 { ++ if p.dliPrefix(data) > 0 { ++ data = data[p.list(data, ListTypeDefinition):] ++ continue ++ } ++ } ++ ++ // anything else must look like a normal paragraph ++ // note: this finds underlined headings, too ++ data = data[p.paragraph(data):] ++ } ++ ++ p.nesting-- ++} ++ ++func (p *Markdown) addBlock(typ NodeType, content []byte) *Node { ++ p.closeUnmatchedBlocks() ++ container := p.addChild(typ, 0) ++ container.content = content ++ return container ++} ++ ++func (p *Markdown) isPrefixHeading(data []byte) bool { ++ if data[0] != '#' { ++ return false ++ } ++ ++ if p.extensions&SpaceHeadings != 0 { ++ level := 0 ++ for level < 6 && level < len(data) && data[level] == '#' { ++ level++ ++ } ++ if level == len(data) || data[level] != ' ' { ++ return false ++ } ++ } ++ return true ++} ++ ++func (p *Markdown) prefixHeading(data []byte) int { ++ level := 0 ++ for level < 6 && level < len(data) && data[level] == '#' { ++ level++ ++ } ++ i := skipChar(data, level, ' ') ++ end := skipUntilChar(data, i, '\n') ++ skip := end ++ id := "" ++ if p.extensions&HeadingIDs != 0 { ++ j, k := 0, 0 ++ // find start/end of heading id ++ for j = i; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ { ++ } ++ for k = j + 1; k < end && data[k] != '}'; k++ { ++ } ++ // extract heading id iff found ++ if j < end && k < end { ++ id = string(data[j+2 : k]) ++ end = j ++ skip = k + 1 ++ for end > 0 && data[end-1] == ' ' { ++ end-- ++ } ++ } ++ } ++ for end > 0 && data[end-1] == '#' { ++ if isBackslashEscaped(data, end-1) { ++ break ++ } ++ end-- ++ } ++ for end > 0 && data[end-1] == ' ' { ++ end-- ++ } ++ if end > i { ++ if id == "" && p.extensions&AutoHeadingIDs != 0 { ++ id = SanitizedAnchorName(string(data[i:end])) ++ } ++ block := p.addBlock(Heading, data[i:end]) ++ block.HeadingID = id ++ block.Level = level ++ } ++ return skip ++} ++ ++func (p *Markdown) isUnderlinedHeading(data []byte) int { ++ // test of level 1 heading ++ if data[0] == '=' { ++ i := skipChar(data, 1, '=') ++ i = skipChar(data, i, ' ') ++ if i < len(data) && data[i] == '\n' { ++ return 1 ++ } ++ return 0 ++ } ++ ++ // test of level 2 heading ++ if data[0] == '-' { ++ i := skipChar(data, 1, '-') ++ i = skipChar(data, i, ' ') ++ if i < len(data) && data[i] == '\n' { ++ return 2 ++ } ++ return 0 ++ } ++ ++ return 0 ++} ++ ++func (p *Markdown) titleBlock(data []byte, doRender bool) int { ++ if data[0] != '%' { ++ return 0 ++ } ++ splitData := bytes.Split(data, []byte("\n")) ++ var i int ++ for idx, b := range splitData { ++ if !bytes.HasPrefix(b, []byte("%")) { ++ i = idx // - 1 ++ break ++ } ++ } ++ ++ data = bytes.Join(splitData[0:i], []byte("\n")) ++ consumed := len(data) ++ data = bytes.TrimPrefix(data, []byte("% ")) ++ data = bytes.Replace(data, []byte("\n% "), []byte("\n"), -1) ++ block := p.addBlock(Heading, data) ++ block.Level = 1 ++ block.IsTitleblock = true ++ ++ return consumed ++} ++ ++func (p *Markdown) html(data []byte, doRender bool) int { ++ var i, j int ++ ++ // identify the opening tag ++ if data[0] != '<' { ++ return 0 ++ } ++ curtag, tagfound := p.htmlFindTag(data[1:]) ++ ++ // handle special cases ++ if !tagfound { ++ // check for an HTML comment ++ if size := p.htmlComment(data, doRender); size > 0 { ++ return size ++ } ++ ++ // check for an
tag ++ if size := p.htmlHr(data, doRender); size > 0 { ++ return size ++ } ++ ++ // no special case recognized ++ return 0 ++ } ++ ++ // look for an unindented matching closing tag ++ // followed by a blank line ++ found := false ++ /* ++ closetag := []byte("\n") ++ j = len(curtag) + 1 ++ for !found { ++ // scan for a closing tag at the beginning of a line ++ if skip := bytes.Index(data[j:], closetag); skip >= 0 { ++ j += skip + len(closetag) ++ } else { ++ break ++ } ++ ++ // see if it is the only thing on the line ++ if skip := p.isEmpty(data[j:]); skip > 0 { ++ // see if it is followed by a blank line/eof ++ j += skip ++ if j >= len(data) { ++ found = true ++ i = j ++ } else { ++ if skip := p.isEmpty(data[j:]); skip > 0 { ++ j += skip ++ found = true ++ i = j ++ } ++ } ++ } ++ } ++ */ ++ ++ // if not found, try a second pass looking for indented match ++ // but not if tag is "ins" or "del" (following original Markdown.pl) ++ if !found && curtag != "ins" && curtag != "del" { ++ i = 1 ++ for i < len(data) { ++ i++ ++ for i < len(data) && !(data[i-1] == '<' && data[i] == '/') { ++ i++ ++ } ++ ++ if i+2+len(curtag) >= len(data) { ++ break ++ } ++ ++ j = p.htmlFindEnd(curtag, data[i-1:]) ++ ++ if j > 0 { ++ i += j - 1 ++ found = true ++ break ++ } ++ } ++ } ++ ++ if !found { ++ return 0 ++ } ++ ++ // the end of the block has been found ++ if doRender { ++ // trim newlines ++ end := i ++ for end > 0 && data[end-1] == '\n' { ++ end-- ++ } ++ finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) ++ } ++ ++ return i ++} ++ ++func finalizeHTMLBlock(block *Node) { ++ block.Literal = block.content ++ block.content = nil ++} ++ ++// HTML comment, lax form ++func (p *Markdown) htmlComment(data []byte, doRender bool) int { ++ i := p.inlineHTMLComment(data) ++ // needs to end with a blank line ++ if j := p.isEmpty(data[i:]); j > 0 { ++ size := i + j ++ if doRender { ++ // trim trailing newlines ++ end := size ++ for end > 0 && data[end-1] == '\n' { ++ end-- ++ } ++ block := p.addBlock(HTMLBlock, data[:end]) ++ finalizeHTMLBlock(block) ++ } ++ return size ++ } ++ return 0 ++} ++ ++// HR, which is the only self-closing block tag considered ++func (p *Markdown) htmlHr(data []byte, doRender bool) int { ++ if len(data) < 4 { ++ return 0 ++ } ++ if data[0] != '<' || (data[1] != 'h' && data[1] != 'H') || (data[2] != 'r' && data[2] != 'R') { ++ return 0 ++ } ++ if data[3] != ' ' && data[3] != '/' && data[3] != '>' { ++ // not an
tag after all; at least not a valid one ++ return 0 ++ } ++ i := 3 ++ for i < len(data) && data[i] != '>' && data[i] != '\n' { ++ i++ ++ } ++ if i < len(data) && data[i] == '>' { ++ i++ ++ if j := p.isEmpty(data[i:]); j > 0 { ++ size := i + j ++ if doRender { ++ // trim newlines ++ end := size ++ for end > 0 && data[end-1] == '\n' { ++ end-- ++ } ++ finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) ++ } ++ return size ++ } ++ } ++ return 0 ++} ++ ++func (p *Markdown) htmlFindTag(data []byte) (string, bool) { ++ i := 0 ++ for i < len(data) && isalnum(data[i]) { ++ i++ ++ } ++ key := string(data[:i]) ++ if _, ok := blockTags[key]; ok { ++ return key, true ++ } ++ return "", false ++} ++ ++func (p *Markdown) htmlFindEnd(tag string, data []byte) int { ++ // assume data[0] == '<' && data[1] == '/' already tested ++ if tag == "hr" { ++ return 2 ++ } ++ // check if tag is a match ++ closetag := []byte("") ++ if !bytes.HasPrefix(data, closetag) { ++ return 0 ++ } ++ i := len(closetag) ++ ++ // check that the rest of the line is blank ++ skip := 0 ++ if skip = p.isEmpty(data[i:]); skip == 0 { ++ return 0 ++ } ++ i += skip ++ skip = 0 ++ ++ if i >= len(data) { ++ return i ++ } ++ ++ if p.extensions&LaxHTMLBlocks != 0 { ++ return i ++ } ++ if skip = p.isEmpty(data[i:]); skip == 0 { ++ // following line must be blank ++ return 0 ++ } ++ ++ return i + skip ++} ++ ++func (*Markdown) isEmpty(data []byte) int { ++ // it is okay to call isEmpty on an empty buffer ++ if len(data) == 0 { ++ return 0 ++ } ++ ++ var i int ++ for i = 0; i < len(data) && data[i] != '\n'; i++ { ++ if data[i] != ' ' && data[i] != '\t' { ++ return 0 ++ } ++ } ++ if i < len(data) && data[i] == '\n' { ++ i++ ++ } ++ return i ++} ++ ++func (*Markdown) isHRule(data []byte) bool { ++ i := 0 ++ ++ // skip up to three spaces ++ for i < 3 && data[i] == ' ' { ++ i++ ++ } ++ ++ // look at the hrule char ++ if data[i] != '*' && data[i] != '-' && data[i] != '_' { ++ return false ++ } ++ c := data[i] ++ ++ // the whole line must be the char or whitespace ++ n := 0 ++ for i < len(data) && data[i] != '\n' { ++ switch { ++ case data[i] == c: ++ n++ ++ case data[i] != ' ': ++ return false ++ } ++ i++ ++ } ++ ++ return n >= 3 ++} ++ ++// isFenceLine checks if there's a fence line (e.g., ``` or ``` go) at the beginning of data, ++// and returns the end index if so, or 0 otherwise. It also returns the marker found. ++// If info is not nil, it gets set to the syntax specified in the fence line. ++func isFenceLine(data []byte, info *string, oldmarker string) (end int, marker string) { ++ i, size := 0, 0 ++ ++ // skip up to three spaces ++ for i < len(data) && i < 3 && data[i] == ' ' { ++ i++ ++ } ++ ++ // check for the marker characters: ~ or ` ++ if i >= len(data) { ++ return 0, "" ++ } ++ if data[i] != '~' && data[i] != '`' { ++ return 0, "" ++ } ++ ++ c := data[i] ++ ++ // the whole line must be the same char or whitespace ++ for i < len(data) && data[i] == c { ++ size++ ++ i++ ++ } ++ ++ // the marker char must occur at least 3 times ++ if size < 3 { ++ return 0, "" ++ } ++ marker = string(data[i-size : i]) ++ ++ // if this is the end marker, it must match the beginning marker ++ if oldmarker != "" && marker != oldmarker { ++ return 0, "" ++ } ++ ++ // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here ++ // into one, always get the info string, and discard it if the caller doesn't care. ++ if info != nil { ++ infoLength := 0 ++ i = skipChar(data, i, ' ') ++ ++ if i >= len(data) { ++ if i == len(data) { ++ return i, marker ++ } ++ return 0, "" ++ } ++ ++ infoStart := i ++ ++ if data[i] == '{' { ++ i++ ++ infoStart++ ++ ++ for i < len(data) && data[i] != '}' && data[i] != '\n' { ++ infoLength++ ++ i++ ++ } ++ ++ if i >= len(data) || data[i] != '}' { ++ return 0, "" ++ } ++ ++ // strip all whitespace at the beginning and the end ++ // of the {} block ++ for infoLength > 0 && isspace(data[infoStart]) { ++ infoStart++ ++ infoLength-- ++ } ++ ++ for infoLength > 0 && isspace(data[infoStart+infoLength-1]) { ++ infoLength-- ++ } ++ i++ ++ i = skipChar(data, i, ' ') ++ } else { ++ for i < len(data) && !isverticalspace(data[i]) { ++ infoLength++ ++ i++ ++ } ++ } ++ ++ *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength])) ++ } ++ ++ if i == len(data) { ++ return i, marker ++ } ++ if i > len(data) || data[i] != '\n' { ++ return 0, "" ++ } ++ return i + 1, marker // Take newline into account. ++} ++ ++// fencedCodeBlock returns the end index if data contains a fenced code block at the beginning, ++// or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects. ++// If doRender is true, a final newline is mandatory to recognize the fenced code block. ++func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { ++ var info string ++ beg, marker := isFenceLine(data, &info, "") ++ if beg == 0 || beg >= len(data) { ++ return 0 ++ } ++ fenceLength := beg - 1 ++ ++ var work bytes.Buffer ++ work.Write([]byte(info)) ++ work.WriteByte('\n') ++ ++ for { ++ // safe to assume beg < len(data) ++ ++ // check for the end of the code block ++ fenceEnd, _ := isFenceLine(data[beg:], nil, marker) ++ if fenceEnd != 0 { ++ beg += fenceEnd ++ break ++ } ++ ++ // copy the current line ++ end := skipUntilChar(data, beg, '\n') + 1 ++ ++ // did we reach the end of the buffer without a closing marker? ++ if end >= len(data) { ++ return 0 ++ } ++ ++ // verbatim copy to the working buffer ++ if doRender { ++ work.Write(data[beg:end]) ++ } ++ beg = end ++ } ++ ++ if doRender { ++ block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer ++ block.IsFenced = true ++ block.FenceLength = fenceLength ++ finalizeCodeBlock(block) ++ } ++ ++ return beg ++} ++ ++func unescapeChar(str []byte) []byte { ++ if str[0] == '\\' { ++ return []byte{str[1]} ++ } ++ return []byte(html.UnescapeString(string(str))) ++} ++ ++func unescapeString(str []byte) []byte { ++ if reBackslashOrAmp.Match(str) { ++ return reEntityOrEscapedChar.ReplaceAllFunc(str, unescapeChar) ++ } ++ return str ++} ++ ++func finalizeCodeBlock(block *Node) { ++ if block.IsFenced { ++ newlinePos := bytes.IndexByte(block.content, '\n') ++ firstLine := block.content[:newlinePos] ++ rest := block.content[newlinePos+1:] ++ block.Info = unescapeString(bytes.Trim(firstLine, "\n")) ++ block.Literal = rest ++ } else { ++ block.Literal = block.content ++ } ++ block.content = nil ++} ++ ++func (p *Markdown) table(data []byte) int { ++ table := p.addBlock(Table, nil) ++ i, columns := p.tableHeader(data) ++ if i == 0 { ++ p.tip = table.Parent ++ table.Unlink() ++ return 0 ++ } ++ ++ p.addBlock(TableBody, nil) ++ ++ for i < len(data) { ++ pipes, rowStart := 0, i ++ for ; i < len(data) && data[i] != '\n'; i++ { ++ if data[i] == '|' { ++ pipes++ ++ } ++ } ++ ++ if pipes == 0 { ++ i = rowStart ++ break ++ } ++ ++ // include the newline in data sent to tableRow ++ if i < len(data) && data[i] == '\n' { ++ i++ ++ } ++ p.tableRow(data[rowStart:i], columns, false) ++ } ++ ++ return i ++} ++ ++// check if the specified position is preceded by an odd number of backslashes ++func isBackslashEscaped(data []byte, i int) bool { ++ backslashes := 0 ++ for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' { ++ backslashes++ ++ } ++ return backslashes&1 == 1 ++} ++ ++func (p *Markdown) tableHeader(data []byte) (size int, columns []CellAlignFlags) { ++ i := 0 ++ colCount := 1 ++ for i = 0; i < len(data) && data[i] != '\n'; i++ { ++ if data[i] == '|' && !isBackslashEscaped(data, i) { ++ colCount++ ++ } ++ } ++ ++ // doesn't look like a table header ++ if colCount == 1 { ++ return ++ } ++ ++ // include the newline in the data sent to tableRow ++ j := i ++ if j < len(data) && data[j] == '\n' { ++ j++ ++ } ++ header := data[:j] ++ ++ // column count ignores pipes at beginning or end of line ++ if data[0] == '|' { ++ colCount-- ++ } ++ if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) { ++ colCount-- ++ } ++ ++ columns = make([]CellAlignFlags, colCount) ++ ++ // move on to the header underline ++ i++ ++ if i >= len(data) { ++ return ++ } ++ ++ if data[i] == '|' && !isBackslashEscaped(data, i) { ++ i++ ++ } ++ i = skipChar(data, i, ' ') ++ ++ // each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3 ++ // and trailing | optional on last column ++ col := 0 ++ for i < len(data) && data[i] != '\n' { ++ dashes := 0 ++ ++ if data[i] == ':' { ++ i++ ++ columns[col] |= TableAlignmentLeft ++ dashes++ ++ } ++ for i < len(data) && data[i] == '-' { ++ i++ ++ dashes++ ++ } ++ if i < len(data) && data[i] == ':' { ++ i++ ++ columns[col] |= TableAlignmentRight ++ dashes++ ++ } ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ if i == len(data) { ++ return ++ } ++ // end of column test is messy ++ switch { ++ case dashes < 3: ++ // not a valid column ++ return ++ ++ case data[i] == '|' && !isBackslashEscaped(data, i): ++ // marker found, now skip past trailing whitespace ++ col++ ++ i++ ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ // trailing junk found after last column ++ if col >= colCount && i < len(data) && data[i] != '\n' { ++ return ++ } ++ ++ case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount: ++ // something else found where marker was required ++ return ++ ++ case data[i] == '\n': ++ // marker is optional for the last column ++ col++ ++ ++ default: ++ // trailing junk found after last column ++ return ++ } ++ } ++ if col != colCount { ++ return ++ } ++ ++ p.addBlock(TableHead, nil) ++ p.tableRow(header, columns, true) ++ size = i ++ if size < len(data) && data[size] == '\n' { ++ size++ ++ } ++ return ++} ++ ++func (p *Markdown) tableRow(data []byte, columns []CellAlignFlags, header bool) { ++ p.addBlock(TableRow, nil) ++ i, col := 0, 0 ++ ++ if data[i] == '|' && !isBackslashEscaped(data, i) { ++ i++ ++ } ++ ++ for col = 0; col < len(columns) && i < len(data); col++ { ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ cellStart := i ++ ++ for i < len(data) && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' { ++ i++ ++ } ++ ++ cellEnd := i ++ ++ // skip the end-of-cell marker, possibly taking us past end of buffer ++ i++ ++ ++ for cellEnd > cellStart && cellEnd-1 < len(data) && data[cellEnd-1] == ' ' { ++ cellEnd-- ++ } ++ ++ cell := p.addBlock(TableCell, data[cellStart:cellEnd]) ++ cell.IsHeader = header ++ cell.Align = columns[col] ++ } ++ ++ // pad it out with empty columns to get the right number ++ for ; col < len(columns); col++ { ++ cell := p.addBlock(TableCell, nil) ++ cell.IsHeader = header ++ cell.Align = columns[col] ++ } ++ ++ // silently ignore rows with too many cells ++} ++ ++// returns blockquote prefix length ++func (p *Markdown) quotePrefix(data []byte) int { ++ i := 0 ++ for i < 3 && i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ if i < len(data) && data[i] == '>' { ++ if i+1 < len(data) && data[i+1] == ' ' { ++ return i + 2 ++ } ++ return i + 1 ++ } ++ return 0 ++} ++ ++// blockquote ends with at least one blank line ++// followed by something without a blockquote prefix ++func (p *Markdown) terminateBlockquote(data []byte, beg, end int) bool { ++ if p.isEmpty(data[beg:]) <= 0 { ++ return false ++ } ++ if end >= len(data) { ++ return true ++ } ++ return p.quotePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0 ++} ++ ++// parse a blockquote fragment ++func (p *Markdown) quote(data []byte) int { ++ block := p.addBlock(BlockQuote, nil) ++ var raw bytes.Buffer ++ beg, end := 0, 0 ++ for beg < len(data) { ++ end = beg ++ // Step over whole lines, collecting them. While doing that, check for ++ // fenced code and if one's found, incorporate it altogether, ++ // irregardless of any contents inside it ++ for end < len(data) && data[end] != '\n' { ++ if p.extensions&FencedCode != 0 { ++ if i := p.fencedCodeBlock(data[end:], false); i > 0 { ++ // -1 to compensate for the extra end++ after the loop: ++ end += i - 1 ++ break ++ } ++ } ++ end++ ++ } ++ if end < len(data) && data[end] == '\n' { ++ end++ ++ } ++ if pre := p.quotePrefix(data[beg:]); pre > 0 { ++ // skip the prefix ++ beg += pre ++ } else if p.terminateBlockquote(data, beg, end) { ++ break ++ } ++ // this line is part of the blockquote ++ raw.Write(data[beg:end]) ++ beg = end ++ } ++ p.block(raw.Bytes()) ++ p.finalize(block) ++ return end ++} ++ ++// returns prefix length for block code ++func (p *Markdown) codePrefix(data []byte) int { ++ if len(data) >= 1 && data[0] == '\t' { ++ return 1 ++ } ++ if len(data) >= 4 && data[0] == ' ' && data[1] == ' ' && data[2] == ' ' && data[3] == ' ' { ++ return 4 ++ } ++ return 0 ++} ++ ++func (p *Markdown) code(data []byte) int { ++ var work bytes.Buffer ++ ++ i := 0 ++ for i < len(data) { ++ beg := i ++ for i < len(data) && data[i] != '\n' { ++ i++ ++ } ++ if i < len(data) && data[i] == '\n' { ++ i++ ++ } ++ ++ blankline := p.isEmpty(data[beg:i]) > 0 ++ if pre := p.codePrefix(data[beg:i]); pre > 0 { ++ beg += pre ++ } else if !blankline { ++ // non-empty, non-prefixed line breaks the pre ++ i = beg ++ break ++ } ++ ++ // verbatim copy to the working buffer ++ if blankline { ++ work.WriteByte('\n') ++ } else { ++ work.Write(data[beg:i]) ++ } ++ } ++ ++ // trim all the \n off the end of work ++ workbytes := work.Bytes() ++ eol := len(workbytes) ++ for eol > 0 && workbytes[eol-1] == '\n' { ++ eol-- ++ } ++ if eol != len(workbytes) { ++ work.Truncate(eol) ++ } ++ ++ work.WriteByte('\n') ++ ++ block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer ++ block.IsFenced = false ++ finalizeCodeBlock(block) ++ ++ return i ++} ++ ++// returns unordered list item prefix ++func (p *Markdown) uliPrefix(data []byte) int { ++ i := 0 ++ // start with up to 3 spaces ++ for i < len(data) && i < 3 && data[i] == ' ' { ++ i++ ++ } ++ if i >= len(data)-1 { ++ return 0 ++ } ++ // need one of {'*', '+', '-'} followed by a space or a tab ++ if (data[i] != '*' && data[i] != '+' && data[i] != '-') || ++ (data[i+1] != ' ' && data[i+1] != '\t') { ++ return 0 ++ } ++ return i + 2 ++} ++ ++// returns ordered list item prefix ++func (p *Markdown) oliPrefix(data []byte) int { ++ i := 0 ++ ++ // start with up to 3 spaces ++ for i < 3 && i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ // count the digits ++ start := i ++ for i < len(data) && data[i] >= '0' && data[i] <= '9' { ++ i++ ++ } ++ if start == i || i >= len(data)-1 { ++ return 0 ++ } ++ ++ // we need >= 1 digits followed by a dot and a space or a tab ++ if data[i] != '.' || !(data[i+1] == ' ' || data[i+1] == '\t') { ++ return 0 ++ } ++ return i + 2 ++} ++ ++// returns definition list item prefix ++func (p *Markdown) dliPrefix(data []byte) int { ++ if len(data) < 2 { ++ return 0 ++ } ++ i := 0 ++ // need a ':' followed by a space or a tab ++ if data[i] != ':' || !(data[i+1] == ' ' || data[i+1] == '\t') { ++ return 0 ++ } ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ return i + 2 ++} ++ ++// parse ordered or unordered list block ++func (p *Markdown) list(data []byte, flags ListType) int { ++ i := 0 ++ flags |= ListItemBeginningOfList ++ block := p.addBlock(List, nil) ++ block.ListFlags = flags ++ block.Tight = true ++ ++ for i < len(data) { ++ skip := p.listItem(data[i:], &flags) ++ if flags&ListItemContainsBlock != 0 { ++ block.ListData.Tight = false ++ } ++ i += skip ++ if skip == 0 || flags&ListItemEndOfList != 0 { ++ break ++ } ++ flags &= ^ListItemBeginningOfList ++ } ++ ++ above := block.Parent ++ finalizeList(block) ++ p.tip = above ++ return i ++} ++ ++// Returns true if the list item is not the same type as its parent list ++func (p *Markdown) listTypeChanged(data []byte, flags *ListType) bool { ++ if p.dliPrefix(data) > 0 && *flags&ListTypeDefinition == 0 { ++ return true ++ } else if p.oliPrefix(data) > 0 && *flags&ListTypeOrdered == 0 { ++ return true ++ } else if p.uliPrefix(data) > 0 && (*flags&ListTypeOrdered != 0 || *flags&ListTypeDefinition != 0) { ++ return true ++ } ++ return false ++} ++ ++// Returns true if block ends with a blank line, descending if needed ++// into lists and sublists. ++func endsWithBlankLine(block *Node) bool { ++ // TODO: figure this out. Always false now. ++ for block != nil { ++ //if block.lastLineBlank { ++ //return true ++ //} ++ t := block.Type ++ if t == List || t == Item { ++ block = block.LastChild ++ } else { ++ break ++ } ++ } ++ return false ++} ++ ++func finalizeList(block *Node) { ++ block.open = false ++ item := block.FirstChild ++ for item != nil { ++ // check for non-final list item ending with blank line: ++ if endsWithBlankLine(item) && item.Next != nil { ++ block.ListData.Tight = false ++ break ++ } ++ // recurse into children of list item, to see if there are spaces ++ // between any of them: ++ subItem := item.FirstChild ++ for subItem != nil { ++ if endsWithBlankLine(subItem) && (item.Next != nil || subItem.Next != nil) { ++ block.ListData.Tight = false ++ break ++ } ++ subItem = subItem.Next ++ } ++ item = item.Next ++ } ++} ++ ++// Parse a single list item. ++// Assumes initial prefix is already removed if this is a sublist. ++func (p *Markdown) listItem(data []byte, flags *ListType) int { ++ // keep track of the indentation of the first line ++ itemIndent := 0 ++ if data[0] == '\t' { ++ itemIndent += 4 ++ } else { ++ for itemIndent < 3 && data[itemIndent] == ' ' { ++ itemIndent++ ++ } ++ } ++ ++ var bulletChar byte = '*' ++ i := p.uliPrefix(data) ++ if i == 0 { ++ i = p.oliPrefix(data) ++ } else { ++ bulletChar = data[i-2] ++ } ++ if i == 0 { ++ i = p.dliPrefix(data) ++ // reset definition term flag ++ if i > 0 { ++ *flags &= ^ListTypeTerm ++ } ++ } ++ if i == 0 { ++ // if in definition list, set term flag and continue ++ if *flags&ListTypeDefinition != 0 { ++ *flags |= ListTypeTerm ++ } else { ++ return 0 ++ } ++ } ++ ++ // skip leading whitespace on first line ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ // find the end of the line ++ line := i ++ for i > 0 && i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // get working buffer ++ var raw bytes.Buffer ++ ++ // put the first line into the working buffer ++ raw.Write(data[line:i]) ++ line = i ++ ++ // process the following lines ++ containsBlankLine := false ++ sublist := 0 ++ codeBlockMarker := "" ++ ++gatherlines: ++ for line < len(data) { ++ i++ ++ ++ // find the end of this line ++ for i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // if it is an empty line, guess that it is part of this item ++ // and move on to the next line ++ if p.isEmpty(data[line:i]) > 0 { ++ containsBlankLine = true ++ line = i ++ continue ++ } ++ ++ // calculate the indentation ++ indent := 0 ++ indentIndex := 0 ++ if data[line] == '\t' { ++ indentIndex++ ++ indent += 4 ++ } else { ++ for indent < 4 && line+indent < i && data[line+indent] == ' ' { ++ indent++ ++ indentIndex++ ++ } ++ } ++ ++ chunk := data[line+indentIndex : i] ++ ++ if p.extensions&FencedCode != 0 { ++ // determine if in or out of codeblock ++ // if in codeblock, ignore normal list processing ++ _, marker := isFenceLine(chunk, nil, codeBlockMarker) ++ if marker != "" { ++ if codeBlockMarker == "" { ++ // start of codeblock ++ codeBlockMarker = marker ++ } else { ++ // end of codeblock. ++ codeBlockMarker = "" ++ } ++ } ++ // we are in a codeblock, write line, and continue ++ if codeBlockMarker != "" || marker != "" { ++ raw.Write(data[line+indentIndex : i]) ++ line = i ++ continue gatherlines ++ } ++ } ++ ++ // evaluate how this line fits in ++ switch { ++ // is this a nested list item? ++ case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) || ++ p.oliPrefix(chunk) > 0 || ++ p.dliPrefix(chunk) > 0: ++ ++ // to be a nested list, it must be indented more ++ // if not, it is either a different kind of list ++ // or the next item in the same list ++ if indent <= itemIndent { ++ if p.listTypeChanged(chunk, flags) { ++ *flags |= ListItemEndOfList ++ } else if containsBlankLine { ++ *flags |= ListItemContainsBlock ++ } ++ ++ break gatherlines ++ } ++ ++ if containsBlankLine { ++ *flags |= ListItemContainsBlock ++ } ++ ++ // is this the first item in the nested list? ++ if sublist == 0 { ++ sublist = raw.Len() ++ } ++ ++ // is this a nested prefix heading? ++ case p.isPrefixHeading(chunk): ++ // if the heading is not indented, it is not nested in the list ++ // and thus ends the list ++ if containsBlankLine && indent < 4 { ++ *flags |= ListItemEndOfList ++ break gatherlines ++ } ++ *flags |= ListItemContainsBlock ++ ++ // anything following an empty line is only part ++ // of this item if it is indented 4 spaces ++ // (regardless of the indentation of the beginning of the item) ++ case containsBlankLine && indent < 4: ++ if *flags&ListTypeDefinition != 0 && i < len(data)-1 { ++ // is the next item still a part of this list? ++ next := i ++ for next < len(data) && data[next] != '\n' { ++ next++ ++ } ++ for next < len(data)-1 && data[next] == '\n' { ++ next++ ++ } ++ if i < len(data)-1 && data[i] != ':' && data[next] != ':' { ++ *flags |= ListItemEndOfList ++ } ++ } else { ++ *flags |= ListItemEndOfList ++ } ++ break gatherlines ++ ++ // a blank line means this should be parsed as a block ++ case containsBlankLine: ++ raw.WriteByte('\n') ++ *flags |= ListItemContainsBlock ++ } ++ ++ // if this line was preceded by one or more blanks, ++ // re-introduce the blank into the buffer ++ if containsBlankLine { ++ containsBlankLine = false ++ raw.WriteByte('\n') ++ } ++ ++ // add the line into the working buffer without prefix ++ raw.Write(data[line+indentIndex : i]) ++ ++ line = i ++ } ++ ++ rawBytes := raw.Bytes() ++ ++ block := p.addBlock(Item, nil) ++ block.ListFlags = *flags ++ block.Tight = false ++ block.BulletChar = bulletChar ++ block.Delimiter = '.' // Only '.' is possible in Markdown, but ')' will also be possible in CommonMark ++ ++ // render the contents of the list item ++ if *flags&ListItemContainsBlock != 0 && *flags&ListTypeTerm == 0 { ++ // intermediate render of block item, except for definition term ++ if sublist > 0 { ++ p.block(rawBytes[:sublist]) ++ p.block(rawBytes[sublist:]) ++ } else { ++ p.block(rawBytes) ++ } ++ } else { ++ // intermediate render of inline item ++ if sublist > 0 { ++ child := p.addChild(Paragraph, 0) ++ child.content = rawBytes[:sublist] ++ p.block(rawBytes[sublist:]) ++ } else { ++ child := p.addChild(Paragraph, 0) ++ child.content = rawBytes ++ } ++ } ++ return line ++} ++ ++// render a single paragraph that has already been parsed out ++func (p *Markdown) renderParagraph(data []byte) { ++ if len(data) == 0 { ++ return ++ } ++ ++ // trim leading spaces ++ beg := 0 ++ for data[beg] == ' ' { ++ beg++ ++ } ++ ++ end := len(data) ++ // trim trailing newline ++ if data[len(data)-1] == '\n' { ++ end-- ++ } ++ ++ // trim trailing spaces ++ for end > beg && data[end-1] == ' ' { ++ end-- ++ } ++ ++ p.addBlock(Paragraph, data[beg:end]) ++} ++ ++func (p *Markdown) paragraph(data []byte) int { ++ // prev: index of 1st char of previous line ++ // line: index of 1st char of current line ++ // i: index of cursor/end of current line ++ var prev, line, i int ++ tabSize := TabSizeDefault ++ if p.extensions&TabSizeEight != 0 { ++ tabSize = TabSizeDouble ++ } ++ // keep going until we find something to mark the end of the paragraph ++ for i < len(data) { ++ // mark the beginning of the current line ++ prev = line ++ current := data[i:] ++ line = i ++ ++ // did we find a reference or a footnote? If so, end a paragraph ++ // preceding it and report that we have consumed up to the end of that ++ // reference: ++ if refEnd := isReference(p, current, tabSize); refEnd > 0 { ++ p.renderParagraph(data[:i]) ++ return i + refEnd ++ } ++ ++ // did we find a blank line marking the end of the paragraph? ++ if n := p.isEmpty(current); n > 0 { ++ // did this blank line followed by a definition list item? ++ if p.extensions&DefinitionLists != 0 { ++ if i < len(data)-1 && data[i+1] == ':' { ++ return p.list(data[prev:], ListTypeDefinition) ++ } ++ } ++ ++ p.renderParagraph(data[:i]) ++ return i + n ++ } ++ ++ // an underline under some text marks a heading, so our paragraph ended on prev line ++ if i > 0 { ++ if level := p.isUnderlinedHeading(current); level > 0 { ++ // render the paragraph ++ p.renderParagraph(data[:prev]) ++ ++ // ignore leading and trailing whitespace ++ eol := i - 1 ++ for prev < eol && data[prev] == ' ' { ++ prev++ ++ } ++ for eol > prev && data[eol-1] == ' ' { ++ eol-- ++ } ++ ++ id := "" ++ if p.extensions&AutoHeadingIDs != 0 { ++ id = SanitizedAnchorName(string(data[prev:eol])) ++ } ++ ++ block := p.addBlock(Heading, data[prev:eol]) ++ block.Level = level ++ block.HeadingID = id ++ ++ // find the end of the underline ++ for i < len(data) && data[i] != '\n' { ++ i++ ++ } ++ return i ++ } ++ } ++ ++ // if the next line starts a block of HTML, then the paragraph ends here ++ if p.extensions&LaxHTMLBlocks != 0 { ++ if data[i] == '<' && p.html(current, false) > 0 { ++ // rewind to before the HTML block ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ } ++ ++ // if there's a prefixed heading or a horizontal rule after this, paragraph is over ++ if p.isPrefixHeading(current) || p.isHRule(current) { ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ ++ // if there's a fenced code block, paragraph is over ++ if p.extensions&FencedCode != 0 { ++ if p.fencedCodeBlock(current, false) > 0 { ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ } ++ ++ // if there's a definition list item, prev line is a definition term ++ if p.extensions&DefinitionLists != 0 { ++ if p.dliPrefix(current) != 0 { ++ ret := p.list(data[prev:], ListTypeDefinition) ++ return ret ++ } ++ } ++ ++ // if there's a list after this, paragraph is over ++ if p.extensions&NoEmptyLineBeforeBlock != 0 { ++ if p.uliPrefix(current) != 0 || ++ p.oliPrefix(current) != 0 || ++ p.quotePrefix(current) != 0 || ++ p.codePrefix(current) != 0 { ++ p.renderParagraph(data[:i]) ++ return i ++ } ++ } ++ ++ // otherwise, scan to the beginning of the next line ++ nl := bytes.IndexByte(data[i:], '\n') ++ if nl >= 0 { ++ i += nl + 1 ++ } else { ++ i += len(data[i:]) ++ } ++ } ++ ++ p.renderParagraph(data[:i]) ++ return i ++} ++ ++func skipChar(data []byte, start int, char byte) int { ++ i := start ++ for i < len(data) && data[i] == char { ++ i++ ++ } ++ return i ++} ++ ++func skipUntilChar(text []byte, start int, char byte) int { ++ i := start ++ for i < len(text) && text[i] != char { ++ i++ ++ } ++ return i ++} ++ ++// SanitizedAnchorName returns a sanitized anchor name for the given text. ++// ++// It implements the algorithm specified in the package comment. ++func SanitizedAnchorName(text string) string { ++ var anchorName []rune ++ futureDash := false ++ for _, r := range text { ++ switch { ++ case unicode.IsLetter(r) || unicode.IsNumber(r): ++ if futureDash && len(anchorName) > 0 { ++ anchorName = append(anchorName, '-') ++ } ++ futureDash = false ++ anchorName = append(anchorName, unicode.ToLower(r)) ++ default: ++ futureDash = true ++ } ++ } ++ return string(anchorName) ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/doc.go b/vendor/github.com/russross/blackfriday/v2/doc.go +new file mode 100644 +index 000000000000..57ff152a0568 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/doc.go +@@ -0,0 +1,46 @@ ++// Package blackfriday is a markdown processor. ++// ++// It translates plain text with simple formatting rules into an AST, which can ++// then be further processed to HTML (provided by Blackfriday itself) or other ++// formats (provided by the community). ++// ++// The simplest way to invoke Blackfriday is to call the Run function. It will ++// take a text input and produce a text output in HTML (or other format). ++// ++// A slightly more sophisticated way to use Blackfriday is to create a Markdown ++// processor and to call Parse, which returns a syntax tree for the input ++// document. You can leverage Blackfriday's parsing for content extraction from ++// markdown documents. You can assign a custom renderer and set various options ++// to the Markdown processor. ++// ++// If you're interested in calling Blackfriday from command line, see ++// https://github.com/russross/blackfriday-tool. ++// ++// Sanitized Anchor Names ++// ++// Blackfriday includes an algorithm for creating sanitized anchor names ++// corresponding to a given input text. This algorithm is used to create ++// anchors for headings when AutoHeadingIDs extension is enabled. The ++// algorithm is specified below, so that other packages can create ++// compatible anchor names and links to those anchors. ++// ++// The algorithm iterates over the input text, interpreted as UTF-8, ++// one Unicode code point (rune) at a time. All runes that are letters (category L) ++// or numbers (category N) are considered valid characters. They are mapped to ++// lower case, and included in the output. All other runes are considered ++// invalid characters. Invalid characters that precede the first valid character, ++// as well as invalid character that follow the last valid character ++// are dropped completely. All other sequences of invalid characters ++// between two valid characters are replaced with a single dash character '-'. ++// ++// SanitizedAnchorName exposes this functionality, and can be used to ++// create compatible links to the anchor names generated by blackfriday. ++// This algorithm is also implemented in a small standalone package at ++// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients ++// that want a small package and don't need full functionality of blackfriday. ++package blackfriday ++ ++// NOTE: Keep Sanitized Anchor Name algorithm in sync with package ++// github.com/shurcooL/sanitized_anchor_name. ++// Otherwise, users of sanitized_anchor_name will get anchor names ++// that are incompatible with those generated by blackfriday. +diff --git a/vendor/github.com/russross/blackfriday/v2/entities.go b/vendor/github.com/russross/blackfriday/v2/entities.go +new file mode 100644 +index 000000000000..a2c3edb691c8 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/entities.go +@@ -0,0 +1,2236 @@ ++package blackfriday ++ ++// Extracted from https://html.spec.whatwg.org/multipage/entities.json ++var entities = map[string]bool{ ++ "Æ": true, ++ "Æ": true, ++ "&": true, ++ "&": true, ++ "Á": true, ++ "Á": true, ++ "Ă": true, ++ "Â": true, ++ "Â": true, ++ "А": true, ++ "𝔄": true, ++ "À": true, ++ "À": true, ++ "Α": true, ++ "Ā": true, ++ "⩓": true, ++ "Ą": true, ++ "𝔸": true, ++ "⁡": true, ++ "Å": true, ++ "Å": true, ++ "𝒜": true, ++ "≔": true, ++ "Ã": true, ++ "Ã": true, ++ "Ä": true, ++ "Ä": true, ++ "∖": true, ++ "⫧": true, ++ "⌆": true, ++ "Б": true, ++ "∵": true, ++ "ℬ": true, ++ "Β": true, ++ "𝔅": true, ++ "𝔹": true, ++ "˘": true, ++ "ℬ": true, ++ "≎": true, ++ "Ч": true, ++ "©": true, ++ "©": true, ++ "Ć": true, ++ "⋒": true, ++ "ⅅ": true, ++ "ℭ": true, ++ "Č": true, ++ "Ç": true, ++ "Ç": true, ++ "Ĉ": true, ++ "∰": true, ++ "Ċ": true, ++ "¸": true, ++ "·": true, ++ "ℭ": true, ++ "Χ": true, ++ "⊙": true, ++ "⊖": true, ++ "⊕": true, ++ "⊗": true, ++ "∲": true, ++ "”": true, ++ "’": true, ++ "∷": true, ++ "⩴": true, ++ "≡": true, ++ "∯": true, ++ "∮": true, ++ "ℂ": true, ++ "∐": true, ++ "∳": true, ++ "⨯": true, ++ "𝒞": true, ++ "⋓": true, ++ "≍": true, ++ "ⅅ": true, ++ "⤑": true, ++ "Ђ": true, ++ "Ѕ": true, ++ "Џ": true, ++ "‡": true, ++ "↡": true, ++ "⫤": true, ++ "Ď": true, ++ "Д": true, ++ "∇": true, ++ "Δ": true, ++ "𝔇": true, ++ "´": true, ++ "˙": true, ++ "˝": true, ++ "`": true, ++ "˜": true, ++ "⋄": true, ++ "ⅆ": true, ++ "𝔻": true, ++ "¨": true, ++ "⃜": true, ++ "≐": true, ++ "∯": true, ++ "¨": true, ++ "⇓": true, ++ "⇐": true, ++ "⇔": true, ++ "⫤": true, ++ "⟸": true, ++ "⟺": true, ++ "⟹": true, ++ "⇒": true, ++ "⊨": true, ++ "⇑": true, ++ "⇕": true, ++ "∥": true, ++ "↓": true, ++ "⤓": true, ++ "⇵": true, ++ "̑": true, ++ "⥐": true, ++ "⥞": true, ++ "↽": true, ++ "⥖": true, ++ "⥟": true, ++ "⇁": true, ++ "⥗": true, ++ "⊤": true, ++ "↧": true, ++ "⇓": true, ++ "𝒟": true, ++ "Đ": true, ++ "Ŋ": true, ++ "Ð": true, ++ "Ð": true, ++ "É": true, ++ "É": true, ++ "Ě": true, ++ "Ê": true, ++ "Ê": true, ++ "Э": true, ++ "Ė": true, ++ "𝔈": true, ++ "È": true, ++ "È": true, ++ "∈": true, ++ "Ē": true, ++ "◻": true, ++ "▫": true, ++ "Ę": true, ++ "𝔼": true, ++ "Ε": true, ++ "⩵": true, ++ "≂": true, ++ "⇌": true, ++ "ℰ": true, ++ "⩳": true, ++ "Η": true, ++ "Ë": true, ++ "Ë": true, ++ "∃": true, ++ "ⅇ": true, ++ "Ф": true, ++ "𝔉": true, ++ "◼": true, ++ "▪": true, ++ "𝔽": true, ++ "∀": true, ++ "ℱ": true, ++ "ℱ": true, ++ "Ѓ": true, ++ ">": true, ++ ">": true, ++ "Γ": true, ++ "Ϝ": true, ++ "Ğ": true, ++ "Ģ": true, ++ "Ĝ": true, ++ "Г": true, ++ "Ġ": true, ++ "𝔊": true, ++ "⋙": true, ++ "𝔾": true, ++ "≥": true, ++ "⋛": true, ++ "≧": true, ++ "⪢": true, ++ "≷": true, ++ "⩾": true, ++ "≳": true, ++ "𝒢": true, ++ "≫": true, ++ "Ъ": true, ++ "ˇ": true, ++ "^": true, ++ "Ĥ": true, ++ "ℌ": true, ++ "ℋ": true, ++ "ℍ": true, ++ "─": true, ++ "ℋ": true, ++ "Ħ": true, ++ "≎": true, ++ "≏": true, ++ "Е": true, ++ "IJ": true, ++ "Ё": true, ++ "Í": true, ++ "Í": true, ++ "Î": true, ++ "Î": true, ++ "И": true, ++ "İ": true, ++ "ℑ": true, ++ "Ì": true, ++ "Ì": true, ++ "ℑ": true, ++ "Ī": true, ++ "ⅈ": true, ++ "⇒": true, ++ "∬": true, ++ "∫": true, ++ "⋂": true, ++ "⁣": true, ++ "⁢": true, ++ "Į": true, ++ "𝕀": true, ++ "Ι": true, ++ "ℐ": true, ++ "Ĩ": true, ++ "І": true, ++ "Ï": true, ++ "Ï": true, ++ "Ĵ": true, ++ "Й": true, ++ "𝔍": true, ++ "𝕁": true, ++ "𝒥": true, ++ "Ј": true, ++ "Є": true, ++ "Х": true, ++ "Ќ": true, ++ "Κ": true, ++ "Ķ": true, ++ "К": true, ++ "𝔎": true, ++ "𝕂": true, ++ "𝒦": true, ++ "Љ": true, ++ "<": true, ++ "<": true, ++ "Ĺ": true, ++ "Λ": true, ++ "⟪": true, ++ "ℒ": true, ++ "↞": true, ++ "Ľ": true, ++ "Ļ": true, ++ "Л": true, ++ "⟨": true, ++ "←": true, ++ "⇤": true, ++ "⇆": true, ++ "⌈": true, ++ "⟦": true, ++ "⥡": true, ++ "⇃": true, ++ "⥙": true, ++ "⌊": true, ++ "↔": true, ++ "⥎": true, ++ "⊣": true, ++ "↤": true, ++ "⥚": true, ++ "⊲": true, ++ "⧏": true, ++ "⊴": true, ++ "⥑": true, ++ "⥠": true, ++ "↿": true, ++ "⥘": true, ++ "↼": true, ++ "⥒": true, ++ "⇐": true, ++ "⇔": true, ++ "⋚": true, ++ "≦": true, ++ "≶": true, ++ "⪡": true, ++ "⩽": true, ++ "≲": true, ++ "𝔏": true, ++ "⋘": true, ++ "⇚": true, ++ "Ŀ": true, ++ "⟵": true, ++ "⟷": true, ++ "⟶": true, ++ "⟸": true, ++ "⟺": true, ++ "⟹": true, ++ "𝕃": true, ++ "↙": true, ++ "↘": true, ++ "ℒ": true, ++ "↰": true, ++ "Ł": true, ++ "≪": true, ++ "⤅": true, ++ "М": true, ++ " ": true, ++ "ℳ": true, ++ "𝔐": true, ++ "∓": true, ++ "𝕄": true, ++ "ℳ": true, ++ "Μ": true, ++ "Њ": true, ++ "Ń": true, ++ "Ň": true, ++ "Ņ": true, ++ "Н": true, ++ "​": true, ++ "​": true, ++ "​": true, ++ "​": true, ++ "≫": true, ++ "≪": true, ++ " ": true, ++ "𝔑": true, ++ "⁠": true, ++ " ": true, ++ "ℕ": true, ++ "⫬": true, ++ "≢": true, ++ "≭": true, ++ "∦": true, ++ "∉": true, ++ "≠": true, ++ "≂̸": true, ++ "∄": true, ++ "≯": true, ++ "≱": true, ++ "≧̸": true, ++ "≫̸": true, ++ "≹": true, ++ "⩾̸": true, ++ "≵": true, ++ "≎̸": true, ++ "≏̸": true, ++ "⋪": true, ++ "⧏̸": true, ++ "⋬": true, ++ "≮": true, ++ "≰": true, ++ "≸": true, ++ "≪̸": true, ++ "⩽̸": true, ++ "≴": true, ++ "⪢̸": true, ++ "⪡̸": true, ++ "⊀": true, ++ "⪯̸": true, ++ "⋠": true, ++ "∌": true, ++ "⋫": true, ++ "⧐̸": true, ++ "⋭": true, ++ "⊏̸": true, ++ "⋢": true, ++ "⊐̸": true, ++ "⋣": true, ++ "⊂⃒": true, ++ "⊈": true, ++ "⊁": true, ++ "⪰̸": true, ++ "⋡": true, ++ "≿̸": true, ++ "⊃⃒": true, ++ "⊉": true, ++ "≁": true, ++ "≄": true, ++ "≇": true, ++ "≉": true, ++ "∤": true, ++ "𝒩": true, ++ "Ñ": true, ++ "Ñ": true, ++ "Ν": true, ++ "Œ": true, ++ "Ó": true, ++ "Ó": true, ++ "Ô": true, ++ "Ô": true, ++ "О": true, ++ "Ő": true, ++ "𝔒": true, ++ "Ò": true, ++ "Ò": true, ++ "Ō": true, ++ "Ω": true, ++ "Ο": true, ++ "𝕆": true, ++ "“": true, ++ "‘": true, ++ "⩔": true, ++ "𝒪": true, ++ "Ø": true, ++ "Ø": true, ++ "Õ": true, ++ "Õ": true, ++ "⨷": true, ++ "Ö": true, ++ "Ö": true, ++ "‾": true, ++ "⏞": true, ++ "⎴": true, ++ "⏜": true, ++ "∂": true, ++ "П": true, ++ "𝔓": true, ++ "Φ": true, ++ "Π": true, ++ "±": true, ++ "ℌ": true, ++ "ℙ": true, ++ "⪻": true, ++ "≺": true, ++ "⪯": true, ++ "≼": true, ++ "≾": true, ++ "″": true, ++ "∏": true, ++ "∷": true, ++ "∝": true, ++ "𝒫": true, ++ "Ψ": true, ++ """: true, ++ """: true, ++ "𝔔": true, ++ "ℚ": true, ++ "𝒬": true, ++ "⤐": true, ++ "®": true, ++ "®": true, ++ "Ŕ": true, ++ "⟫": true, ++ "↠": true, ++ "⤖": true, ++ "Ř": true, ++ "Ŗ": true, ++ "Р": true, ++ "ℜ": true, ++ "∋": true, ++ "⇋": true, ++ "⥯": true, ++ "ℜ": true, ++ "Ρ": true, ++ "⟩": true, ++ "→": true, ++ "⇥": true, ++ "⇄": true, ++ "⌉": true, ++ "⟧": true, ++ "⥝": true, ++ "⇂": true, ++ "⥕": true, ++ "⌋": true, ++ "⊢": true, ++ "↦": true, ++ "⥛": true, ++ "⊳": true, ++ "⧐": true, ++ "⊵": true, ++ "⥏": true, ++ "⥜": true, ++ "↾": true, ++ "⥔": true, ++ "⇀": true, ++ "⥓": true, ++ "⇒": true, ++ "ℝ": true, ++ "⥰": true, ++ "⇛": true, ++ "ℛ": true, ++ "↱": true, ++ "⧴": true, ++ "Щ": true, ++ "Ш": true, ++ "Ь": true, ++ "Ś": true, ++ "⪼": true, ++ "Š": true, ++ "Ş": true, ++ "Ŝ": true, ++ "С": true, ++ "𝔖": true, ++ "↓": true, ++ "←": true, ++ "→": true, ++ "↑": true, ++ "Σ": true, ++ "∘": true, ++ "𝕊": true, ++ "√": true, ++ "□": true, ++ "⊓": true, ++ "⊏": true, ++ "⊑": true, ++ "⊐": true, ++ "⊒": true, ++ "⊔": true, ++ "𝒮": true, ++ "⋆": true, ++ "⋐": true, ++ "⋐": true, ++ "⊆": true, ++ "≻": true, ++ "⪰": true, ++ "≽": true, ++ "≿": true, ++ "∋": true, ++ "∑": true, ++ "⋑": true, ++ "⊃": true, ++ "⊇": true, ++ "⋑": true, ++ "Þ": true, ++ "Þ": true, ++ "™": true, ++ "Ћ": true, ++ "Ц": true, ++ " ": true, ++ "Τ": true, ++ "Ť": true, ++ "Ţ": true, ++ "Т": true, ++ "𝔗": true, ++ "∴": true, ++ "Θ": true, ++ "  ": true, ++ " ": true, ++ "∼": true, ++ "≃": true, ++ "≅": true, ++ "≈": true, ++ "𝕋": true, ++ "⃛": true, ++ "𝒯": true, ++ "Ŧ": true, ++ "Ú": true, ++ "Ú": true, ++ "↟": true, ++ "⥉": true, ++ "Ў": true, ++ "Ŭ": true, ++ "Û": true, ++ "Û": true, ++ "У": true, ++ "Ű": true, ++ "𝔘": true, ++ "Ù": true, ++ "Ù": true, ++ "Ū": true, ++ "_": true, ++ "⏟": true, ++ "⎵": true, ++ "⏝": true, ++ "⋃": true, ++ "⊎": true, ++ "Ų": true, ++ "𝕌": true, ++ "↑": true, ++ "⤒": true, ++ "⇅": true, ++ "↕": true, ++ "⥮": true, ++ "⊥": true, ++ "↥": true, ++ "⇑": true, ++ "⇕": true, ++ "↖": true, ++ "↗": true, ++ "ϒ": true, ++ "Υ": true, ++ "Ů": true, ++ "𝒰": true, ++ "Ũ": true, ++ "Ü": true, ++ "Ü": true, ++ "⊫": true, ++ "⫫": true, ++ "В": true, ++ "⊩": true, ++ "⫦": true, ++ "⋁": true, ++ "‖": true, ++ "‖": true, ++ "∣": true, ++ "|": true, ++ "❘": true, ++ "≀": true, ++ " ": true, ++ "𝔙": true, ++ "𝕍": true, ++ "𝒱": true, ++ "⊪": true, ++ "Ŵ": true, ++ "⋀": true, ++ "𝔚": true, ++ "𝕎": true, ++ "𝒲": true, ++ "𝔛": true, ++ "Ξ": true, ++ "𝕏": true, ++ "𝒳": true, ++ "Я": true, ++ "Ї": true, ++ "Ю": true, ++ "Ý": true, ++ "Ý": true, ++ "Ŷ": true, ++ "Ы": true, ++ "𝔜": true, ++ "𝕐": true, ++ "𝒴": true, ++ "Ÿ": true, ++ "Ж": true, ++ "Ź": true, ++ "Ž": true, ++ "З": true, ++ "Ż": true, ++ "​": true, ++ "Ζ": true, ++ "ℨ": true, ++ "ℤ": true, ++ "𝒵": true, ++ "á": true, ++ "á": true, ++ "ă": true, ++ "∾": true, ++ "∾̳": true, ++ "∿": true, ++ "â": true, ++ "â": true, ++ "´": true, ++ "´": true, ++ "а": true, ++ "æ": true, ++ "æ": true, ++ "⁡": true, ++ "𝔞": true, ++ "à": true, ++ "à": true, ++ "ℵ": true, ++ "ℵ": true, ++ "α": true, ++ "ā": true, ++ "⨿": true, ++ "&": true, ++ "&": true, ++ "∧": true, ++ "⩕": true, ++ "⩜": true, ++ "⩘": true, ++ "⩚": true, ++ "∠": true, ++ "⦤": true, ++ "∠": true, ++ "∡": true, ++ "⦨": true, ++ "⦩": true, ++ "⦪": true, ++ "⦫": true, ++ "⦬": true, ++ "⦭": true, ++ "⦮": true, ++ "⦯": true, ++ "∟": true, ++ "⊾": true, ++ "⦝": true, ++ "∢": true, ++ "Å": true, ++ "⍼": true, ++ "ą": true, ++ "𝕒": true, ++ "≈": true, ++ "⩰": true, ++ "⩯": true, ++ "≊": true, ++ "≋": true, ++ "'": true, ++ "≈": true, ++ "≊": true, ++ "å": true, ++ "å": true, ++ "𝒶": true, ++ "*": true, ++ "≈": true, ++ "≍": true, ++ "ã": true, ++ "ã": true, ++ "ä": true, ++ "ä": true, ++ "∳": true, ++ "⨑": true, ++ "⫭": true, ++ "≌": true, ++ "϶": true, ++ "‵": true, ++ "∽": true, ++ "⋍": true, ++ "⊽": true, ++ "⌅": true, ++ "⌅": true, ++ "⎵": true, ++ "⎶": true, ++ "≌": true, ++ "б": true, ++ "„": true, ++ "∵": true, ++ "∵": true, ++ "⦰": true, ++ "϶": true, ++ "ℬ": true, ++ "β": true, ++ "ℶ": true, ++ "≬": true, ++ "𝔟": true, ++ "⋂": true, ++ "◯": true, ++ "⋃": true, ++ "⨀": true, ++ "⨁": true, ++ "⨂": true, ++ "⨆": true, ++ "★": true, ++ "▽": true, ++ "△": true, ++ "⨄": true, ++ "⋁": true, ++ "⋀": true, ++ "⤍": true, ++ "⧫": true, ++ "▪": true, ++ "▴": true, ++ "▾": true, ++ "◂": true, ++ "▸": true, ++ "␣": true, ++ "▒": true, ++ "░": true, ++ "▓": true, ++ "█": true, ++ "=⃥": true, ++ "≡⃥": true, ++ "⌐": true, ++ "𝕓": true, ++ "⊥": true, ++ "⊥": true, ++ "⋈": true, ++ "╗": true, ++ "╔": true, ++ "╖": true, ++ "╓": true, ++ "═": true, ++ "╦": true, ++ "╩": true, ++ "╤": true, ++ "╧": true, ++ "╝": true, ++ "╚": true, ++ "╜": true, ++ "╙": true, ++ "║": true, ++ "╬": true, ++ "╣": true, ++ "╠": true, ++ "╫": true, ++ "╢": true, ++ "╟": true, ++ "⧉": true, ++ "╕": true, ++ "╒": true, ++ "┐": true, ++ "┌": true, ++ "─": true, ++ "╥": true, ++ "╨": true, ++ "┬": true, ++ "┴": true, ++ "⊟": true, ++ "⊞": true, ++ "⊠": true, ++ "╛": true, ++ "╘": true, ++ "┘": true, ++ "└": true, ++ "│": true, ++ "╪": true, ++ "╡": true, ++ "╞": true, ++ "┼": true, ++ "┤": true, ++ "├": true, ++ "‵": true, ++ "˘": true, ++ "¦": true, ++ "¦": true, ++ "𝒷": true, ++ "⁏": true, ++ "∽": true, ++ "⋍": true, ++ "\": true, ++ "⧅": true, ++ "⟈": true, ++ "•": true, ++ "•": true, ++ "≎": true, ++ "⪮": true, ++ "≏": true, ++ "≏": true, ++ "ć": true, ++ "∩": true, ++ "⩄": true, ++ "⩉": true, ++ "⩋": true, ++ "⩇": true, ++ "⩀": true, ++ "∩︀": true, ++ "⁁": true, ++ "ˇ": true, ++ "⩍": true, ++ "č": true, ++ "ç": true, ++ "ç": true, ++ "ĉ": true, ++ "⩌": true, ++ "⩐": true, ++ "ċ": true, ++ "¸": true, ++ "¸": true, ++ "⦲": true, ++ "¢": true, ++ "¢": true, ++ "·": true, ++ "𝔠": true, ++ "ч": true, ++ "✓": true, ++ "✓": true, ++ "χ": true, ++ "○": true, ++ "⧃": true, ++ "ˆ": true, ++ "≗": true, ++ "↺": true, ++ "↻": true, ++ "®": true, ++ "Ⓢ": true, ++ "⊛": true, ++ "⊚": true, ++ "⊝": true, ++ "≗": true, ++ "⨐": true, ++ "⫯": true, ++ "⧂": true, ++ "♣": true, ++ "♣": true, ++ ":": true, ++ "≔": true, ++ "≔": true, ++ ",": true, ++ "@": true, ++ "∁": true, ++ "∘": true, ++ "∁": true, ++ "ℂ": true, ++ "≅": true, ++ "⩭": true, ++ "∮": true, ++ "𝕔": true, ++ "∐": true, ++ "©": true, ++ "©": true, ++ "℗": true, ++ "↵": true, ++ "✗": true, ++ "𝒸": true, ++ "⫏": true, ++ "⫑": true, ++ "⫐": true, ++ "⫒": true, ++ "⋯": true, ++ "⤸": true, ++ "⤵": true, ++ "⋞": true, ++ "⋟": true, ++ "↶": true, ++ "⤽": true, ++ "∪": true, ++ "⩈": true, ++ "⩆": true, ++ "⩊": true, ++ "⊍": true, ++ "⩅": true, ++ "∪︀": true, ++ "↷": true, ++ "⤼": true, ++ "⋞": true, ++ "⋟": true, ++ "⋎": true, ++ "⋏": true, ++ "¤": true, ++ "¤": true, ++ "↶": true, ++ "↷": true, ++ "⋎": true, ++ "⋏": true, ++ "∲": true, ++ "∱": true, ++ "⌭": true, ++ "⇓": true, ++ "⥥": true, ++ "†": true, ++ "ℸ": true, ++ "↓": true, ++ "‐": true, ++ "⊣": true, ++ "⤏": true, ++ "˝": true, ++ "ď": true, ++ "д": true, ++ "ⅆ": true, ++ "‡": true, ++ "⇊": true, ++ "⩷": true, ++ "°": true, ++ "°": true, ++ "δ": true, ++ "⦱": true, ++ "⥿": true, ++ "𝔡": true, ++ "⇃": true, ++ "⇂": true, ++ "⋄": true, ++ "⋄": true, ++ "♦": true, ++ "♦": true, ++ "¨": true, ++ "ϝ": true, ++ "⋲": true, ++ "÷": true, ++ "÷": true, ++ "÷": true, ++ "⋇": true, ++ "⋇": true, ++ "ђ": true, ++ "⌞": true, ++ "⌍": true, ++ "$": true, ++ "𝕕": true, ++ "˙": true, ++ "≐": true, ++ "≑": true, ++ "∸": true, ++ "∔": true, ++ "⊡": true, ++ "⌆": true, ++ "↓": true, ++ "⇊": true, ++ "⇃": true, ++ "⇂": true, ++ "⤐": true, ++ "⌟": true, ++ "⌌": true, ++ "𝒹": true, ++ "ѕ": true, ++ "⧶": true, ++ "đ": true, ++ "⋱": true, ++ "▿": true, ++ "▾": true, ++ "⇵": true, ++ "⥯": true, ++ "⦦": true, ++ "џ": true, ++ "⟿": true, ++ "⩷": true, ++ "≑": true, ++ "é": true, ++ "é": true, ++ "⩮": true, ++ "ě": true, ++ "≖": true, ++ "ê": true, ++ "ê": true, ++ "≕": true, ++ "э": true, ++ "ė": true, ++ "ⅇ": true, ++ "≒": true, ++ "𝔢": true, ++ "⪚": true, ++ "è": true, ++ "è": true, ++ "⪖": true, ++ "⪘": true, ++ "⪙": true, ++ "⏧": true, ++ "ℓ": true, ++ "⪕": true, ++ "⪗": true, ++ "ē": true, ++ "∅": true, ++ "∅": true, ++ "∅": true, ++ " ": true, ++ " ": true, ++ " ": true, ++ "ŋ": true, ++ " ": true, ++ "ę": true, ++ "𝕖": true, ++ "⋕": true, ++ "⧣": true, ++ "⩱": true, ++ "ε": true, ++ "ε": true, ++ "ϵ": true, ++ "≖": true, ++ "≕": true, ++ "≂": true, ++ "⪖": true, ++ "⪕": true, ++ "=": true, ++ "≟": true, ++ "≡": true, ++ "⩸": true, ++ "⧥": true, ++ "≓": true, ++ "⥱": true, ++ "ℯ": true, ++ "≐": true, ++ "≂": true, ++ "η": true, ++ "ð": true, ++ "ð": true, ++ "ë": true, ++ "ë": true, ++ "€": true, ++ "!": true, ++ "∃": true, ++ "ℰ": true, ++ "ⅇ": true, ++ "≒": true, ++ "ф": true, ++ "♀": true, ++ "ffi": true, ++ "ff": true, ++ "ffl": true, ++ "𝔣": true, ++ "fi": true, ++ "fj": true, ++ "♭": true, ++ "fl": true, ++ "▱": true, ++ "ƒ": true, ++ "𝕗": true, ++ "∀": true, ++ "⋔": true, ++ "⫙": true, ++ "⨍": true, ++ "½": true, ++ "½": true, ++ "⅓": true, ++ "¼": true, ++ "¼": true, ++ "⅕": true, ++ "⅙": true, ++ "⅛": true, ++ "⅔": true, ++ "⅖": true, ++ "¾": true, ++ "¾": true, ++ "⅗": true, ++ "⅜": true, ++ "⅘": true, ++ "⅚": true, ++ "⅝": true, ++ "⅞": true, ++ "⁄": true, ++ "⌢": true, ++ "𝒻": true, ++ "≧": true, ++ "⪌": true, ++ "ǵ": true, ++ "γ": true, ++ "ϝ": true, ++ "⪆": true, ++ "ğ": true, ++ "ĝ": true, ++ "г": true, ++ "ġ": true, ++ "≥": true, ++ "⋛": true, ++ "≥": true, ++ "≧": true, ++ "⩾": true, ++ "⩾": true, ++ "⪩": true, ++ "⪀": true, ++ "⪂": true, ++ "⪄": true, ++ "⋛︀": true, ++ "⪔": true, ++ "𝔤": true, ++ "≫": true, ++ "⋙": true, ++ "ℷ": true, ++ "ѓ": true, ++ "≷": true, ++ "⪒": true, ++ "⪥": true, ++ "⪤": true, ++ "≩": true, ++ "⪊": true, ++ "⪊": true, ++ "⪈": true, ++ "⪈": true, ++ "≩": true, ++ "⋧": true, ++ "𝕘": true, ++ "`": true, ++ "ℊ": true, ++ "≳": true, ++ "⪎": true, ++ "⪐": true, ++ ">": true, ++ ">": true, ++ "⪧": true, ++ "⩺": true, ++ "⋗": true, ++ "⦕": true, ++ "⩼": true, ++ "⪆": true, ++ "⥸": true, ++ "⋗": true, ++ "⋛": true, ++ "⪌": true, ++ "≷": true, ++ "≳": true, ++ "≩︀": true, ++ "≩︀": true, ++ "⇔": true, ++ " ": true, ++ "½": true, ++ "ℋ": true, ++ "ъ": true, ++ "↔": true, ++ "⥈": true, ++ "↭": true, ++ "ℏ": true, ++ "ĥ": true, ++ "♥": true, ++ "♥": true, ++ "…": true, ++ "⊹": true, ++ "𝔥": true, ++ "⤥": true, ++ "⤦": true, ++ "⇿": true, ++ "∻": true, ++ "↩": true, ++ "↪": true, ++ "𝕙": true, ++ "―": true, ++ "𝒽": true, ++ "ℏ": true, ++ "ħ": true, ++ "⁃": true, ++ "‐": true, ++ "í": true, ++ "í": true, ++ "⁣": true, ++ "î": true, ++ "î": true, ++ "и": true, ++ "е": true, ++ "¡": true, ++ "¡": true, ++ "⇔": true, ++ "𝔦": true, ++ "ì": true, ++ "ì": true, ++ "ⅈ": true, ++ "⨌": true, ++ "∭": true, ++ "⧜": true, ++ "℩": true, ++ "ij": true, ++ "ī": true, ++ "ℑ": true, ++ "ℐ": true, ++ "ℑ": true, ++ "ı": true, ++ "⊷": true, ++ "Ƶ": true, ++ "∈": true, ++ "℅": true, ++ "∞": true, ++ "⧝": true, ++ "ı": true, ++ "∫": true, ++ "⊺": true, ++ "ℤ": true, ++ "⊺": true, ++ "⨗": true, ++ "⨼": true, ++ "ё": true, ++ "į": true, ++ "𝕚": true, ++ "ι": true, ++ "⨼": true, ++ "¿": true, ++ "¿": true, ++ "𝒾": true, ++ "∈": true, ++ "⋹": true, ++ "⋵": true, ++ "⋴": true, ++ "⋳": true, ++ "∈": true, ++ "⁢": true, ++ "ĩ": true, ++ "і": true, ++ "ï": true, ++ "ï": true, ++ "ĵ": true, ++ "й": true, ++ "𝔧": true, ++ "ȷ": true, ++ "𝕛": true, ++ "𝒿": true, ++ "ј": true, ++ "є": true, ++ "κ": true, ++ "ϰ": true, ++ "ķ": true, ++ "к": true, ++ "𝔨": true, ++ "ĸ": true, ++ "х": true, ++ "ќ": true, ++ "𝕜": true, ++ "𝓀": true, ++ "⇚": true, ++ "⇐": true, ++ "⤛": true, ++ "⤎": true, ++ "≦": true, ++ "⪋": true, ++ "⥢": true, ++ "ĺ": true, ++ "⦴": true, ++ "ℒ": true, ++ "λ": true, ++ "⟨": true, ++ "⦑": true, ++ "⟨": true, ++ "⪅": true, ++ "«": true, ++ "«": true, ++ "←": true, ++ "⇤": true, ++ "⤟": true, ++ "⤝": true, ++ "↩": true, ++ "↫": true, ++ "⤹": true, ++ "⥳": true, ++ "↢": true, ++ "⪫": true, ++ "⤙": true, ++ "⪭": true, ++ "⪭︀": true, ++ "⤌": true, ++ "❲": true, ++ "{": true, ++ "[": true, ++ "⦋": true, ++ "⦏": true, ++ "⦍": true, ++ "ľ": true, ++ "ļ": true, ++ "⌈": true, ++ "{": true, ++ "л": true, ++ "⤶": true, ++ "“": true, ++ "„": true, ++ "⥧": true, ++ "⥋": true, ++ "↲": true, ++ "≤": true, ++ "←": true, ++ "↢": true, ++ "↽": true, ++ "↼": true, ++ "⇇": true, ++ "↔": true, ++ "⇆": true, ++ "⇋": true, ++ "↭": true, ++ "⋋": true, ++ "⋚": true, ++ "≤": true, ++ "≦": true, ++ "⩽": true, ++ "⩽": true, ++ "⪨": true, ++ "⩿": true, ++ "⪁": true, ++ "⪃": true, ++ "⋚︀": true, ++ "⪓": true, ++ "⪅": true, ++ "⋖": true, ++ "⋚": true, ++ "⪋": true, ++ "≶": true, ++ "≲": true, ++ "⥼": true, ++ "⌊": true, ++ "𝔩": true, ++ "≶": true, ++ "⪑": true, ++ "↽": true, ++ "↼": true, ++ "⥪": true, ++ "▄": true, ++ "љ": true, ++ "≪": true, ++ "⇇": true, ++ "⌞": true, ++ "⥫": true, ++ "◺": true, ++ "ŀ": true, ++ "⎰": true, ++ "⎰": true, ++ "≨": true, ++ "⪉": true, ++ "⪉": true, ++ "⪇": true, ++ "⪇": true, ++ "≨": true, ++ "⋦": true, ++ "⟬": true, ++ "⇽": true, ++ "⟦": true, ++ "⟵": true, ++ "⟷": true, ++ "⟼": true, ++ "⟶": true, ++ "↫": true, ++ "↬": true, ++ "⦅": true, ++ "𝕝": true, ++ "⨭": true, ++ "⨴": true, ++ "∗": true, ++ "_": true, ++ "◊": true, ++ "◊": true, ++ "⧫": true, ++ "(": true, ++ "⦓": true, ++ "⇆": true, ++ "⌟": true, ++ "⇋": true, ++ "⥭": true, ++ "‎": true, ++ "⊿": true, ++ "‹": true, ++ "𝓁": true, ++ "↰": true, ++ "≲": true, ++ "⪍": true, ++ "⪏": true, ++ "[": true, ++ "‘": true, ++ "‚": true, ++ "ł": true, ++ "<": true, ++ "<": true, ++ "⪦": true, ++ "⩹": true, ++ "⋖": true, ++ "⋋": true, ++ "⋉": true, ++ "⥶": true, ++ "⩻": true, ++ "⦖": true, ++ "◃": true, ++ "⊴": true, ++ "◂": true, ++ "⥊": true, ++ "⥦": true, ++ "≨︀": true, ++ "≨︀": true, ++ "∺": true, ++ "¯": true, ++ "¯": true, ++ "♂": true, ++ "✠": true, ++ "✠": true, ++ "↦": true, ++ "↦": true, ++ "↧": true, ++ "↤": true, ++ "↥": true, ++ "▮": true, ++ "⨩": true, ++ "м": true, ++ "—": true, ++ "∡": true, ++ "𝔪": true, ++ "℧": true, ++ "µ": true, ++ "µ": true, ++ "∣": true, ++ "*": true, ++ "⫰": true, ++ "·": true, ++ "·": true, ++ "−": true, ++ "⊟": true, ++ "∸": true, ++ "⨪": true, ++ "⫛": true, ++ "…": true, ++ "∓": true, ++ "⊧": true, ++ "𝕞": true, ++ "∓": true, ++ "𝓂": true, ++ "∾": true, ++ "μ": true, ++ "⊸": true, ++ "⊸": true, ++ "⋙̸": true, ++ "≫⃒": true, ++ "≫̸": true, ++ "⇍": true, ++ "⇎": true, ++ "⋘̸": true, ++ "≪⃒": true, ++ "≪̸": true, ++ "⇏": true, ++ "⊯": true, ++ "⊮": true, ++ "∇": true, ++ "ń": true, ++ "∠⃒": true, ++ "≉": true, ++ "⩰̸": true, ++ "≋̸": true, ++ "ʼn": true, ++ "≉": true, ++ "♮": true, ++ "♮": true, ++ "ℕ": true, ++ " ": true, ++ " ": true, ++ "≎̸": true, ++ "≏̸": true, ++ "⩃": true, ++ "ň": true, ++ "ņ": true, ++ "≇": true, ++ "⩭̸": true, ++ "⩂": true, ++ "н": true, ++ "–": true, ++ "≠": true, ++ "⇗": true, ++ "⤤": true, ++ "↗": true, ++ "↗": true, ++ "≐̸": true, ++ "≢": true, ++ "⤨": true, ++ "≂̸": true, ++ "∄": true, ++ "∄": true, ++ "𝔫": true, ++ "≧̸": true, ++ "≱": true, ++ "≱": true, ++ "≧̸": true, ++ "⩾̸": true, ++ "⩾̸": true, ++ "≵": true, ++ "≯": true, ++ "≯": true, ++ "⇎": true, ++ "↮": true, ++ "⫲": true, ++ "∋": true, ++ "⋼": true, ++ "⋺": true, ++ "∋": true, ++ "њ": true, ++ "⇍": true, ++ "≦̸": true, ++ "↚": true, ++ "‥": true, ++ "≰": true, ++ "↚": true, ++ "↮": true, ++ "≰": true, ++ "≦̸": true, ++ "⩽̸": true, ++ "⩽̸": true, ++ "≮": true, ++ "≴": true, ++ "≮": true, ++ "⋪": true, ++ "⋬": true, ++ "∤": true, ++ "𝕟": true, ++ "¬": true, ++ "¬": true, ++ "∉": true, ++ "⋹̸": true, ++ "⋵̸": true, ++ "∉": true, ++ "⋷": true, ++ "⋶": true, ++ "∌": true, ++ "∌": true, ++ "⋾": true, ++ "⋽": true, ++ "∦": true, ++ "∦": true, ++ "⫽⃥": true, ++ "∂̸": true, ++ "⨔": true, ++ "⊀": true, ++ "⋠": true, ++ "⪯̸": true, ++ "⊀": true, ++ "⪯̸": true, ++ "⇏": true, ++ "↛": true, ++ "⤳̸": true, ++ "↝̸": true, ++ "↛": true, ++ "⋫": true, ++ "⋭": true, ++ "⊁": true, ++ "⋡": true, ++ "⪰̸": true, ++ "𝓃": true, ++ "∤": true, ++ "∦": true, ++ "≁": true, ++ "≄": true, ++ "≄": true, ++ "∤": true, ++ "∦": true, ++ "⋢": true, ++ "⋣": true, ++ "⊄": true, ++ "⫅̸": true, ++ "⊈": true, ++ "⊂⃒": true, ++ "⊈": true, ++ "⫅̸": true, ++ "⊁": true, ++ "⪰̸": true, ++ "⊅": true, ++ "⫆̸": true, ++ "⊉": true, ++ "⊃⃒": true, ++ "⊉": true, ++ "⫆̸": true, ++ "≹": true, ++ "ñ": true, ++ "ñ": true, ++ "≸": true, ++ "⋪": true, ++ "⋬": true, ++ "⋫": true, ++ "⋭": true, ++ "ν": true, ++ "#": true, ++ "№": true, ++ " ": true, ++ "⊭": true, ++ "⤄": true, ++ "≍⃒": true, ++ "⊬": true, ++ "≥⃒": true, ++ ">⃒": true, ++ "⧞": true, ++ "⤂": true, ++ "≤⃒": true, ++ "<⃒": true, ++ "⊴⃒": true, ++ "⤃": true, ++ "⊵⃒": true, ++ "∼⃒": true, ++ "⇖": true, ++ "⤣": true, ++ "↖": true, ++ "↖": true, ++ "⤧": true, ++ "Ⓢ": true, ++ "ó": true, ++ "ó": true, ++ "⊛": true, ++ "⊚": true, ++ "ô": true, ++ "ô": true, ++ "о": true, ++ "⊝": true, ++ "ő": true, ++ "⨸": true, ++ "⊙": true, ++ "⦼": true, ++ "œ": true, ++ "⦿": true, ++ "𝔬": true, ++ "˛": true, ++ "ò": true, ++ "ò": true, ++ "⧁": true, ++ "⦵": true, ++ "Ω": true, ++ "∮": true, ++ "↺": true, ++ "⦾": true, ++ "⦻": true, ++ "‾": true, ++ "⧀": true, ++ "ō": true, ++ "ω": true, ++ "ο": true, ++ "⦶": true, ++ "⊖": true, ++ "𝕠": true, ++ "⦷": true, ++ "⦹": true, ++ "⊕": true, ++ "∨": true, ++ "↻": true, ++ "⩝": true, ++ "ℴ": true, ++ "ℴ": true, ++ "ª": true, ++ "ª": true, ++ "º": true, ++ "º": true, ++ "⊶": true, ++ "⩖": true, ++ "⩗": true, ++ "⩛": true, ++ "ℴ": true, ++ "ø": true, ++ "ø": true, ++ "⊘": true, ++ "õ": true, ++ "õ": true, ++ "⊗": true, ++ "⨶": true, ++ "ö": true, ++ "ö": true, ++ "⌽": true, ++ "∥": true, ++ "¶": true, ++ "¶": true, ++ "∥": true, ++ "⫳": true, ++ "⫽": true, ++ "∂": true, ++ "п": true, ++ "%": true, ++ ".": true, ++ "‰": true, ++ "⊥": true, ++ "‱": true, ++ "𝔭": true, ++ "φ": true, ++ "ϕ": true, ++ "ℳ": true, ++ "☎": true, ++ "π": true, ++ "⋔": true, ++ "ϖ": true, ++ "ℏ": true, ++ "ℎ": true, ++ "ℏ": true, ++ "+": true, ++ "⨣": true, ++ "⊞": true, ++ "⨢": true, ++ "∔": true, ++ "⨥": true, ++ "⩲": true, ++ "±": true, ++ "±": true, ++ "⨦": true, ++ "⨧": true, ++ "±": true, ++ "⨕": true, ++ "𝕡": true, ++ "£": true, ++ "£": true, ++ "≺": true, ++ "⪳": true, ++ "⪷": true, ++ "≼": true, ++ "⪯": true, ++ "≺": true, ++ "⪷": true, ++ "≼": true, ++ "⪯": true, ++ "⪹": true, ++ "⪵": true, ++ "⋨": true, ++ "≾": true, ++ "′": true, ++ "ℙ": true, ++ "⪵": true, ++ "⪹": true, ++ "⋨": true, ++ "∏": true, ++ "⌮": true, ++ "⌒": true, ++ "⌓": true, ++ "∝": true, ++ "∝": true, ++ "≾": true, ++ "⊰": true, ++ "𝓅": true, ++ "ψ": true, ++ " ": true, ++ "𝔮": true, ++ "⨌": true, ++ "𝕢": true, ++ "⁗": true, ++ "𝓆": true, ++ "ℍ": true, ++ "⨖": true, ++ "?": true, ++ "≟": true, ++ """: true, ++ """: true, ++ "⇛": true, ++ "⇒": true, ++ "⤜": true, ++ "⤏": true, ++ "⥤": true, ++ "∽̱": true, ++ "ŕ": true, ++ "√": true, ++ "⦳": true, ++ "⟩": true, ++ "⦒": true, ++ "⦥": true, ++ "⟩": true, ++ "»": true, ++ "»": true, ++ "→": true, ++ "⥵": true, ++ "⇥": true, ++ "⤠": true, ++ "⤳": true, ++ "⤞": true, ++ "↪": true, ++ "↬": true, ++ "⥅": true, ++ "⥴": true, ++ "↣": true, ++ "↝": true, ++ "⤚": true, ++ "∶": true, ++ "ℚ": true, ++ "⤍": true, ++ "❳": true, ++ "}": true, ++ "]": true, ++ "⦌": true, ++ "⦎": true, ++ "⦐": true, ++ "ř": true, ++ "ŗ": true, ++ "⌉": true, ++ "}": true, ++ "р": true, ++ "⤷": true, ++ "⥩": true, ++ "”": true, ++ "”": true, ++ "↳": true, ++ "ℜ": true, ++ "ℛ": true, ++ "ℜ": true, ++ "ℝ": true, ++ "▭": true, ++ "®": true, ++ "®": true, ++ "⥽": true, ++ "⌋": true, ++ "𝔯": true, ++ "⇁": true, ++ "⇀": true, ++ "⥬": true, ++ "ρ": true, ++ "ϱ": true, ++ "→": true, ++ "↣": true, ++ "⇁": true, ++ "⇀": true, ++ "⇄": true, ++ "⇌": true, ++ "⇉": true, ++ "↝": true, ++ "⋌": true, ++ "˚": true, ++ "≓": true, ++ "⇄": true, ++ "⇌": true, ++ "‏": true, ++ "⎱": true, ++ "⎱": true, ++ "⫮": true, ++ "⟭": true, ++ "⇾": true, ++ "⟧": true, ++ "⦆": true, ++ "𝕣": true, ++ "⨮": true, ++ "⨵": true, ++ ")": true, ++ "⦔": true, ++ "⨒": true, ++ "⇉": true, ++ "›": true, ++ "𝓇": true, ++ "↱": true, ++ "]": true, ++ "’": true, ++ "’": true, ++ "⋌": true, ++ "⋊": true, ++ "▹": true, ++ "⊵": true, ++ "▸": true, ++ "⧎": true, ++ "⥨": true, ++ "℞": true, ++ "ś": true, ++ "‚": true, ++ "≻": true, ++ "⪴": true, ++ "⪸": true, ++ "š": true, ++ "≽": true, ++ "⪰": true, ++ "ş": true, ++ "ŝ": true, ++ "⪶": true, ++ "⪺": true, ++ "⋩": true, ++ "⨓": true, ++ "≿": true, ++ "с": true, ++ "⋅": true, ++ "⊡": true, ++ "⩦": true, ++ "⇘": true, ++ "⤥": true, ++ "↘": true, ++ "↘": true, ++ "§": true, ++ "§": true, ++ ";": true, ++ "⤩": true, ++ "∖": true, ++ "∖": true, ++ "✶": true, ++ "𝔰": true, ++ "⌢": true, ++ "♯": true, ++ "щ": true, ++ "ш": true, ++ "∣": true, ++ "∥": true, ++ "­": true, ++ "­": true, ++ "σ": true, ++ "ς": true, ++ "ς": true, ++ "∼": true, ++ "⩪": true, ++ "≃": true, ++ "≃": true, ++ "⪞": true, ++ "⪠": true, ++ "⪝": true, ++ "⪟": true, ++ "≆": true, ++ "⨤": true, ++ "⥲": true, ++ "←": true, ++ "∖": true, ++ "⨳": true, ++ "⧤": true, ++ "∣": true, ++ "⌣": true, ++ "⪪": true, ++ "⪬": true, ++ "⪬︀": true, ++ "ь": true, ++ "/": true, ++ "⧄": true, ++ "⌿": true, ++ "𝕤": true, ++ "♠": true, ++ "♠": true, ++ "∥": true, ++ "⊓": true, ++ "⊓︀": true, ++ "⊔": true, ++ "⊔︀": true, ++ "⊏": true, ++ "⊑": true, ++ "⊏": true, ++ "⊑": true, ++ "⊐": true, ++ "⊒": true, ++ "⊐": true, ++ "⊒": true, ++ "□": true, ++ "□": true, ++ "▪": true, ++ "▪": true, ++ "→": true, ++ "𝓈": true, ++ "∖": true, ++ "⌣": true, ++ "⋆": true, ++ "☆": true, ++ "★": true, ++ "ϵ": true, ++ "ϕ": true, ++ "¯": true, ++ "⊂": true, ++ "⫅": true, ++ "⪽": true, ++ "⊆": true, ++ "⫃": true, ++ "⫁": true, ++ "⫋": true, ++ "⊊": true, ++ "⪿": true, ++ "⥹": true, ++ "⊂": true, ++ "⊆": true, ++ "⫅": true, ++ "⊊": true, ++ "⫋": true, ++ "⫇": true, ++ "⫕": true, ++ "⫓": true, ++ "≻": true, ++ "⪸": true, ++ "≽": true, ++ "⪰": true, ++ "⪺": true, ++ "⪶": true, ++ "⋩": true, ++ "≿": true, ++ "∑": true, ++ "♪": true, ++ "¹": true, ++ "¹": true, ++ "²": true, ++ "²": true, ++ "³": true, ++ "³": true, ++ "⊃": true, ++ "⫆": true, ++ "⪾": true, ++ "⫘": true, ++ "⊇": true, ++ "⫄": true, ++ "⟉": true, ++ "⫗": true, ++ "⥻": true, ++ "⫂": true, ++ "⫌": true, ++ "⊋": true, ++ "⫀": true, ++ "⊃": true, ++ "⊇": true, ++ "⫆": true, ++ "⊋": true, ++ "⫌": true, ++ "⫈": true, ++ "⫔": true, ++ "⫖": true, ++ "⇙": true, ++ "⤦": true, ++ "↙": true, ++ "↙": true, ++ "⤪": true, ++ "ß": true, ++ "ß": true, ++ "⌖": true, ++ "τ": true, ++ "⎴": true, ++ "ť": true, ++ "ţ": true, ++ "т": true, ++ "⃛": true, ++ "⌕": true, ++ "𝔱": true, ++ "∴": true, ++ "∴": true, ++ "θ": true, ++ "ϑ": true, ++ "ϑ": true, ++ "≈": true, ++ "∼": true, ++ " ": true, ++ "≈": true, ++ "∼": true, ++ "þ": true, ++ "þ": true, ++ "˜": true, ++ "×": true, ++ "×": true, ++ "⊠": true, ++ "⨱": true, ++ "⨰": true, ++ "∭": true, ++ "⤨": true, ++ "⊤": true, ++ "⌶": true, ++ "⫱": true, ++ "𝕥": true, ++ "⫚": true, ++ "⤩": true, ++ "‴": true, ++ "™": true, ++ "▵": true, ++ "▿": true, ++ "◃": true, ++ "⊴": true, ++ "≜": true, ++ "▹": true, ++ "⊵": true, ++ "◬": true, ++ "≜": true, ++ "⨺": true, ++ "⨹": true, ++ "⧍": true, ++ "⨻": true, ++ "⏢": true, ++ "𝓉": true, ++ "ц": true, ++ "ћ": true, ++ "ŧ": true, ++ "≬": true, ++ "↞": true, ++ "↠": true, ++ "⇑": true, ++ "⥣": true, ++ "ú": true, ++ "ú": true, ++ "↑": true, ++ "ў": true, ++ "ŭ": true, ++ "û": true, ++ "û": true, ++ "у": true, ++ "⇅": true, ++ "ű": true, ++ "⥮": true, ++ "⥾": true, ++ "𝔲": true, ++ "ù": true, ++ "ù": true, ++ "↿": true, ++ "↾": true, ++ "▀": true, ++ "⌜": true, ++ "⌜": true, ++ "⌏": true, ++ "◸": true, ++ "ū": true, ++ "¨": true, ++ "¨": true, ++ "ų": true, ++ "𝕦": true, ++ "↑": true, ++ "↕": true, ++ "↿": true, ++ "↾": true, ++ "⊎": true, ++ "υ": true, ++ "ϒ": true, ++ "υ": true, ++ "⇈": true, ++ "⌝": true, ++ "⌝": true, ++ "⌎": true, ++ "ů": true, ++ "◹": true, ++ "𝓊": true, ++ "⋰": true, ++ "ũ": true, ++ "▵": true, ++ "▴": true, ++ "⇈": true, ++ "ü": true, ++ "ü": true, ++ "⦧": true, ++ "⇕": true, ++ "⫨": true, ++ "⫩": true, ++ "⊨": true, ++ "⦜": true, ++ "ϵ": true, ++ "ϰ": true, ++ "∅": true, ++ "ϕ": true, ++ "ϖ": true, ++ "∝": true, ++ "↕": true, ++ "ϱ": true, ++ "ς": true, ++ "⊊︀": true, ++ "⫋︀": true, ++ "⊋︀": true, ++ "⫌︀": true, ++ "ϑ": true, ++ "⊲": true, ++ "⊳": true, ++ "в": true, ++ "⊢": true, ++ "∨": true, ++ "⊻": true, ++ "≚": true, ++ "⋮": true, ++ "|": true, ++ "|": true, ++ "𝔳": true, ++ "⊲": true, ++ "⊂⃒": true, ++ "⊃⃒": true, ++ "𝕧": true, ++ "∝": true, ++ "⊳": true, ++ "𝓋": true, ++ "⫋︀": true, ++ "⊊︀": true, ++ "⫌︀": true, ++ "⊋︀": true, ++ "⦚": true, ++ "ŵ": true, ++ "⩟": true, ++ "∧": true, ++ "≙": true, ++ "℘": true, ++ "𝔴": true, ++ "𝕨": true, ++ "℘": true, ++ "≀": true, ++ "≀": true, ++ "𝓌": true, ++ "⋂": true, ++ "◯": true, ++ "⋃": true, ++ "▽": true, ++ "𝔵": true, ++ "⟺": true, ++ "⟷": true, ++ "ξ": true, ++ "⟸": true, ++ "⟵": true, ++ "⟼": true, ++ "⋻": true, ++ "⨀": true, ++ "𝕩": true, ++ "⨁": true, ++ "⨂": true, ++ "⟹": true, ++ "⟶": true, ++ "𝓍": true, ++ "⨆": true, ++ "⨄": true, ++ "△": true, ++ "⋁": true, ++ "⋀": true, ++ "ý": true, ++ "ý": true, ++ "я": true, ++ "ŷ": true, ++ "ы": true, ++ "¥": true, ++ "¥": true, ++ "𝔶": true, ++ "ї": true, ++ "𝕪": true, ++ "𝓎": true, ++ "ю": true, ++ "ÿ": true, ++ "ÿ": true, ++ "ź": true, ++ "ž": true, ++ "з": true, ++ "ż": true, ++ "ℨ": true, ++ "ζ": true, ++ "𝔷": true, ++ "ж": true, ++ "⇝": true, ++ "𝕫": true, ++ "𝓏": true, ++ "‍": true, ++ "‌": true, ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/esc.go b/vendor/github.com/russross/blackfriday/v2/esc.go +new file mode 100644 +index 000000000000..6ab60102c9bf +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/esc.go +@@ -0,0 +1,70 @@ ++package blackfriday ++ ++import ( ++ "html" ++ "io" ++) ++ ++var htmlEscaper = [256][]byte{ ++ '&': []byte("&"), ++ '<': []byte("<"), ++ '>': []byte(">"), ++ '"': []byte("""), ++} ++ ++func escapeHTML(w io.Writer, s []byte) { ++ escapeEntities(w, s, false) ++} ++ ++func escapeAllHTML(w io.Writer, s []byte) { ++ escapeEntities(w, s, true) ++} ++ ++func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) { ++ var start, end int ++ for end < len(s) { ++ escSeq := htmlEscaper[s[end]] ++ if escSeq != nil { ++ isEntity, entityEnd := nodeIsEntity(s, end) ++ if isEntity && !escapeValidEntities { ++ w.Write(s[start : entityEnd+1]) ++ start = entityEnd + 1 ++ } else { ++ w.Write(s[start:end]) ++ w.Write(escSeq) ++ start = end + 1 ++ } ++ } ++ end++ ++ } ++ if start < len(s) && end <= len(s) { ++ w.Write(s[start:end]) ++ } ++} ++ ++func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) { ++ isEntity = false ++ endEntityPos = end + 1 ++ ++ if s[end] == '&' { ++ for endEntityPos < len(s) { ++ if s[endEntityPos] == ';' { ++ if entities[string(s[end:endEntityPos+1])] { ++ isEntity = true ++ break ++ } ++ } ++ if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' { ++ break ++ } ++ endEntityPos++ ++ } ++ } ++ ++ return isEntity, endEntityPos ++} ++ ++func escLink(w io.Writer, text []byte) { ++ unesc := html.UnescapeString(string(text)) ++ escapeHTML(w, []byte(unesc)) ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/html.go b/vendor/github.com/russross/blackfriday/v2/html.go +new file mode 100644 +index 000000000000..cb4f26e30fd5 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/html.go +@@ -0,0 +1,952 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// ++// HTML rendering backend ++// ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "regexp" ++ "strings" ++) ++ ++// HTMLFlags control optional behavior of HTML renderer. ++type HTMLFlags int ++ ++// HTML renderer configuration options. ++const ( ++ HTMLFlagsNone HTMLFlags = 0 ++ SkipHTML HTMLFlags = 1 << iota // Skip preformatted HTML blocks ++ SkipImages // Skip embedded images ++ SkipLinks // Skip all links ++ Safelink // Only link to trusted protocols ++ NofollowLinks // Only link with rel="nofollow" ++ NoreferrerLinks // Only link with rel="noreferrer" ++ NoopenerLinks // Only link with rel="noopener" ++ HrefTargetBlank // Add a blank target ++ CompletePage // Generate a complete HTML page ++ UseXHTML // Generate XHTML output instead of HTML ++ FootnoteReturnLinks // Generate a link at the end of a footnote to return to the source ++ Smartypants // Enable smart punctuation substitutions ++ SmartypantsFractions // Enable smart fractions (with Smartypants) ++ SmartypantsDashes // Enable smart dashes (with Smartypants) ++ SmartypantsLatexDashes // Enable LaTeX-style dashes (with Smartypants) ++ SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering ++ SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants) ++ TOC // Generate a table of contents ++) ++ ++var ( ++ htmlTagRe = regexp.MustCompile("(?i)^" + htmlTag) ++) ++ ++const ( ++ htmlTag = "(?:" + openTag + "|" + closeTag + "|" + htmlComment + "|" + ++ processingInstruction + "|" + declaration + "|" + cdata + ")" ++ closeTag = "]" ++ openTag = "<" + tagName + attribute + "*" + "\\s*/?>" ++ attribute = "(?:" + "\\s+" + attributeName + attributeValueSpec + "?)" ++ attributeValue = "(?:" + unquotedValue + "|" + singleQuotedValue + "|" + doubleQuotedValue + ")" ++ attributeValueSpec = "(?:" + "\\s*=" + "\\s*" + attributeValue + ")" ++ attributeName = "[a-zA-Z_:][a-zA-Z0-9:._-]*" ++ cdata = "" ++ declaration = "]*>" ++ doubleQuotedValue = "\"[^\"]*\"" ++ htmlComment = "|" ++ processingInstruction = "[<][?].*?[?][>]" ++ singleQuotedValue = "'[^']*'" ++ tagName = "[A-Za-z][A-Za-z0-9-]*" ++ unquotedValue = "[^\"'=<>`\\x00-\\x20]+" ++) ++ ++// HTMLRendererParameters is a collection of supplementary parameters tweaking ++// the behavior of various parts of HTML renderer. ++type HTMLRendererParameters struct { ++ // Prepend this text to each relative URL. ++ AbsolutePrefix string ++ // Add this text to each footnote anchor, to ensure uniqueness. ++ FootnoteAnchorPrefix string ++ // Show this text inside the tag for a footnote return link, if the ++ // HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string ++ // [return] is used. ++ FootnoteReturnLinkContents string ++ // If set, add this text to the front of each Heading ID, to ensure ++ // uniqueness. ++ HeadingIDPrefix string ++ // If set, add this text to the back of each Heading ID, to ensure uniqueness. ++ HeadingIDSuffix string ++ // Increase heading levels: if the offset is 1,

becomes

etc. ++ // Negative offset is also valid. ++ // Resulting levels are clipped between 1 and 6. ++ HeadingLevelOffset int ++ ++ Title string // Document title (used if CompletePage is set) ++ CSS string // Optional CSS file URL (used if CompletePage is set) ++ Icon string // Optional icon file URL (used if CompletePage is set) ++ ++ Flags HTMLFlags // Flags allow customizing this renderer's behavior ++} ++ ++// HTMLRenderer is a type that implements the Renderer interface for HTML output. ++// ++// Do not create this directly, instead use the NewHTMLRenderer function. ++type HTMLRenderer struct { ++ HTMLRendererParameters ++ ++ closeTag string // how to end singleton tags: either " />" or ">" ++ ++ // Track heading IDs to prevent ID collision in a single generation. ++ headingIDs map[string]int ++ ++ lastOutputLen int ++ disableTags int ++ ++ sr *SPRenderer ++} ++ ++const ( ++ xhtmlClose = " />" ++ htmlClose = ">" ++) ++ ++// NewHTMLRenderer creates and configures an HTMLRenderer object, which ++// satisfies the Renderer interface. ++func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer { ++ // configure the rendering engine ++ closeTag := htmlClose ++ if params.Flags&UseXHTML != 0 { ++ closeTag = xhtmlClose ++ } ++ ++ if params.FootnoteReturnLinkContents == "" { ++ // U+FE0E is VARIATION SELECTOR-15. ++ // It suppresses automatic emoji presentation of the preceding ++ // U+21A9 LEFTWARDS ARROW WITH HOOK on iOS and iPadOS. ++ params.FootnoteReturnLinkContents = "↩\ufe0e" ++ } ++ ++ return &HTMLRenderer{ ++ HTMLRendererParameters: params, ++ ++ closeTag: closeTag, ++ headingIDs: make(map[string]int), ++ ++ sr: NewSmartypantsRenderer(params.Flags), ++ } ++} ++ ++func isHTMLTag(tag []byte, tagname string) bool { ++ found, _ := findHTMLTagPos(tag, tagname) ++ return found ++} ++ ++// Look for a character, but ignore it when it's in any kind of quotes, it ++// might be JavaScript ++func skipUntilCharIgnoreQuotes(html []byte, start int, char byte) int { ++ inSingleQuote := false ++ inDoubleQuote := false ++ inGraveQuote := false ++ i := start ++ for i < len(html) { ++ switch { ++ case html[i] == char && !inSingleQuote && !inDoubleQuote && !inGraveQuote: ++ return i ++ case html[i] == '\'': ++ inSingleQuote = !inSingleQuote ++ case html[i] == '"': ++ inDoubleQuote = !inDoubleQuote ++ case html[i] == '`': ++ inGraveQuote = !inGraveQuote ++ } ++ i++ ++ } ++ return start ++} ++ ++func findHTMLTagPos(tag []byte, tagname string) (bool, int) { ++ i := 0 ++ if i < len(tag) && tag[0] != '<' { ++ return false, -1 ++ } ++ i++ ++ i = skipSpace(tag, i) ++ ++ if i < len(tag) && tag[i] == '/' { ++ i++ ++ } ++ ++ i = skipSpace(tag, i) ++ j := 0 ++ for ; i < len(tag); i, j = i+1, j+1 { ++ if j >= len(tagname) { ++ break ++ } ++ ++ if strings.ToLower(string(tag[i]))[0] != tagname[j] { ++ return false, -1 ++ } ++ } ++ ++ if i == len(tag) { ++ return false, -1 ++ } ++ ++ rightAngle := skipUntilCharIgnoreQuotes(tag, i, '>') ++ if rightAngle >= i { ++ return true, rightAngle ++ } ++ ++ return false, -1 ++} ++ ++func skipSpace(tag []byte, i int) int { ++ for i < len(tag) && isspace(tag[i]) { ++ i++ ++ } ++ return i ++} ++ ++func isRelativeLink(link []byte) (yes bool) { ++ // a tag begin with '#' ++ if link[0] == '#' { ++ return true ++ } ++ ++ // link begin with '/' but not '//', the second maybe a protocol relative link ++ if len(link) >= 2 && link[0] == '/' && link[1] != '/' { ++ return true ++ } ++ ++ // only the root '/' ++ if len(link) == 1 && link[0] == '/' { ++ return true ++ } ++ ++ // current directory : begin with "./" ++ if bytes.HasPrefix(link, []byte("./")) { ++ return true ++ } ++ ++ // parent directory : begin with "../" ++ if bytes.HasPrefix(link, []byte("../")) { ++ return true ++ } ++ ++ return false ++} ++ ++func (r *HTMLRenderer) ensureUniqueHeadingID(id string) string { ++ for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] { ++ tmp := fmt.Sprintf("%s-%d", id, count+1) ++ ++ if _, tmpFound := r.headingIDs[tmp]; !tmpFound { ++ r.headingIDs[id] = count + 1 ++ id = tmp ++ } else { ++ id = id + "-1" ++ } ++ } ++ ++ if _, found := r.headingIDs[id]; !found { ++ r.headingIDs[id] = 0 ++ } ++ ++ return id ++} ++ ++func (r *HTMLRenderer) addAbsPrefix(link []byte) []byte { ++ if r.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' { ++ newDest := r.AbsolutePrefix ++ if link[0] != '/' { ++ newDest += "/" ++ } ++ newDest += string(link) ++ return []byte(newDest) ++ } ++ return link ++} ++ ++func appendLinkAttrs(attrs []string, flags HTMLFlags, link []byte) []string { ++ if isRelativeLink(link) { ++ return attrs ++ } ++ val := []string{} ++ if flags&NofollowLinks != 0 { ++ val = append(val, "nofollow") ++ } ++ if flags&NoreferrerLinks != 0 { ++ val = append(val, "noreferrer") ++ } ++ if flags&NoopenerLinks != 0 { ++ val = append(val, "noopener") ++ } ++ if flags&HrefTargetBlank != 0 { ++ attrs = append(attrs, "target=\"_blank\"") ++ } ++ if len(val) == 0 { ++ return attrs ++ } ++ attr := fmt.Sprintf("rel=%q", strings.Join(val, " ")) ++ return append(attrs, attr) ++} ++ ++func isMailto(link []byte) bool { ++ return bytes.HasPrefix(link, []byte("mailto:")) ++} ++ ++func needSkipLink(flags HTMLFlags, dest []byte) bool { ++ if flags&SkipLinks != 0 { ++ return true ++ } ++ return flags&Safelink != 0 && !isSafeLink(dest) && !isMailto(dest) ++} ++ ++func isSmartypantable(node *Node) bool { ++ pt := node.Parent.Type ++ return pt != Link && pt != CodeBlock && pt != Code ++} ++ ++func appendLanguageAttr(attrs []string, info []byte) []string { ++ if len(info) == 0 { ++ return attrs ++ } ++ endOfLang := bytes.IndexAny(info, "\t ") ++ if endOfLang < 0 { ++ endOfLang = len(info) ++ } ++ return append(attrs, fmt.Sprintf("class=\"language-%s\"", info[:endOfLang])) ++} ++ ++func (r *HTMLRenderer) tag(w io.Writer, name []byte, attrs []string) { ++ w.Write(name) ++ if len(attrs) > 0 { ++ w.Write(spaceBytes) ++ w.Write([]byte(strings.Join(attrs, " "))) ++ } ++ w.Write(gtBytes) ++ r.lastOutputLen = 1 ++} ++ ++func footnoteRef(prefix string, node *Node) []byte { ++ urlFrag := prefix + string(slugify(node.Destination)) ++ anchor := fmt.Sprintf(`%d`, urlFrag, node.NoteID) ++ return []byte(fmt.Sprintf(`%s`, urlFrag, anchor)) ++} ++ ++func footnoteItem(prefix string, slug []byte) []byte { ++ return []byte(fmt.Sprintf(`
  • `, prefix, slug)) ++} ++ ++func footnoteReturnLink(prefix, returnLink string, slug []byte) []byte { ++ const format = ` %s` ++ return []byte(fmt.Sprintf(format, prefix, slug, returnLink)) ++} ++ ++func itemOpenCR(node *Node) bool { ++ if node.Prev == nil { ++ return false ++ } ++ ld := node.Parent.ListData ++ return !ld.Tight && ld.ListFlags&ListTypeDefinition == 0 ++} ++ ++func skipParagraphTags(node *Node) bool { ++ grandparent := node.Parent.Parent ++ if grandparent == nil || grandparent.Type != List { ++ return false ++ } ++ tightOrTerm := grandparent.Tight || node.Parent.ListFlags&ListTypeTerm != 0 ++ return grandparent.Type == List && tightOrTerm ++} ++ ++func cellAlignment(align CellAlignFlags) string { ++ switch align { ++ case TableAlignmentLeft: ++ return "left" ++ case TableAlignmentRight: ++ return "right" ++ case TableAlignmentCenter: ++ return "center" ++ default: ++ return "" ++ } ++} ++ ++func (r *HTMLRenderer) out(w io.Writer, text []byte) { ++ if r.disableTags > 0 { ++ w.Write(htmlTagRe.ReplaceAll(text, []byte{})) ++ } else { ++ w.Write(text) ++ } ++ r.lastOutputLen = len(text) ++} ++ ++func (r *HTMLRenderer) cr(w io.Writer) { ++ if r.lastOutputLen > 0 { ++ r.out(w, nlBytes) ++ } ++} ++ ++var ( ++ nlBytes = []byte{'\n'} ++ gtBytes = []byte{'>'} ++ spaceBytes = []byte{' '} ++) ++ ++var ( ++ brTag = []byte("
    ") ++ brXHTMLTag = []byte("
    ") ++ emTag = []byte("") ++ emCloseTag = []byte("") ++ strongTag = []byte("") ++ strongCloseTag = []byte("") ++ delTag = []byte("") ++ delCloseTag = []byte("") ++ ttTag = []byte("") ++ ttCloseTag = []byte("") ++ aTag = []byte("") ++ preTag = []byte("
    ")
    ++	preCloseTag        = []byte("
    ") ++ codeTag = []byte("") ++ codeCloseTag = []byte("") ++ pTag = []byte("

    ") ++ pCloseTag = []byte("

    ") ++ blockquoteTag = []byte("
    ") ++ blockquoteCloseTag = []byte("
    ") ++ hrTag = []byte("
    ") ++ hrXHTMLTag = []byte("
    ") ++ ulTag = []byte("
      ") ++ ulCloseTag = []byte("
    ") ++ olTag = []byte("
      ") ++ olCloseTag = []byte("
    ") ++ dlTag = []byte("
    ") ++ dlCloseTag = []byte("
    ") ++ liTag = []byte("
  • ") ++ liCloseTag = []byte("
  • ") ++ ddTag = []byte("
    ") ++ ddCloseTag = []byte("
    ") ++ dtTag = []byte("
    ") ++ dtCloseTag = []byte("
    ") ++ tableTag = []byte("") ++ tableCloseTag = []byte("
    ") ++ tdTag = []byte("") ++ thTag = []byte("") ++ theadTag = []byte("") ++ theadCloseTag = []byte("") ++ tbodyTag = []byte("") ++ tbodyCloseTag = []byte("") ++ trTag = []byte("") ++ trCloseTag = []byte("") ++ h1Tag = []byte("") ++ h2Tag = []byte("") ++ h3Tag = []byte("") ++ h4Tag = []byte("") ++ h5Tag = []byte("") ++ h6Tag = []byte("") ++ ++ footnotesDivBytes = []byte("\n
    \n\n") ++ footnotesCloseDivBytes = []byte("\n
    \n") ++) ++ ++func headingTagsFromLevel(level int) ([]byte, []byte) { ++ if level <= 1 { ++ return h1Tag, h1CloseTag ++ } ++ switch level { ++ case 2: ++ return h2Tag, h2CloseTag ++ case 3: ++ return h3Tag, h3CloseTag ++ case 4: ++ return h4Tag, h4CloseTag ++ case 5: ++ return h5Tag, h5CloseTag ++ } ++ return h6Tag, h6CloseTag ++} ++ ++func (r *HTMLRenderer) outHRTag(w io.Writer) { ++ if r.Flags&UseXHTML == 0 { ++ r.out(w, hrTag) ++ } else { ++ r.out(w, hrXHTMLTag) ++ } ++} ++ ++// RenderNode is a default renderer of a single node of a syntax tree. For ++// block nodes it will be called twice: first time with entering=true, second ++// time with entering=false, so that it could know when it's working on an open ++// tag and when on close. It writes the result to w. ++// ++// The return value is a way to tell the calling walker to adjust its walk ++// pattern: e.g. it can terminate the traversal by returning Terminate. Or it ++// can ask the walker to skip a subtree of this node by returning SkipChildren. ++// The typical behavior is to return GoToNext, which asks for the usual ++// traversal to the next node. ++func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkStatus { ++ attrs := []string{} ++ switch node.Type { ++ case Text: ++ if r.Flags&Smartypants != 0 { ++ var tmp bytes.Buffer ++ escapeHTML(&tmp, node.Literal) ++ r.sr.Process(w, tmp.Bytes()) ++ } else { ++ if node.Parent.Type == Link { ++ escLink(w, node.Literal) ++ } else { ++ escapeHTML(w, node.Literal) ++ } ++ } ++ case Softbreak: ++ r.cr(w) ++ // TODO: make it configurable via out(renderer.softbreak) ++ case Hardbreak: ++ if r.Flags&UseXHTML == 0 { ++ r.out(w, brTag) ++ } else { ++ r.out(w, brXHTMLTag) ++ } ++ r.cr(w) ++ case Emph: ++ if entering { ++ r.out(w, emTag) ++ } else { ++ r.out(w, emCloseTag) ++ } ++ case Strong: ++ if entering { ++ r.out(w, strongTag) ++ } else { ++ r.out(w, strongCloseTag) ++ } ++ case Del: ++ if entering { ++ r.out(w, delTag) ++ } else { ++ r.out(w, delCloseTag) ++ } ++ case HTMLSpan: ++ if r.Flags&SkipHTML != 0 { ++ break ++ } ++ r.out(w, node.Literal) ++ case Link: ++ // mark it but don't link it if it is not a safe link: no smartypants ++ dest := node.LinkData.Destination ++ if needSkipLink(r.Flags, dest) { ++ if entering { ++ r.out(w, ttTag) ++ } else { ++ r.out(w, ttCloseTag) ++ } ++ } else { ++ if entering { ++ dest = r.addAbsPrefix(dest) ++ var hrefBuf bytes.Buffer ++ hrefBuf.WriteString("href=\"") ++ escLink(&hrefBuf, dest) ++ hrefBuf.WriteByte('"') ++ attrs = append(attrs, hrefBuf.String()) ++ if node.NoteID != 0 { ++ r.out(w, footnoteRef(r.FootnoteAnchorPrefix, node)) ++ break ++ } ++ attrs = appendLinkAttrs(attrs, r.Flags, dest) ++ if len(node.LinkData.Title) > 0 { ++ var titleBuff bytes.Buffer ++ titleBuff.WriteString("title=\"") ++ escapeHTML(&titleBuff, node.LinkData.Title) ++ titleBuff.WriteByte('"') ++ attrs = append(attrs, titleBuff.String()) ++ } ++ r.tag(w, aTag, attrs) ++ } else { ++ if node.NoteID != 0 { ++ break ++ } ++ r.out(w, aCloseTag) ++ } ++ } ++ case Image: ++ if r.Flags&SkipImages != 0 { ++ return SkipChildren ++ } ++ if entering { ++ dest := node.LinkData.Destination ++ dest = r.addAbsPrefix(dest) ++ if r.disableTags == 0 { ++ //if options.safe && potentiallyUnsafe(dest) { ++ //out(w, ``)
++				//} else {
++				r.out(w, []byte(`<img src=`)) ++ } ++ } ++ case Code: ++ r.out(w, codeTag) ++ escapeAllHTML(w, node.Literal) ++ r.out(w, codeCloseTag) ++ case Document: ++ break ++ case Paragraph: ++ if skipParagraphTags(node) { ++ break ++ } ++ if entering { ++ // TODO: untangle this clusterfuck about when the newlines need ++ // to be added and when not. ++ if node.Prev != nil { ++ switch node.Prev.Type { ++ case HTMLBlock, List, Paragraph, Heading, CodeBlock, BlockQuote, HorizontalRule: ++ r.cr(w) ++ } ++ } ++ if node.Parent.Type == BlockQuote && node.Prev == nil { ++ r.cr(w) ++ } ++ r.out(w, pTag) ++ } else { ++ r.out(w, pCloseTag) ++ if !(node.Parent.Type == Item && node.Next == nil) { ++ r.cr(w) ++ } ++ } ++ case BlockQuote: ++ if entering { ++ r.cr(w) ++ r.out(w, blockquoteTag) ++ } else { ++ r.out(w, blockquoteCloseTag) ++ r.cr(w) ++ } ++ case HTMLBlock: ++ if r.Flags&SkipHTML != 0 { ++ break ++ } ++ r.cr(w) ++ r.out(w, node.Literal) ++ r.cr(w) ++ case Heading: ++ headingLevel := r.HTMLRendererParameters.HeadingLevelOffset + node.Level ++ openTag, closeTag := headingTagsFromLevel(headingLevel) ++ if entering { ++ if node.IsTitleblock { ++ attrs = append(attrs, `class="title"`) ++ } ++ if node.HeadingID != "" { ++ id := r.ensureUniqueHeadingID(node.HeadingID) ++ if r.HeadingIDPrefix != "" { ++ id = r.HeadingIDPrefix + id ++ } ++ if r.HeadingIDSuffix != "" { ++ id = id + r.HeadingIDSuffix ++ } ++ attrs = append(attrs, fmt.Sprintf(`id="%s"`, id)) ++ } ++ r.cr(w) ++ r.tag(w, openTag, attrs) ++ } else { ++ r.out(w, closeTag) ++ if !(node.Parent.Type == Item && node.Next == nil) { ++ r.cr(w) ++ } ++ } ++ case HorizontalRule: ++ r.cr(w) ++ r.outHRTag(w) ++ r.cr(w) ++ case List: ++ openTag := ulTag ++ closeTag := ulCloseTag ++ if node.ListFlags&ListTypeOrdered != 0 { ++ openTag = olTag ++ closeTag = olCloseTag ++ } ++ if node.ListFlags&ListTypeDefinition != 0 { ++ openTag = dlTag ++ closeTag = dlCloseTag ++ } ++ if entering { ++ if node.IsFootnotesList { ++ r.out(w, footnotesDivBytes) ++ r.outHRTag(w) ++ r.cr(w) ++ } ++ r.cr(w) ++ if node.Parent.Type == Item && node.Parent.Parent.Tight { ++ r.cr(w) ++ } ++ r.tag(w, openTag[:len(openTag)-1], attrs) ++ r.cr(w) ++ } else { ++ r.out(w, closeTag) ++ //cr(w) ++ //if node.parent.Type != Item { ++ // cr(w) ++ //} ++ if node.Parent.Type == Item && node.Next != nil { ++ r.cr(w) ++ } ++ if node.Parent.Type == Document || node.Parent.Type == BlockQuote { ++ r.cr(w) ++ } ++ if node.IsFootnotesList { ++ r.out(w, footnotesCloseDivBytes) ++ } ++ } ++ case Item: ++ openTag := liTag ++ closeTag := liCloseTag ++ if node.ListFlags&ListTypeDefinition != 0 { ++ openTag = ddTag ++ closeTag = ddCloseTag ++ } ++ if node.ListFlags&ListTypeTerm != 0 { ++ openTag = dtTag ++ closeTag = dtCloseTag ++ } ++ if entering { ++ if itemOpenCR(node) { ++ r.cr(w) ++ } ++ if node.ListData.RefLink != nil { ++ slug := slugify(node.ListData.RefLink) ++ r.out(w, footnoteItem(r.FootnoteAnchorPrefix, slug)) ++ break ++ } ++ r.out(w, openTag) ++ } else { ++ if node.ListData.RefLink != nil { ++ slug := slugify(node.ListData.RefLink) ++ if r.Flags&FootnoteReturnLinks != 0 { ++ r.out(w, footnoteReturnLink(r.FootnoteAnchorPrefix, r.FootnoteReturnLinkContents, slug)) ++ } ++ } ++ r.out(w, closeTag) ++ r.cr(w) ++ } ++ case CodeBlock: ++ attrs = appendLanguageAttr(attrs, node.Info) ++ r.cr(w) ++ r.out(w, preTag) ++ r.tag(w, codeTag[:len(codeTag)-1], attrs) ++ escapeAllHTML(w, node.Literal) ++ r.out(w, codeCloseTag) ++ r.out(w, preCloseTag) ++ if node.Parent.Type != Item { ++ r.cr(w) ++ } ++ case Table: ++ if entering { ++ r.cr(w) ++ r.out(w, tableTag) ++ } else { ++ r.out(w, tableCloseTag) ++ r.cr(w) ++ } ++ case TableCell: ++ openTag := tdTag ++ closeTag := tdCloseTag ++ if node.IsHeader { ++ openTag = thTag ++ closeTag = thCloseTag ++ } ++ if entering { ++ align := cellAlignment(node.Align) ++ if align != "" { ++ attrs = append(attrs, fmt.Sprintf(`align="%s"`, align)) ++ } ++ if node.Prev == nil { ++ r.cr(w) ++ } ++ r.tag(w, openTag, attrs) ++ } else { ++ r.out(w, closeTag) ++ r.cr(w) ++ } ++ case TableHead: ++ if entering { ++ r.cr(w) ++ r.out(w, theadTag) ++ } else { ++ r.out(w, theadCloseTag) ++ r.cr(w) ++ } ++ case TableBody: ++ if entering { ++ r.cr(w) ++ r.out(w, tbodyTag) ++ // XXX: this is to adhere to a rather silly test. Should fix test. ++ if node.FirstChild == nil { ++ r.cr(w) ++ } ++ } else { ++ r.out(w, tbodyCloseTag) ++ r.cr(w) ++ } ++ case TableRow: ++ if entering { ++ r.cr(w) ++ r.out(w, trTag) ++ } else { ++ r.out(w, trCloseTag) ++ r.cr(w) ++ } ++ default: ++ panic("Unknown node type " + node.Type.String()) ++ } ++ return GoToNext ++} ++ ++// RenderHeader writes HTML document preamble and TOC if requested. ++func (r *HTMLRenderer) RenderHeader(w io.Writer, ast *Node) { ++ r.writeDocumentHeader(w) ++ if r.Flags&TOC != 0 { ++ r.writeTOC(w, ast) ++ } ++} ++ ++// RenderFooter writes HTML document footer. ++func (r *HTMLRenderer) RenderFooter(w io.Writer, ast *Node) { ++ if r.Flags&CompletePage == 0 { ++ return ++ } ++ io.WriteString(w, "\n\n\n") ++} ++ ++func (r *HTMLRenderer) writeDocumentHeader(w io.Writer) { ++ if r.Flags&CompletePage == 0 { ++ return ++ } ++ ending := "" ++ if r.Flags&UseXHTML != 0 { ++ io.WriteString(w, "\n") ++ io.WriteString(w, "\n") ++ ending = " /" ++ } else { ++ io.WriteString(w, "\n") ++ io.WriteString(w, "\n") ++ } ++ io.WriteString(w, "\n") ++ io.WriteString(w, " ") ++ if r.Flags&Smartypants != 0 { ++ r.sr.Process(w, []byte(r.Title)) ++ } else { ++ escapeHTML(w, []byte(r.Title)) ++ } ++ io.WriteString(w, "\n") ++ io.WriteString(w, " \n") ++ io.WriteString(w, " \n") ++ if r.CSS != "" { ++ io.WriteString(w, " \n") ++ } ++ if r.Icon != "" { ++ io.WriteString(w, " \n") ++ } ++ io.WriteString(w, "\n") ++ io.WriteString(w, "\n\n") ++} ++ ++func (r *HTMLRenderer) writeTOC(w io.Writer, ast *Node) { ++ buf := bytes.Buffer{} ++ ++ inHeading := false ++ tocLevel := 0 ++ headingCount := 0 ++ ++ ast.Walk(func(node *Node, entering bool) WalkStatus { ++ if node.Type == Heading && !node.HeadingData.IsTitleblock { ++ inHeading = entering ++ if entering { ++ node.HeadingID = fmt.Sprintf("toc_%d", headingCount) ++ if node.Level == tocLevel { ++ buf.WriteString("\n\n
  • ") ++ } else if node.Level < tocLevel { ++ for node.Level < tocLevel { ++ tocLevel-- ++ buf.WriteString("
  • \n") ++ } ++ buf.WriteString("\n\n
  • ") ++ } else { ++ for node.Level > tocLevel { ++ tocLevel++ ++ buf.WriteString("\n") ++ } ++ ++ if buf.Len() > 0 { ++ io.WriteString(w, "\n") ++ } ++ r.lastOutputLen = buf.Len() ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/inline.go b/vendor/github.com/russross/blackfriday/v2/inline.go +new file mode 100644 +index 000000000000..d45bd941726e +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/inline.go +@@ -0,0 +1,1228 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// Functions to parse inline elements. ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "regexp" ++ "strconv" ++) ++ ++var ( ++ urlRe = `((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+` ++ anchorRe = regexp.MustCompile(`^(]+")?\s?>` + urlRe + `<\/a>)`) ++ ++ // https://www.w3.org/TR/html5/syntax.html#character-references ++ // highest unicode code point in 17 planes (2^20): 1,114,112d = ++ // 7 dec digits or 6 hex digits ++ // named entity references can be 2-31 characters with stuff like < ++ // at one end and ∳ at the other. There ++ // are also sometimes numbers at the end, although this isn't inherent ++ // in the specification; there are never numbers anywhere else in ++ // current character references, though; see ¾ and ▒, etc. ++ // https://www.w3.org/TR/html5/syntax.html#named-character-references ++ // ++ // entity := "&" (named group | number ref) ";" ++ // named group := [a-zA-Z]{2,31}[0-9]{0,2} ++ // number ref := "#" (dec ref | hex ref) ++ // dec ref := [0-9]{1,7} ++ // hex ref := ("x" | "X") [0-9a-fA-F]{1,6} ++ htmlEntityRe = regexp.MustCompile(`&([a-zA-Z]{2,31}[0-9]{0,2}|#([0-9]{1,7}|[xX][0-9a-fA-F]{1,6}));`) ++) ++ ++// Functions to parse text within a block ++// Each function returns the number of chars taken care of ++// data is the complete block being rendered ++// offset is the number of valid chars before the current cursor ++ ++func (p *Markdown) inline(currBlock *Node, data []byte) { ++ // handlers might call us recursively: enforce a maximum depth ++ if p.nesting >= p.maxNesting || len(data) == 0 { ++ return ++ } ++ p.nesting++ ++ beg, end := 0, 0 ++ for end < len(data) { ++ handler := p.inlineCallback[data[end]] ++ if handler != nil { ++ if consumed, node := handler(p, data, end); consumed == 0 { ++ // No action from the callback. ++ end++ ++ } else { ++ // Copy inactive chars into the output. ++ currBlock.AppendChild(text(data[beg:end])) ++ if node != nil { ++ currBlock.AppendChild(node) ++ } ++ // Skip past whatever the callback used. ++ beg = end + consumed ++ end = beg ++ } ++ } else { ++ end++ ++ } ++ } ++ if beg < len(data) { ++ if data[end-1] == '\n' { ++ end-- ++ } ++ currBlock.AppendChild(text(data[beg:end])) ++ } ++ p.nesting-- ++} ++ ++// single and double emphasis parsing ++func emphasis(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ c := data[0] ++ ++ if len(data) > 2 && data[1] != c { ++ // whitespace cannot follow an opening emphasis; ++ // strikethrough only takes two characters '~~' ++ if c == '~' || isspace(data[1]) { ++ return 0, nil ++ } ++ ret, node := helperEmphasis(p, data[1:], c) ++ if ret == 0 { ++ return 0, nil ++ } ++ ++ return ret + 1, node ++ } ++ ++ if len(data) > 3 && data[1] == c && data[2] != c { ++ if isspace(data[2]) { ++ return 0, nil ++ } ++ ret, node := helperDoubleEmphasis(p, data[2:], c) ++ if ret == 0 { ++ return 0, nil ++ } ++ ++ return ret + 2, node ++ } ++ ++ if len(data) > 4 && data[1] == c && data[2] == c && data[3] != c { ++ if c == '~' || isspace(data[3]) { ++ return 0, nil ++ } ++ ret, node := helperTripleEmphasis(p, data, 3, c) ++ if ret == 0 { ++ return 0, nil ++ } ++ ++ return ret + 3, node ++ } ++ ++ return 0, nil ++} ++ ++func codeSpan(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ ++ nb := 0 ++ ++ // count the number of backticks in the delimiter ++ for nb < len(data) && data[nb] == '`' { ++ nb++ ++ } ++ ++ // find the next delimiter ++ i, end := 0, 0 ++ for end = nb; end < len(data) && i < nb; end++ { ++ if data[end] == '`' { ++ i++ ++ } else { ++ i = 0 ++ } ++ } ++ ++ // no matching delimiter? ++ if i < nb && end >= len(data) { ++ return 0, nil ++ } ++ ++ // trim outside whitespace ++ fBegin := nb ++ for fBegin < end && data[fBegin] == ' ' { ++ fBegin++ ++ } ++ ++ fEnd := end - nb ++ for fEnd > fBegin && data[fEnd-1] == ' ' { ++ fEnd-- ++ } ++ ++ // render the code span ++ if fBegin != fEnd { ++ code := NewNode(Code) ++ code.Literal = data[fBegin:fEnd] ++ return end, code ++ } ++ ++ return end, nil ++} ++ ++// newline preceded by two spaces becomes
    ++func maybeLineBreak(p *Markdown, data []byte, offset int) (int, *Node) { ++ origOffset := offset ++ for offset < len(data) && data[offset] == ' ' { ++ offset++ ++ } ++ ++ if offset < len(data) && data[offset] == '\n' { ++ if offset-origOffset >= 2 { ++ return offset - origOffset + 1, NewNode(Hardbreak) ++ } ++ return offset - origOffset, nil ++ } ++ return 0, nil ++} ++ ++// newline without two spaces works when HardLineBreak is enabled ++func lineBreak(p *Markdown, data []byte, offset int) (int, *Node) { ++ if p.extensions&HardLineBreak != 0 { ++ return 1, NewNode(Hardbreak) ++ } ++ return 0, nil ++} ++ ++type linkType int ++ ++const ( ++ linkNormal linkType = iota ++ linkImg ++ linkDeferredFootnote ++ linkInlineFootnote ++) ++ ++func isReferenceStyleLink(data []byte, pos int, t linkType) bool { ++ if t == linkDeferredFootnote { ++ return false ++ } ++ return pos < len(data)-1 && data[pos] == '[' && data[pos+1] != '^' ++} ++ ++func maybeImage(p *Markdown, data []byte, offset int) (int, *Node) { ++ if offset < len(data)-1 && data[offset+1] == '[' { ++ return link(p, data, offset) ++ } ++ return 0, nil ++} ++ ++func maybeInlineFootnote(p *Markdown, data []byte, offset int) (int, *Node) { ++ if offset < len(data)-1 && data[offset+1] == '[' { ++ return link(p, data, offset) ++ } ++ return 0, nil ++} ++ ++// '[': parse a link or an image or a footnote ++func link(p *Markdown, data []byte, offset int) (int, *Node) { ++ // no links allowed inside regular links, footnote, and deferred footnotes ++ if p.insideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') { ++ return 0, nil ++ } ++ ++ var t linkType ++ switch { ++ // special case: ![^text] == deferred footnote (that follows something with ++ // an exclamation point) ++ case p.extensions&Footnotes != 0 && len(data)-1 > offset && data[offset+1] == '^': ++ t = linkDeferredFootnote ++ // ![alt] == image ++ case offset >= 0 && data[offset] == '!': ++ t = linkImg ++ offset++ ++ // ^[text] == inline footnote ++ // [^refId] == deferred footnote ++ case p.extensions&Footnotes != 0: ++ if offset >= 0 && data[offset] == '^' { ++ t = linkInlineFootnote ++ offset++ ++ } else if len(data)-1 > offset && data[offset+1] == '^' { ++ t = linkDeferredFootnote ++ } ++ // [text] == regular link ++ default: ++ t = linkNormal ++ } ++ ++ data = data[offset:] ++ ++ var ( ++ i = 1 ++ noteID int ++ title, link, altContent []byte ++ textHasNl = false ++ ) ++ ++ if t == linkDeferredFootnote { ++ i++ ++ } ++ ++ // look for the matching closing bracket ++ for level := 1; level > 0 && i < len(data); i++ { ++ switch { ++ case data[i] == '\n': ++ textHasNl = true ++ ++ case isBackslashEscaped(data, i): ++ continue ++ ++ case data[i] == '[': ++ level++ ++ ++ case data[i] == ']': ++ level-- ++ if level <= 0 { ++ i-- // compensate for extra i++ in for loop ++ } ++ } ++ } ++ ++ if i >= len(data) { ++ return 0, nil ++ } ++ ++ txtE := i ++ i++ ++ var footnoteNode *Node ++ ++ // skip any amount of whitespace or newline ++ // (this is much more lax than original markdown syntax) ++ for i < len(data) && isspace(data[i]) { ++ i++ ++ } ++ ++ // inline style link ++ switch { ++ case i < len(data) && data[i] == '(': ++ // skip initial whitespace ++ i++ ++ ++ for i < len(data) && isspace(data[i]) { ++ i++ ++ } ++ ++ linkB := i ++ ++ // look for link end: ' " ) ++ findlinkend: ++ for i < len(data) { ++ switch { ++ case data[i] == '\\': ++ i += 2 ++ ++ case data[i] == ')' || data[i] == '\'' || data[i] == '"': ++ break findlinkend ++ ++ default: ++ i++ ++ } ++ } ++ ++ if i >= len(data) { ++ return 0, nil ++ } ++ linkE := i ++ ++ // look for title end if present ++ titleB, titleE := 0, 0 ++ if data[i] == '\'' || data[i] == '"' { ++ i++ ++ titleB = i ++ ++ findtitleend: ++ for i < len(data) { ++ switch { ++ case data[i] == '\\': ++ i += 2 ++ ++ case data[i] == ')': ++ break findtitleend ++ ++ default: ++ i++ ++ } ++ } ++ ++ if i >= len(data) { ++ return 0, nil ++ } ++ ++ // skip whitespace after title ++ titleE = i - 1 ++ for titleE > titleB && isspace(data[titleE]) { ++ titleE-- ++ } ++ ++ // check for closing quote presence ++ if data[titleE] != '\'' && data[titleE] != '"' { ++ titleB, titleE = 0, 0 ++ linkE = i ++ } ++ } ++ ++ // remove whitespace at the end of the link ++ for linkE > linkB && isspace(data[linkE-1]) { ++ linkE-- ++ } ++ ++ // remove optional angle brackets around the link ++ if data[linkB] == '<' { ++ linkB++ ++ } ++ if data[linkE-1] == '>' { ++ linkE-- ++ } ++ ++ // build escaped link and title ++ if linkE > linkB { ++ link = data[linkB:linkE] ++ } ++ ++ if titleE > titleB { ++ title = data[titleB:titleE] ++ } ++ ++ i++ ++ ++ // reference style link ++ case isReferenceStyleLink(data, i, t): ++ var id []byte ++ altContentConsidered := false ++ ++ // look for the id ++ i++ ++ linkB := i ++ for i < len(data) && data[i] != ']' { ++ i++ ++ } ++ if i >= len(data) { ++ return 0, nil ++ } ++ linkE := i ++ ++ // find the reference ++ if linkB == linkE { ++ if textHasNl { ++ var b bytes.Buffer ++ ++ for j := 1; j < txtE; j++ { ++ switch { ++ case data[j] != '\n': ++ b.WriteByte(data[j]) ++ case data[j-1] != ' ': ++ b.WriteByte(' ') ++ } ++ } ++ ++ id = b.Bytes() ++ } else { ++ id = data[1:txtE] ++ altContentConsidered = true ++ } ++ } else { ++ id = data[linkB:linkE] ++ } ++ ++ // find the reference with matching id ++ lr, ok := p.getRef(string(id)) ++ if !ok { ++ return 0, nil ++ } ++ ++ // keep link and title from reference ++ link = lr.link ++ title = lr.title ++ if altContentConsidered { ++ altContent = lr.text ++ } ++ i++ ++ ++ // shortcut reference style link or reference or inline footnote ++ default: ++ var id []byte ++ ++ // craft the id ++ if textHasNl { ++ var b bytes.Buffer ++ ++ for j := 1; j < txtE; j++ { ++ switch { ++ case data[j] != '\n': ++ b.WriteByte(data[j]) ++ case data[j-1] != ' ': ++ b.WriteByte(' ') ++ } ++ } ++ ++ id = b.Bytes() ++ } else { ++ if t == linkDeferredFootnote { ++ id = data[2:txtE] // get rid of the ^ ++ } else { ++ id = data[1:txtE] ++ } ++ } ++ ++ footnoteNode = NewNode(Item) ++ if t == linkInlineFootnote { ++ // create a new reference ++ noteID = len(p.notes) + 1 ++ ++ var fragment []byte ++ if len(id) > 0 { ++ if len(id) < 16 { ++ fragment = make([]byte, len(id)) ++ } else { ++ fragment = make([]byte, 16) ++ } ++ copy(fragment, slugify(id)) ++ } else { ++ fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteID))...) ++ } ++ ++ ref := &reference{ ++ noteID: noteID, ++ hasBlock: false, ++ link: fragment, ++ title: id, ++ footnote: footnoteNode, ++ } ++ ++ p.notes = append(p.notes, ref) ++ ++ link = ref.link ++ title = ref.title ++ } else { ++ // find the reference with matching id ++ lr, ok := p.getRef(string(id)) ++ if !ok { ++ return 0, nil ++ } ++ ++ if t == linkDeferredFootnote { ++ lr.noteID = len(p.notes) + 1 ++ lr.footnote = footnoteNode ++ p.notes = append(p.notes, lr) ++ } ++ ++ // keep link and title from reference ++ link = lr.link ++ // if inline footnote, title == footnote contents ++ title = lr.title ++ noteID = lr.noteID ++ } ++ ++ // rewind the whitespace ++ i = txtE + 1 ++ } ++ ++ var uLink []byte ++ if t == linkNormal || t == linkImg { ++ if len(link) > 0 { ++ var uLinkBuf bytes.Buffer ++ unescapeText(&uLinkBuf, link) ++ uLink = uLinkBuf.Bytes() ++ } ++ ++ // links need something to click on and somewhere to go ++ if len(uLink) == 0 || (t == linkNormal && txtE <= 1) { ++ return 0, nil ++ } ++ } ++ ++ // call the relevant rendering function ++ var linkNode *Node ++ switch t { ++ case linkNormal: ++ linkNode = NewNode(Link) ++ linkNode.Destination = normalizeURI(uLink) ++ linkNode.Title = title ++ if len(altContent) > 0 { ++ linkNode.AppendChild(text(altContent)) ++ } else { ++ // links cannot contain other links, so turn off link parsing ++ // temporarily and recurse ++ insideLink := p.insideLink ++ p.insideLink = true ++ p.inline(linkNode, data[1:txtE]) ++ p.insideLink = insideLink ++ } ++ ++ case linkImg: ++ linkNode = NewNode(Image) ++ linkNode.Destination = uLink ++ linkNode.Title = title ++ linkNode.AppendChild(text(data[1:txtE])) ++ i++ ++ ++ case linkInlineFootnote, linkDeferredFootnote: ++ linkNode = NewNode(Link) ++ linkNode.Destination = link ++ linkNode.Title = title ++ linkNode.NoteID = noteID ++ linkNode.Footnote = footnoteNode ++ if t == linkInlineFootnote { ++ i++ ++ } ++ ++ default: ++ return 0, nil ++ } ++ ++ return i, linkNode ++} ++ ++func (p *Markdown) inlineHTMLComment(data []byte) int { ++ if len(data) < 5 { ++ return 0 ++ } ++ if data[0] != '<' || data[1] != '!' || data[2] != '-' || data[3] != '-' { ++ return 0 ++ } ++ i := 5 ++ // scan for an end-of-comment marker, across lines if necessary ++ for i < len(data) && !(data[i-2] == '-' && data[i-1] == '-' && data[i] == '>') { ++ i++ ++ } ++ // no end-of-comment marker ++ if i >= len(data) { ++ return 0 ++ } ++ return i + 1 ++} ++ ++func stripMailto(link []byte) []byte { ++ if bytes.HasPrefix(link, []byte("mailto://")) { ++ return link[9:] ++ } else if bytes.HasPrefix(link, []byte("mailto:")) { ++ return link[7:] ++ } else { ++ return link ++ } ++} ++ ++// autolinkType specifies a kind of autolink that gets detected. ++type autolinkType int ++ ++// These are the possible flag values for the autolink renderer. ++const ( ++ notAutolink autolinkType = iota ++ normalAutolink ++ emailAutolink ++) ++ ++// '<' when tags or autolinks are allowed ++func leftAngle(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ altype, end := tagLength(data) ++ if size := p.inlineHTMLComment(data); size > 0 { ++ end = size ++ } ++ if end > 2 { ++ if altype != notAutolink { ++ var uLink bytes.Buffer ++ unescapeText(&uLink, data[1:end+1-2]) ++ if uLink.Len() > 0 { ++ link := uLink.Bytes() ++ node := NewNode(Link) ++ node.Destination = link ++ if altype == emailAutolink { ++ node.Destination = append([]byte("mailto:"), link...) ++ } ++ node.AppendChild(text(stripMailto(link))) ++ return end, node ++ } ++ } else { ++ htmlTag := NewNode(HTMLSpan) ++ htmlTag.Literal = data[:end] ++ return end, htmlTag ++ } ++ } ++ ++ return end, nil ++} ++ ++// '\\' backslash escape ++var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~") ++ ++func escape(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ ++ if len(data) > 1 { ++ if p.extensions&BackslashLineBreak != 0 && data[1] == '\n' { ++ return 2, NewNode(Hardbreak) ++ } ++ if bytes.IndexByte(escapeChars, data[1]) < 0 { ++ return 0, nil ++ } ++ ++ return 2, text(data[1:2]) ++ } ++ ++ return 2, nil ++} ++ ++func unescapeText(ob *bytes.Buffer, src []byte) { ++ i := 0 ++ for i < len(src) { ++ org := i ++ for i < len(src) && src[i] != '\\' { ++ i++ ++ } ++ ++ if i > org { ++ ob.Write(src[org:i]) ++ } ++ ++ if i+1 >= len(src) { ++ break ++ } ++ ++ ob.WriteByte(src[i+1]) ++ i += 2 ++ } ++} ++ ++// '&' escaped when it doesn't belong to an entity ++// valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; ++func entity(p *Markdown, data []byte, offset int) (int, *Node) { ++ data = data[offset:] ++ ++ end := 1 ++ ++ if end < len(data) && data[end] == '#' { ++ end++ ++ } ++ ++ for end < len(data) && isalnum(data[end]) { ++ end++ ++ } ++ ++ if end < len(data) && data[end] == ';' { ++ end++ // real entity ++ } else { ++ return 0, nil // lone '&' ++ } ++ ++ ent := data[:end] ++ // undo & escaping or it will be converted to &amp; by another ++ // escaper in the renderer ++ if bytes.Equal(ent, []byte("&")) { ++ ent = []byte{'&'} ++ } ++ ++ return end, text(ent) ++} ++ ++func linkEndsWithEntity(data []byte, linkEnd int) bool { ++ entityRanges := htmlEntityRe.FindAllIndex(data[:linkEnd], -1) ++ return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd ++} ++ ++// hasPrefixCaseInsensitive is a custom implementation of ++// strings.HasPrefix(strings.ToLower(s), prefix) ++// we rolled our own because ToLower pulls in a huge machinery of lowercasing ++// anything from Unicode and that's very slow. Since this func will only be ++// used on ASCII protocol prefixes, we can take shortcuts. ++func hasPrefixCaseInsensitive(s, prefix []byte) bool { ++ if len(s) < len(prefix) { ++ return false ++ } ++ delta := byte('a' - 'A') ++ for i, b := range prefix { ++ if b != s[i] && b != s[i]+delta { ++ return false ++ } ++ } ++ return true ++} ++ ++var protocolPrefixes = [][]byte{ ++ []byte("http://"), ++ []byte("https://"), ++ []byte("ftp://"), ++ []byte("file://"), ++ []byte("mailto:"), ++} ++ ++const shortestPrefix = 6 // len("ftp://"), the shortest of the above ++ ++func maybeAutoLink(p *Markdown, data []byte, offset int) (int, *Node) { ++ // quick check to rule out most false hits ++ if p.insideLink || len(data) < offset+shortestPrefix { ++ return 0, nil ++ } ++ for _, prefix := range protocolPrefixes { ++ endOfHead := offset + 8 // 8 is the len() of the longest prefix ++ if endOfHead > len(data) { ++ endOfHead = len(data) ++ } ++ if hasPrefixCaseInsensitive(data[offset:endOfHead], prefix) { ++ return autoLink(p, data, offset) ++ } ++ } ++ return 0, nil ++} ++ ++func autoLink(p *Markdown, data []byte, offset int) (int, *Node) { ++ // Now a more expensive check to see if we're not inside an anchor element ++ anchorStart := offset ++ offsetFromAnchor := 0 ++ for anchorStart > 0 && data[anchorStart] != '<' { ++ anchorStart-- ++ offsetFromAnchor++ ++ } ++ ++ anchorStr := anchorRe.Find(data[anchorStart:]) ++ if anchorStr != nil { ++ anchorClose := NewNode(HTMLSpan) ++ anchorClose.Literal = anchorStr[offsetFromAnchor:] ++ return len(anchorStr) - offsetFromAnchor, anchorClose ++ } ++ ++ // scan backward for a word boundary ++ rewind := 0 ++ for offset-rewind > 0 && rewind <= 7 && isletter(data[offset-rewind-1]) { ++ rewind++ ++ } ++ if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters ++ return 0, nil ++ } ++ ++ origData := data ++ data = data[offset-rewind:] ++ ++ if !isSafeLink(data) { ++ return 0, nil ++ } ++ ++ linkEnd := 0 ++ for linkEnd < len(data) && !isEndOfLink(data[linkEnd]) { ++ linkEnd++ ++ } ++ ++ // Skip punctuation at the end of the link ++ if (data[linkEnd-1] == '.' || data[linkEnd-1] == ',') && data[linkEnd-2] != '\\' { ++ linkEnd-- ++ } ++ ++ // But don't skip semicolon if it's a part of escaped entity: ++ if data[linkEnd-1] == ';' && data[linkEnd-2] != '\\' && !linkEndsWithEntity(data, linkEnd) { ++ linkEnd-- ++ } ++ ++ // See if the link finishes with a punctuation sign that can be closed. ++ var copen byte ++ switch data[linkEnd-1] { ++ case '"': ++ copen = '"' ++ case '\'': ++ copen = '\'' ++ case ')': ++ copen = '(' ++ case ']': ++ copen = '[' ++ case '}': ++ copen = '{' ++ default: ++ copen = 0 ++ } ++ ++ if copen != 0 { ++ bufEnd := offset - rewind + linkEnd - 2 ++ ++ openDelim := 1 ++ ++ /* Try to close the final punctuation sign in this same line; ++ * if we managed to close it outside of the URL, that means that it's ++ * not part of the URL. If it closes inside the URL, that means it ++ * is part of the URL. ++ * ++ * Examples: ++ * ++ * foo http://www.pokemon.com/Pikachu_(Electric) bar ++ * => http://www.pokemon.com/Pikachu_(Electric) ++ * ++ * foo (http://www.pokemon.com/Pikachu_(Electric)) bar ++ * => http://www.pokemon.com/Pikachu_(Electric) ++ * ++ * foo http://www.pokemon.com/Pikachu_(Electric)) bar ++ * => http://www.pokemon.com/Pikachu_(Electric)) ++ * ++ * (foo http://www.pokemon.com/Pikachu_(Electric)) bar ++ * => foo http://www.pokemon.com/Pikachu_(Electric) ++ */ ++ ++ for bufEnd >= 0 && origData[bufEnd] != '\n' && openDelim != 0 { ++ if origData[bufEnd] == data[linkEnd-1] { ++ openDelim++ ++ } ++ ++ if origData[bufEnd] == copen { ++ openDelim-- ++ } ++ ++ bufEnd-- ++ } ++ ++ if openDelim == 0 { ++ linkEnd-- ++ } ++ } ++ ++ var uLink bytes.Buffer ++ unescapeText(&uLink, data[:linkEnd]) ++ ++ if uLink.Len() > 0 { ++ node := NewNode(Link) ++ node.Destination = uLink.Bytes() ++ node.AppendChild(text(uLink.Bytes())) ++ return linkEnd, node ++ } ++ ++ return linkEnd, nil ++} ++ ++func isEndOfLink(char byte) bool { ++ return isspace(char) || char == '<' ++} ++ ++var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")} ++var validPaths = [][]byte{[]byte("/"), []byte("./"), []byte("../")} ++ ++func isSafeLink(link []byte) bool { ++ for _, path := range validPaths { ++ if len(link) >= len(path) && bytes.Equal(link[:len(path)], path) { ++ if len(link) == len(path) { ++ return true ++ } else if isalnum(link[len(path)]) { ++ return true ++ } ++ } ++ } ++ ++ for _, prefix := range validUris { ++ // TODO: handle unicode here ++ // case-insensitive prefix test ++ if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) { ++ return true ++ } ++ } ++ ++ return false ++} ++ ++// return the length of the given tag, or 0 is it's not valid ++func tagLength(data []byte) (autolink autolinkType, end int) { ++ var i, j int ++ ++ // a valid tag can't be shorter than 3 chars ++ if len(data) < 3 { ++ return notAutolink, 0 ++ } ++ ++ // begins with a '<' optionally followed by '/', followed by letter or number ++ if data[0] != '<' { ++ return notAutolink, 0 ++ } ++ if data[1] == '/' { ++ i = 2 ++ } else { ++ i = 1 ++ } ++ ++ if !isalnum(data[i]) { ++ return notAutolink, 0 ++ } ++ ++ // scheme test ++ autolink = notAutolink ++ ++ // try to find the beginning of an URI ++ for i < len(data) && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') { ++ i++ ++ } ++ ++ if i > 1 && i < len(data) && data[i] == '@' { ++ if j = isMailtoAutoLink(data[i:]); j != 0 { ++ return emailAutolink, i + j ++ } ++ } ++ ++ if i > 2 && i < len(data) && data[i] == ':' { ++ autolink = normalAutolink ++ i++ ++ } ++ ++ // complete autolink test: no whitespace or ' or " ++ switch { ++ case i >= len(data): ++ autolink = notAutolink ++ case autolink != notAutolink: ++ j = i ++ ++ for i < len(data) { ++ if data[i] == '\\' { ++ i += 2 ++ } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || isspace(data[i]) { ++ break ++ } else { ++ i++ ++ } ++ ++ } ++ ++ if i >= len(data) { ++ return autolink, 0 ++ } ++ if i > j && data[i] == '>' { ++ return autolink, i + 1 ++ } ++ ++ // one of the forbidden chars has been found ++ autolink = notAutolink ++ } ++ i += bytes.IndexByte(data[i:], '>') ++ if i < 0 { ++ return autolink, 0 ++ } ++ return autolink, i + 1 ++} ++ ++// look for the address part of a mail autolink and '>' ++// this is less strict than the original markdown e-mail address matching ++func isMailtoAutoLink(data []byte) int { ++ nb := 0 ++ ++ // address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' ++ for i := 0; i < len(data); i++ { ++ if isalnum(data[i]) { ++ continue ++ } ++ ++ switch data[i] { ++ case '@': ++ nb++ ++ ++ case '-', '.', '_': ++ break ++ ++ case '>': ++ if nb == 1 { ++ return i + 1 ++ } ++ return 0 ++ default: ++ return 0 ++ } ++ } ++ ++ return 0 ++} ++ ++// look for the next emph char, skipping other constructs ++func helperFindEmphChar(data []byte, c byte) int { ++ i := 0 ++ ++ for i < len(data) { ++ for i < len(data) && data[i] != c && data[i] != '`' && data[i] != '[' { ++ i++ ++ } ++ if i >= len(data) { ++ return 0 ++ } ++ // do not count escaped chars ++ if i != 0 && data[i-1] == '\\' { ++ i++ ++ continue ++ } ++ if data[i] == c { ++ return i ++ } ++ ++ if data[i] == '`' { ++ // skip a code span ++ tmpI := 0 ++ i++ ++ for i < len(data) && data[i] != '`' { ++ if tmpI == 0 && data[i] == c { ++ tmpI = i ++ } ++ i++ ++ } ++ if i >= len(data) { ++ return tmpI ++ } ++ i++ ++ } else if data[i] == '[' { ++ // skip a link ++ tmpI := 0 ++ i++ ++ for i < len(data) && data[i] != ']' { ++ if tmpI == 0 && data[i] == c { ++ tmpI = i ++ } ++ i++ ++ } ++ i++ ++ for i < len(data) && (data[i] == ' ' || data[i] == '\n') { ++ i++ ++ } ++ if i >= len(data) { ++ return tmpI ++ } ++ if data[i] != '[' && data[i] != '(' { // not a link ++ if tmpI > 0 { ++ return tmpI ++ } ++ continue ++ } ++ cc := data[i] ++ i++ ++ for i < len(data) && data[i] != cc { ++ if tmpI == 0 && data[i] == c { ++ return i ++ } ++ i++ ++ } ++ if i >= len(data) { ++ return tmpI ++ } ++ i++ ++ } ++ } ++ return 0 ++} ++ ++func helperEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { ++ i := 0 ++ ++ // skip one symbol if coming from emph3 ++ if len(data) > 1 && data[0] == c && data[1] == c { ++ i = 1 ++ } ++ ++ for i < len(data) { ++ length := helperFindEmphChar(data[i:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ i += length ++ if i >= len(data) { ++ return 0, nil ++ } ++ ++ if i+1 < len(data) && data[i+1] == c { ++ i++ ++ continue ++ } ++ ++ if data[i] == c && !isspace(data[i-1]) { ++ ++ if p.extensions&NoIntraEmphasis != 0 { ++ if !(i+1 == len(data) || isspace(data[i+1]) || ispunct(data[i+1])) { ++ continue ++ } ++ } ++ ++ emph := NewNode(Emph) ++ p.inline(emph, data[:i]) ++ return i + 1, emph ++ } ++ } ++ ++ return 0, nil ++} ++ ++func helperDoubleEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { ++ i := 0 ++ ++ for i < len(data) { ++ length := helperFindEmphChar(data[i:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ i += length ++ ++ if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !isspace(data[i-1]) { ++ nodeType := Strong ++ if c == '~' { ++ nodeType = Del ++ } ++ node := NewNode(nodeType) ++ p.inline(node, data[:i]) ++ return i + 2, node ++ } ++ i++ ++ } ++ return 0, nil ++} ++ ++func helperTripleEmphasis(p *Markdown, data []byte, offset int, c byte) (int, *Node) { ++ i := 0 ++ origData := data ++ data = data[offset:] ++ ++ for i < len(data) { ++ length := helperFindEmphChar(data[i:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ i += length ++ ++ // skip whitespace preceded symbols ++ if data[i] != c || isspace(data[i-1]) { ++ continue ++ } ++ ++ switch { ++ case i+2 < len(data) && data[i+1] == c && data[i+2] == c: ++ // triple symbol found ++ strong := NewNode(Strong) ++ em := NewNode(Emph) ++ strong.AppendChild(em) ++ p.inline(em, data[:i]) ++ return i + 3, strong ++ case (i+1 < len(data) && data[i+1] == c): ++ // double symbol found, hand over to emph1 ++ length, node := helperEmphasis(p, origData[offset-2:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ return length - 2, node ++ default: ++ // single symbol found, hand over to emph2 ++ length, node := helperDoubleEmphasis(p, origData[offset-1:], c) ++ if length == 0 { ++ return 0, nil ++ } ++ return length - 1, node ++ } ++ } ++ return 0, nil ++} ++ ++func text(s []byte) *Node { ++ node := NewNode(Text) ++ node.Literal = s ++ return node ++} ++ ++func normalizeURI(s []byte) []byte { ++ return s // TODO: implement ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/markdown.go b/vendor/github.com/russross/blackfriday/v2/markdown.go +new file mode 100644 +index 000000000000..58d2e4538c62 +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/markdown.go +@@ -0,0 +1,950 @@ ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "strings" ++ "unicode/utf8" ++) ++ ++// ++// Markdown parsing and processing ++// ++ ++// Version string of the package. Appears in the rendered document when ++// CompletePage flag is on. ++const Version = "2.0" ++ ++// Extensions is a bitwise or'ed collection of enabled Blackfriday's ++// extensions. ++type Extensions int ++ ++// These are the supported markdown parsing extensions. ++// OR these values together to select multiple extensions. ++const ( ++ NoExtensions Extensions = 0 ++ NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words ++ Tables // Render tables ++ FencedCode // Render fenced code blocks ++ Autolink // Detect embedded URLs that are not explicitly marked ++ Strikethrough // Strikethrough text using ~~test~~ ++ LaxHTMLBlocks // Loosen up HTML block parsing rules ++ SpaceHeadings // Be strict about prefix heading rules ++ HardLineBreak // Translate newlines into line breaks ++ TabSizeEight // Expand tabs to eight spaces instead of four ++ Footnotes // Pandoc-style footnotes ++ NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block ++ HeadingIDs // specify heading IDs with {#id} ++ Titleblock // Titleblock ala pandoc ++ AutoHeadingIDs // Create the heading ID from the text ++ BackslashLineBreak // Translate trailing backslashes into line breaks ++ DefinitionLists // Render definition lists ++ ++ CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants | ++ SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes ++ ++ CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode | ++ Autolink | Strikethrough | SpaceHeadings | HeadingIDs | ++ BackslashLineBreak | DefinitionLists ++) ++ ++// ListType contains bitwise or'ed flags for list and list item objects. ++type ListType int ++ ++// These are the possible flag values for the ListItem renderer. ++// Multiple flag values may be ORed together. ++// These are mostly of interest if you are writing a new output format. ++const ( ++ ListTypeOrdered ListType = 1 << iota ++ ListTypeDefinition ++ ListTypeTerm ++ ++ ListItemContainsBlock ++ ListItemBeginningOfList // TODO: figure out if this is of any use now ++ ListItemEndOfList ++) ++ ++// CellAlignFlags holds a type of alignment in a table cell. ++type CellAlignFlags int ++ ++// These are the possible flag values for the table cell renderer. ++// Only a single one of these values will be used; they are not ORed together. ++// These are mostly of interest if you are writing a new output format. ++const ( ++ TableAlignmentLeft CellAlignFlags = 1 << iota ++ TableAlignmentRight ++ TableAlignmentCenter = (TableAlignmentLeft | TableAlignmentRight) ++) ++ ++// The size of a tab stop. ++const ( ++ TabSizeDefault = 4 ++ TabSizeDouble = 8 ++) ++ ++// blockTags is a set of tags that are recognized as HTML block tags. ++// Any of these can be included in markdown text without special escaping. ++var blockTags = map[string]struct{}{ ++ "blockquote": {}, ++ "del": {}, ++ "div": {}, ++ "dl": {}, ++ "fieldset": {}, ++ "form": {}, ++ "h1": {}, ++ "h2": {}, ++ "h3": {}, ++ "h4": {}, ++ "h5": {}, ++ "h6": {}, ++ "iframe": {}, ++ "ins": {}, ++ "math": {}, ++ "noscript": {}, ++ "ol": {}, ++ "pre": {}, ++ "p": {}, ++ "script": {}, ++ "style": {}, ++ "table": {}, ++ "ul": {}, ++ ++ // HTML5 ++ "address": {}, ++ "article": {}, ++ "aside": {}, ++ "canvas": {}, ++ "figcaption": {}, ++ "figure": {}, ++ "footer": {}, ++ "header": {}, ++ "hgroup": {}, ++ "main": {}, ++ "nav": {}, ++ "output": {}, ++ "progress": {}, ++ "section": {}, ++ "video": {}, ++} ++ ++// Renderer is the rendering interface. This is mostly of interest if you are ++// implementing a new rendering format. ++// ++// Only an HTML implementation is provided in this repository, see the README ++// for external implementations. ++type Renderer interface { ++ // RenderNode is the main rendering method. It will be called once for ++ // every leaf node and twice for every non-leaf node (first with ++ // entering=true, then with entering=false). The method should write its ++ // rendition of the node to the supplied writer w. ++ RenderNode(w io.Writer, node *Node, entering bool) WalkStatus ++ ++ // RenderHeader is a method that allows the renderer to produce some ++ // content preceding the main body of the output document. The header is ++ // understood in the broad sense here. For example, the default HTML ++ // renderer will write not only the HTML document preamble, but also the ++ // table of contents if it was requested. ++ // ++ // The method will be passed an entire document tree, in case a particular ++ // implementation needs to inspect it to produce output. ++ // ++ // The output should be written to the supplied writer w. If your ++ // implementation has no header to write, supply an empty implementation. ++ RenderHeader(w io.Writer, ast *Node) ++ ++ // RenderFooter is a symmetric counterpart of RenderHeader. ++ RenderFooter(w io.Writer, ast *Node) ++} ++ ++// Callback functions for inline parsing. One such function is defined ++// for each character that triggers a response when parsing inline data. ++type inlineParser func(p *Markdown, data []byte, offset int) (int, *Node) ++ ++// Markdown is a type that holds extensions and the runtime state used by ++// Parse, and the renderer. You can not use it directly, construct it with New. ++type Markdown struct { ++ renderer Renderer ++ referenceOverride ReferenceOverrideFunc ++ refs map[string]*reference ++ inlineCallback [256]inlineParser ++ extensions Extensions ++ nesting int ++ maxNesting int ++ insideLink bool ++ ++ // Footnotes need to be ordered as well as available to quickly check for ++ // presence. If a ref is also a footnote, it's stored both in refs and here ++ // in notes. Slice is nil if footnotes not enabled. ++ notes []*reference ++ ++ doc *Node ++ tip *Node // = doc ++ oldTip *Node ++ lastMatchedContainer *Node // = doc ++ allClosed bool ++} ++ ++func (p *Markdown) getRef(refid string) (ref *reference, found bool) { ++ if p.referenceOverride != nil { ++ r, overridden := p.referenceOverride(refid) ++ if overridden { ++ if r == nil { ++ return nil, false ++ } ++ return &reference{ ++ link: []byte(r.Link), ++ title: []byte(r.Title), ++ noteID: 0, ++ hasBlock: false, ++ text: []byte(r.Text)}, true ++ } ++ } ++ // refs are case insensitive ++ ref, found = p.refs[strings.ToLower(refid)] ++ return ref, found ++} ++ ++func (p *Markdown) finalize(block *Node) { ++ above := block.Parent ++ block.open = false ++ p.tip = above ++} ++ ++func (p *Markdown) addChild(node NodeType, offset uint32) *Node { ++ return p.addExistingChild(NewNode(node), offset) ++} ++ ++func (p *Markdown) addExistingChild(node *Node, offset uint32) *Node { ++ for !p.tip.canContain(node.Type) { ++ p.finalize(p.tip) ++ } ++ p.tip.AppendChild(node) ++ p.tip = node ++ return node ++} ++ ++func (p *Markdown) closeUnmatchedBlocks() { ++ if !p.allClosed { ++ for p.oldTip != p.lastMatchedContainer { ++ parent := p.oldTip.Parent ++ p.finalize(p.oldTip) ++ p.oldTip = parent ++ } ++ p.allClosed = true ++ } ++} ++ ++// ++// ++// Public interface ++// ++// ++ ++// Reference represents the details of a link. ++// See the documentation in Options for more details on use-case. ++type Reference struct { ++ // Link is usually the URL the reference points to. ++ Link string ++ // Title is the alternate text describing the link in more detail. ++ Title string ++ // Text is the optional text to override the ref with if the syntax used was ++ // [refid][] ++ Text string ++} ++ ++// ReferenceOverrideFunc is expected to be called with a reference string and ++// return either a valid Reference type that the reference string maps to or ++// nil. If overridden is false, the default reference logic will be executed. ++// See the documentation in Options for more details on use-case. ++type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool) ++ ++// New constructs a Markdown processor. You can use the same With* functions as ++// for Run() to customize parser's behavior and the renderer. ++func New(opts ...Option) *Markdown { ++ var p Markdown ++ for _, opt := range opts { ++ opt(&p) ++ } ++ p.refs = make(map[string]*reference) ++ p.maxNesting = 16 ++ p.insideLink = false ++ docNode := NewNode(Document) ++ p.doc = docNode ++ p.tip = docNode ++ p.oldTip = docNode ++ p.lastMatchedContainer = docNode ++ p.allClosed = true ++ // register inline parsers ++ p.inlineCallback[' '] = maybeLineBreak ++ p.inlineCallback['*'] = emphasis ++ p.inlineCallback['_'] = emphasis ++ if p.extensions&Strikethrough != 0 { ++ p.inlineCallback['~'] = emphasis ++ } ++ p.inlineCallback['`'] = codeSpan ++ p.inlineCallback['\n'] = lineBreak ++ p.inlineCallback['['] = link ++ p.inlineCallback['<'] = leftAngle ++ p.inlineCallback['\\'] = escape ++ p.inlineCallback['&'] = entity ++ p.inlineCallback['!'] = maybeImage ++ p.inlineCallback['^'] = maybeInlineFootnote ++ if p.extensions&Autolink != 0 { ++ p.inlineCallback['h'] = maybeAutoLink ++ p.inlineCallback['m'] = maybeAutoLink ++ p.inlineCallback['f'] = maybeAutoLink ++ p.inlineCallback['H'] = maybeAutoLink ++ p.inlineCallback['M'] = maybeAutoLink ++ p.inlineCallback['F'] = maybeAutoLink ++ } ++ if p.extensions&Footnotes != 0 { ++ p.notes = make([]*reference, 0) ++ } ++ return &p ++} ++ ++// Option customizes the Markdown processor's default behavior. ++type Option func(*Markdown) ++ ++// WithRenderer allows you to override the default renderer. ++func WithRenderer(r Renderer) Option { ++ return func(p *Markdown) { ++ p.renderer = r ++ } ++} ++ ++// WithExtensions allows you to pick some of the many extensions provided by ++// Blackfriday. You can bitwise OR them. ++func WithExtensions(e Extensions) Option { ++ return func(p *Markdown) { ++ p.extensions = e ++ } ++} ++ ++// WithNoExtensions turns off all extensions and custom behavior. ++func WithNoExtensions() Option { ++ return func(p *Markdown) { ++ p.extensions = NoExtensions ++ p.renderer = NewHTMLRenderer(HTMLRendererParameters{ ++ Flags: HTMLFlagsNone, ++ }) ++ } ++} ++ ++// WithRefOverride sets an optional function callback that is called every ++// time a reference is resolved. ++// ++// In Markdown, the link reference syntax can be made to resolve a link to ++// a reference instead of an inline URL, in one of the following ways: ++// ++// * [link text][refid] ++// * [refid][] ++// ++// Usually, the refid is defined at the bottom of the Markdown document. If ++// this override function is provided, the refid is passed to the override ++// function first, before consulting the defined refids at the bottom. If ++// the override function indicates an override did not occur, the refids at ++// the bottom will be used to fill in the link details. ++func WithRefOverride(o ReferenceOverrideFunc) Option { ++ return func(p *Markdown) { ++ p.referenceOverride = o ++ } ++} ++ ++// Run is the main entry point to Blackfriday. It parses and renders a ++// block of markdown-encoded text. ++// ++// The simplest invocation of Run takes one argument, input: ++// output := Run(input) ++// This will parse the input with CommonExtensions enabled and render it with ++// the default HTMLRenderer (with CommonHTMLFlags). ++// ++// Variadic arguments opts can customize the default behavior. Since Markdown ++// type does not contain exported fields, you can not use it directly. Instead, ++// use the With* functions. For example, this will call the most basic ++// functionality, with no extensions: ++// output := Run(input, WithNoExtensions()) ++// ++// You can use any number of With* arguments, even contradicting ones. They ++// will be applied in order of appearance and the latter will override the ++// former: ++// output := Run(input, WithNoExtensions(), WithExtensions(exts), ++// WithRenderer(yourRenderer)) ++func Run(input []byte, opts ...Option) []byte { ++ r := NewHTMLRenderer(HTMLRendererParameters{ ++ Flags: CommonHTMLFlags, ++ }) ++ optList := []Option{WithRenderer(r), WithExtensions(CommonExtensions)} ++ optList = append(optList, opts...) ++ parser := New(optList...) ++ ast := parser.Parse(input) ++ var buf bytes.Buffer ++ parser.renderer.RenderHeader(&buf, ast) ++ ast.Walk(func(node *Node, entering bool) WalkStatus { ++ return parser.renderer.RenderNode(&buf, node, entering) ++ }) ++ parser.renderer.RenderFooter(&buf, ast) ++ return buf.Bytes() ++} ++ ++// Parse is an entry point to the parsing part of Blackfriday. It takes an ++// input markdown document and produces a syntax tree for its contents. This ++// tree can then be rendered with a default or custom renderer, or ++// analyzed/transformed by the caller to whatever non-standard needs they have. ++// The return value is the root node of the syntax tree. ++func (p *Markdown) Parse(input []byte) *Node { ++ p.block(input) ++ // Walk the tree and finish up some of unfinished blocks ++ for p.tip != nil { ++ p.finalize(p.tip) ++ } ++ // Walk the tree again and process inline markdown in each block ++ p.doc.Walk(func(node *Node, entering bool) WalkStatus { ++ if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell { ++ p.inline(node, node.content) ++ node.content = nil ++ } ++ return GoToNext ++ }) ++ p.parseRefsToAST() ++ return p.doc ++} ++ ++func (p *Markdown) parseRefsToAST() { ++ if p.extensions&Footnotes == 0 || len(p.notes) == 0 { ++ return ++ } ++ p.tip = p.doc ++ block := p.addBlock(List, nil) ++ block.IsFootnotesList = true ++ block.ListFlags = ListTypeOrdered ++ flags := ListItemBeginningOfList ++ // Note: this loop is intentionally explicit, not range-form. This is ++ // because the body of the loop will append nested footnotes to p.notes and ++ // we need to process those late additions. Range form would only walk over ++ // the fixed initial set. ++ for i := 0; i < len(p.notes); i++ { ++ ref := p.notes[i] ++ p.addExistingChild(ref.footnote, 0) ++ block := ref.footnote ++ block.ListFlags = flags | ListTypeOrdered ++ block.RefLink = ref.link ++ if ref.hasBlock { ++ flags |= ListItemContainsBlock ++ p.block(ref.title) ++ } else { ++ p.inline(block, ref.title) ++ } ++ flags &^= ListItemBeginningOfList | ListItemContainsBlock ++ } ++ above := block.Parent ++ finalizeList(block) ++ p.tip = above ++ block.Walk(func(node *Node, entering bool) WalkStatus { ++ if node.Type == Paragraph || node.Type == Heading { ++ p.inline(node, node.content) ++ node.content = nil ++ } ++ return GoToNext ++ }) ++} ++ ++// ++// Link references ++// ++// This section implements support for references that (usually) appear ++// as footnotes in a document, and can be referenced anywhere in the document. ++// The basic format is: ++// ++// [1]: http://www.google.com/ "Google" ++// [2]: http://www.github.com/ "Github" ++// ++// Anywhere in the document, the reference can be linked by referring to its ++// label, i.e., 1 and 2 in this example, as in: ++// ++// This library is hosted on [Github][2], a git hosting site. ++// ++// Actual footnotes as specified in Pandoc and supported by some other Markdown ++// libraries such as php-markdown are also taken care of. They look like this: ++// ++// This sentence needs a bit of further explanation.[^note] ++// ++// [^note]: This is the explanation. ++// ++// Footnotes should be placed at the end of the document in an ordered list. ++// Finally, there are inline footnotes such as: ++// ++// Inline footnotes^[Also supported.] provide a quick inline explanation, ++// but are rendered at the bottom of the document. ++// ++ ++// reference holds all information necessary for a reference-style links or ++// footnotes. ++// ++// Consider this markdown with reference-style links: ++// ++// [link][ref] ++// ++// [ref]: /url/ "tooltip title" ++// ++// It will be ultimately converted to this HTML: ++// ++//

    link

    ++// ++// And a reference structure will be populated as follows: ++// ++// p.refs["ref"] = &reference{ ++// link: "/url/", ++// title: "tooltip title", ++// } ++// ++// Alternatively, reference can contain information about a footnote. Consider ++// this markdown: ++// ++// Text needing a footnote.[^a] ++// ++// [^a]: This is the note ++// ++// A reference structure will be populated as follows: ++// ++// p.refs["a"] = &reference{ ++// link: "a", ++// title: "This is the note", ++// noteID: , ++// } ++// ++// TODO: As you can see, it begs for splitting into two dedicated structures ++// for refs and for footnotes. ++type reference struct { ++ link []byte ++ title []byte ++ noteID int // 0 if not a footnote ref ++ hasBlock bool ++ footnote *Node // a link to the Item node within a list of footnotes ++ ++ text []byte // only gets populated by refOverride feature with Reference.Text ++} ++ ++func (r *reference) String() string { ++ return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}", ++ r.link, r.title, r.text, r.noteID, r.hasBlock) ++} ++ ++// Check whether or not data starts with a reference link. ++// If so, it is parsed and stored in the list of references ++// (in the render struct). ++// Returns the number of bytes to skip to move past it, ++// or zero if the first line is not a reference. ++func isReference(p *Markdown, data []byte, tabSize int) int { ++ // up to 3 optional leading spaces ++ if len(data) < 4 { ++ return 0 ++ } ++ i := 0 ++ for i < 3 && data[i] == ' ' { ++ i++ ++ } ++ ++ noteID := 0 ++ ++ // id part: anything but a newline between brackets ++ if data[i] != '[' { ++ return 0 ++ } ++ i++ ++ if p.extensions&Footnotes != 0 { ++ if i < len(data) && data[i] == '^' { ++ // we can set it to anything here because the proper noteIds will ++ // be assigned later during the second pass. It just has to be != 0 ++ noteID = 1 ++ i++ ++ } ++ } ++ idOffset := i ++ for i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != ']' { ++ i++ ++ } ++ if i >= len(data) || data[i] != ']' { ++ return 0 ++ } ++ idEnd := i ++ // footnotes can have empty ID, like this: [^], but a reference can not be ++ // empty like this: []. Break early if it's not a footnote and there's no ID ++ if noteID == 0 && idOffset == idEnd { ++ return 0 ++ } ++ // spacer: colon (space | tab)* newline? (space | tab)* ++ i++ ++ if i >= len(data) || data[i] != ':' { ++ return 0 ++ } ++ i++ ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ if i < len(data) && (data[i] == '\n' || data[i] == '\r') { ++ i++ ++ if i < len(data) && data[i] == '\n' && data[i-1] == '\r' { ++ i++ ++ } ++ } ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ if i >= len(data) { ++ return 0 ++ } ++ ++ var ( ++ linkOffset, linkEnd int ++ titleOffset, titleEnd int ++ lineEnd int ++ raw []byte ++ hasBlock bool ++ ) ++ ++ if p.extensions&Footnotes != 0 && noteID != 0 { ++ linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize) ++ lineEnd = linkEnd ++ } else { ++ linkOffset, linkEnd, titleOffset, titleEnd, lineEnd = scanLinkRef(p, data, i) ++ } ++ if lineEnd == 0 { ++ return 0 ++ } ++ ++ // a valid ref has been found ++ ++ ref := &reference{ ++ noteID: noteID, ++ hasBlock: hasBlock, ++ } ++ ++ if noteID > 0 { ++ // reusing the link field for the id since footnotes don't have links ++ ref.link = data[idOffset:idEnd] ++ // if footnote, it's not really a title, it's the contained text ++ ref.title = raw ++ } else { ++ ref.link = data[linkOffset:linkEnd] ++ ref.title = data[titleOffset:titleEnd] ++ } ++ ++ // id matches are case-insensitive ++ id := string(bytes.ToLower(data[idOffset:idEnd])) ++ ++ p.refs[id] = ref ++ ++ return lineEnd ++} ++ ++func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) { ++ // link: whitespace-free sequence, optionally between angle brackets ++ if data[i] == '<' { ++ i++ ++ } ++ linkOffset = i ++ for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' { ++ i++ ++ } ++ linkEnd = i ++ if data[linkOffset] == '<' && data[linkEnd-1] == '>' { ++ linkOffset++ ++ linkEnd-- ++ } ++ ++ // optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ if i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != '\'' && data[i] != '"' && data[i] != '(' { ++ return ++ } ++ ++ // compute end-of-line ++ if i >= len(data) || data[i] == '\r' || data[i] == '\n' { ++ lineEnd = i ++ } ++ if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' { ++ lineEnd++ ++ } ++ ++ // optional (space|tab)* spacer after a newline ++ if lineEnd > 0 { ++ i = lineEnd + 1 ++ for i < len(data) && (data[i] == ' ' || data[i] == '\t') { ++ i++ ++ } ++ } ++ ++ // optional title: any non-newline sequence enclosed in '"() alone on its line ++ if i+1 < len(data) && (data[i] == '\'' || data[i] == '"' || data[i] == '(') { ++ i++ ++ titleOffset = i ++ ++ // look for EOL ++ for i < len(data) && data[i] != '\n' && data[i] != '\r' { ++ i++ ++ } ++ if i+1 < len(data) && data[i] == '\n' && data[i+1] == '\r' { ++ titleEnd = i + 1 ++ } else { ++ titleEnd = i ++ } ++ ++ // step back ++ i-- ++ for i > titleOffset && (data[i] == ' ' || data[i] == '\t') { ++ i-- ++ } ++ if i > titleOffset && (data[i] == '\'' || data[i] == '"' || data[i] == ')') { ++ lineEnd = titleEnd ++ titleEnd = i ++ } ++ } ++ ++ return ++} ++ ++// The first bit of this logic is the same as Parser.listItem, but the rest ++// is much simpler. This function simply finds the entire block and shifts it ++// over by one tab if it is indeed a block (just returns the line if it's not). ++// blockEnd is the end of the section in the input buffer, and contents is the ++// extracted text that was shifted over one tab. It will need to be rendered at ++// the end of the document. ++func scanFootnote(p *Markdown, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) { ++ if i == 0 || len(data) == 0 { ++ return ++ } ++ ++ // skip leading whitespace on first line ++ for i < len(data) && data[i] == ' ' { ++ i++ ++ } ++ ++ blockStart = i ++ ++ // find the end of the line ++ blockEnd = i ++ for i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // get working buffer ++ var raw bytes.Buffer ++ ++ // put the first line into the working buffer ++ raw.Write(data[blockEnd:i]) ++ blockEnd = i ++ ++ // process the following lines ++ containsBlankLine := false ++ ++gatherLines: ++ for blockEnd < len(data) { ++ i++ ++ ++ // find the end of this line ++ for i < len(data) && data[i-1] != '\n' { ++ i++ ++ } ++ ++ // if it is an empty line, guess that it is part of this item ++ // and move on to the next line ++ if p.isEmpty(data[blockEnd:i]) > 0 { ++ containsBlankLine = true ++ blockEnd = i ++ continue ++ } ++ ++ n := 0 ++ if n = isIndented(data[blockEnd:i], indentSize); n == 0 { ++ // this is the end of the block. ++ // we don't want to include this last line in the index. ++ break gatherLines ++ } ++ ++ // if there were blank lines before this one, insert a new one now ++ if containsBlankLine { ++ raw.WriteByte('\n') ++ containsBlankLine = false ++ } ++ ++ // get rid of that first tab, write to buffer ++ raw.Write(data[blockEnd+n : i]) ++ hasBlock = true ++ ++ blockEnd = i ++ } ++ ++ if data[blockEnd-1] != '\n' { ++ raw.WriteByte('\n') ++ } ++ ++ contents = raw.Bytes() ++ ++ return ++} ++ ++// ++// ++// Miscellaneous helper functions ++// ++// ++ ++// Test if a character is a punctuation symbol. ++// Taken from a private function in regexp in the stdlib. ++func ispunct(c byte) bool { ++ for _, r := range []byte("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") { ++ if c == r { ++ return true ++ } ++ } ++ return false ++} ++ ++// Test if a character is a whitespace character. ++func isspace(c byte) bool { ++ return ishorizontalspace(c) || isverticalspace(c) ++} ++ ++// Test if a character is a horizontal whitespace character. ++func ishorizontalspace(c byte) bool { ++ return c == ' ' || c == '\t' ++} ++ ++// Test if a character is a vertical character. ++func isverticalspace(c byte) bool { ++ return c == '\n' || c == '\r' || c == '\f' || c == '\v' ++} ++ ++// Test if a character is letter. ++func isletter(c byte) bool { ++ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ++} ++ ++// Test if a character is a letter or a digit. ++// TODO: check when this is looking for ASCII alnum and when it should use unicode ++func isalnum(c byte) bool { ++ return (c >= '0' && c <= '9') || isletter(c) ++} ++ ++// Replace tab characters with spaces, aligning to the next TAB_SIZE column. ++// always ends output with a newline ++func expandTabs(out *bytes.Buffer, line []byte, tabSize int) { ++ // first, check for common cases: no tabs, or only tabs at beginning of line ++ i, prefix := 0, 0 ++ slowcase := false ++ for i = 0; i < len(line); i++ { ++ if line[i] == '\t' { ++ if prefix == i { ++ prefix++ ++ } else { ++ slowcase = true ++ break ++ } ++ } ++ } ++ ++ // no need to decode runes if all tabs are at the beginning of the line ++ if !slowcase { ++ for i = 0; i < prefix*tabSize; i++ { ++ out.WriteByte(' ') ++ } ++ out.Write(line[prefix:]) ++ return ++ } ++ ++ // the slow case: we need to count runes to figure out how ++ // many spaces to insert for each tab ++ column := 0 ++ i = 0 ++ for i < len(line) { ++ start := i ++ for i < len(line) && line[i] != '\t' { ++ _, size := utf8.DecodeRune(line[i:]) ++ i += size ++ column++ ++ } ++ ++ if i > start { ++ out.Write(line[start:i]) ++ } ++ ++ if i >= len(line) { ++ break ++ } ++ ++ for { ++ out.WriteByte(' ') ++ column++ ++ if column%tabSize == 0 { ++ break ++ } ++ } ++ ++ i++ ++ } ++} ++ ++// Find if a line counts as indented or not. ++// Returns number of characters the indent is (0 = not indented). ++func isIndented(data []byte, indentSize int) int { ++ if len(data) == 0 { ++ return 0 ++ } ++ if data[0] == '\t' { ++ return 1 ++ } ++ if len(data) < indentSize { ++ return 0 ++ } ++ for i := 0; i < indentSize; i++ { ++ if data[i] != ' ' { ++ return 0 ++ } ++ } ++ return indentSize ++} ++ ++// Create a url-safe slug for fragments ++func slugify(in []byte) []byte { ++ if len(in) == 0 { ++ return in ++ } ++ out := make([]byte, 0, len(in)) ++ sym := false ++ ++ for _, ch := range in { ++ if isalnum(ch) { ++ sym = false ++ out = append(out, ch) ++ } else if sym { ++ continue ++ } else { ++ out = append(out, '-') ++ sym = true ++ } ++ } ++ var a, b int ++ var ch byte ++ for a, ch = range out { ++ if ch != '-' { ++ break ++ } ++ } ++ for b = len(out) - 1; b > 0; b-- { ++ if out[b] != '-' { ++ break ++ } ++ } ++ return out[a : b+1] ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/node.go b/vendor/github.com/russross/blackfriday/v2/node.go +new file mode 100644 +index 000000000000..04e6050ceeae +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/node.go +@@ -0,0 +1,360 @@ ++package blackfriday ++ ++import ( ++ "bytes" ++ "fmt" ++) ++ ++// NodeType specifies a type of a single node of a syntax tree. Usually one ++// node (and its type) corresponds to a single markdown feature, e.g. emphasis ++// or code block. ++type NodeType int ++ ++// Constants for identifying different types of nodes. See NodeType. ++const ( ++ Document NodeType = iota ++ BlockQuote ++ List ++ Item ++ Paragraph ++ Heading ++ HorizontalRule ++ Emph ++ Strong ++ Del ++ Link ++ Image ++ Text ++ HTMLBlock ++ CodeBlock ++ Softbreak ++ Hardbreak ++ Code ++ HTMLSpan ++ Table ++ TableCell ++ TableHead ++ TableBody ++ TableRow ++) ++ ++var nodeTypeNames = []string{ ++ Document: "Document", ++ BlockQuote: "BlockQuote", ++ List: "List", ++ Item: "Item", ++ Paragraph: "Paragraph", ++ Heading: "Heading", ++ HorizontalRule: "HorizontalRule", ++ Emph: "Emph", ++ Strong: "Strong", ++ Del: "Del", ++ Link: "Link", ++ Image: "Image", ++ Text: "Text", ++ HTMLBlock: "HTMLBlock", ++ CodeBlock: "CodeBlock", ++ Softbreak: "Softbreak", ++ Hardbreak: "Hardbreak", ++ Code: "Code", ++ HTMLSpan: "HTMLSpan", ++ Table: "Table", ++ TableCell: "TableCell", ++ TableHead: "TableHead", ++ TableBody: "TableBody", ++ TableRow: "TableRow", ++} ++ ++func (t NodeType) String() string { ++ return nodeTypeNames[t] ++} ++ ++// ListData contains fields relevant to a List and Item node type. ++type ListData struct { ++ ListFlags ListType ++ Tight bool // Skip

    s around list item data if true ++ BulletChar byte // '*', '+' or '-' in bullet lists ++ Delimiter byte // '.' or ')' after the number in ordered lists ++ RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering ++ IsFootnotesList bool // This is a list of footnotes ++} ++ ++// LinkData contains fields relevant to a Link node type. ++type LinkData struct { ++ Destination []byte // Destination is what goes into a href ++ Title []byte // Title is the tooltip thing that goes in a title attribute ++ NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote ++ Footnote *Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil. ++} ++ ++// CodeBlockData contains fields relevant to a CodeBlock node type. ++type CodeBlockData struct { ++ IsFenced bool // Specifies whether it's a fenced code block or an indented one ++ Info []byte // This holds the info string ++ FenceChar byte ++ FenceLength int ++ FenceOffset int ++} ++ ++// TableCellData contains fields relevant to a TableCell node type. ++type TableCellData struct { ++ IsHeader bool // This tells if it's under the header row ++ Align CellAlignFlags // This holds the value for align attribute ++} ++ ++// HeadingData contains fields relevant to a Heading node type. ++type HeadingData struct { ++ Level int // This holds the heading level number ++ HeadingID string // This might hold heading ID, if present ++ IsTitleblock bool // Specifies whether it's a title block ++} ++ ++// Node is a single element in the abstract syntax tree of the parsed document. ++// It holds connections to the structurally neighboring nodes and, for certain ++// types of nodes, additional information that might be needed when rendering. ++type Node struct { ++ Type NodeType // Determines the type of the node ++ Parent *Node // Points to the parent ++ FirstChild *Node // Points to the first child, if any ++ LastChild *Node // Points to the last child, if any ++ Prev *Node // Previous sibling; nil if it's the first child ++ Next *Node // Next sibling; nil if it's the last child ++ ++ Literal []byte // Text contents of the leaf nodes ++ ++ HeadingData // Populated if Type is Heading ++ ListData // Populated if Type is List ++ CodeBlockData // Populated if Type is CodeBlock ++ LinkData // Populated if Type is Link ++ TableCellData // Populated if Type is TableCell ++ ++ content []byte // Markdown content of the block nodes ++ open bool // Specifies an open block node that has not been finished to process yet ++} ++ ++// NewNode allocates a node of a specified type. ++func NewNode(typ NodeType) *Node { ++ return &Node{ ++ Type: typ, ++ open: true, ++ } ++} ++ ++func (n *Node) String() string { ++ ellipsis := "" ++ snippet := n.Literal ++ if len(snippet) > 16 { ++ snippet = snippet[:16] ++ ellipsis = "..." ++ } ++ return fmt.Sprintf("%s: '%s%s'", n.Type, snippet, ellipsis) ++} ++ ++// Unlink removes node 'n' from the tree. ++// It panics if the node is nil. ++func (n *Node) Unlink() { ++ if n.Prev != nil { ++ n.Prev.Next = n.Next ++ } else if n.Parent != nil { ++ n.Parent.FirstChild = n.Next ++ } ++ if n.Next != nil { ++ n.Next.Prev = n.Prev ++ } else if n.Parent != nil { ++ n.Parent.LastChild = n.Prev ++ } ++ n.Parent = nil ++ n.Next = nil ++ n.Prev = nil ++} ++ ++// AppendChild adds a node 'child' as a child of 'n'. ++// It panics if either node is nil. ++func (n *Node) AppendChild(child *Node) { ++ child.Unlink() ++ child.Parent = n ++ if n.LastChild != nil { ++ n.LastChild.Next = child ++ child.Prev = n.LastChild ++ n.LastChild = child ++ } else { ++ n.FirstChild = child ++ n.LastChild = child ++ } ++} ++ ++// InsertBefore inserts 'sibling' immediately before 'n'. ++// It panics if either node is nil. ++func (n *Node) InsertBefore(sibling *Node) { ++ sibling.Unlink() ++ sibling.Prev = n.Prev ++ if sibling.Prev != nil { ++ sibling.Prev.Next = sibling ++ } ++ sibling.Next = n ++ n.Prev = sibling ++ sibling.Parent = n.Parent ++ if sibling.Prev == nil { ++ sibling.Parent.FirstChild = sibling ++ } ++} ++ ++// IsContainer returns true if 'n' can contain children. ++func (n *Node) IsContainer() bool { ++ switch n.Type { ++ case Document: ++ fallthrough ++ case BlockQuote: ++ fallthrough ++ case List: ++ fallthrough ++ case Item: ++ fallthrough ++ case Paragraph: ++ fallthrough ++ case Heading: ++ fallthrough ++ case Emph: ++ fallthrough ++ case Strong: ++ fallthrough ++ case Del: ++ fallthrough ++ case Link: ++ fallthrough ++ case Image: ++ fallthrough ++ case Table: ++ fallthrough ++ case TableHead: ++ fallthrough ++ case TableBody: ++ fallthrough ++ case TableRow: ++ fallthrough ++ case TableCell: ++ return true ++ default: ++ return false ++ } ++} ++ ++// IsLeaf returns true if 'n' is a leaf node. ++func (n *Node) IsLeaf() bool { ++ return !n.IsContainer() ++} ++ ++func (n *Node) canContain(t NodeType) bool { ++ if n.Type == List { ++ return t == Item ++ } ++ if n.Type == Document || n.Type == BlockQuote || n.Type == Item { ++ return t != Item ++ } ++ if n.Type == Table { ++ return t == TableHead || t == TableBody ++ } ++ if n.Type == TableHead || n.Type == TableBody { ++ return t == TableRow ++ } ++ if n.Type == TableRow { ++ return t == TableCell ++ } ++ return false ++} ++ ++// WalkStatus allows NodeVisitor to have some control over the tree traversal. ++// It is returned from NodeVisitor and different values allow Node.Walk to ++// decide which node to go to next. ++type WalkStatus int ++ ++const ( ++ // GoToNext is the default traversal of every node. ++ GoToNext WalkStatus = iota ++ // SkipChildren tells walker to skip all children of current node. ++ SkipChildren ++ // Terminate tells walker to terminate the traversal. ++ Terminate ++) ++ ++// NodeVisitor is a callback to be called when traversing the syntax tree. ++// Called twice for every node: once with entering=true when the branch is ++// first visited, then with entering=false after all the children are done. ++type NodeVisitor func(node *Node, entering bool) WalkStatus ++ ++// Walk is a convenience method that instantiates a walker and starts a ++// traversal of subtree rooted at n. ++func (n *Node) Walk(visitor NodeVisitor) { ++ w := newNodeWalker(n) ++ for w.current != nil { ++ status := visitor(w.current, w.entering) ++ switch status { ++ case GoToNext: ++ w.next() ++ case SkipChildren: ++ w.entering = false ++ w.next() ++ case Terminate: ++ return ++ } ++ } ++} ++ ++type nodeWalker struct { ++ current *Node ++ root *Node ++ entering bool ++} ++ ++func newNodeWalker(root *Node) *nodeWalker { ++ return &nodeWalker{ ++ current: root, ++ root: root, ++ entering: true, ++ } ++} ++ ++func (nw *nodeWalker) next() { ++ if (!nw.current.IsContainer() || !nw.entering) && nw.current == nw.root { ++ nw.current = nil ++ return ++ } ++ if nw.entering && nw.current.IsContainer() { ++ if nw.current.FirstChild != nil { ++ nw.current = nw.current.FirstChild ++ nw.entering = true ++ } else { ++ nw.entering = false ++ } ++ } else if nw.current.Next == nil { ++ nw.current = nw.current.Parent ++ nw.entering = false ++ } else { ++ nw.current = nw.current.Next ++ nw.entering = true ++ } ++} ++ ++func dump(ast *Node) { ++ fmt.Println(dumpString(ast)) ++} ++ ++func dumpR(ast *Node, depth int) string { ++ if ast == nil { ++ return "" ++ } ++ indent := bytes.Repeat([]byte("\t"), depth) ++ content := ast.Literal ++ if content == nil { ++ content = ast.content ++ } ++ result := fmt.Sprintf("%s%s(%q)\n", indent, ast.Type, content) ++ for n := ast.FirstChild; n != nil; n = n.Next { ++ result += dumpR(n, depth+1) ++ } ++ return result ++} ++ ++func dumpString(ast *Node) string { ++ return dumpR(ast, 0) ++} +diff --git a/vendor/github.com/russross/blackfriday/v2/smartypants.go b/vendor/github.com/russross/blackfriday/v2/smartypants.go +new file mode 100644 +index 000000000000..3a220e94247d +--- /dev/null ++++ b/vendor/github.com/russross/blackfriday/v2/smartypants.go +@@ -0,0 +1,457 @@ ++// ++// Blackfriday Markdown Processor ++// Available at http://github.com/russross/blackfriday ++// ++// Copyright © 2011 Russ Ross . ++// Distributed under the Simplified BSD License. ++// See README.md for details. ++// ++ ++// ++// ++// SmartyPants rendering ++// ++// ++ ++package blackfriday ++ ++import ( ++ "bytes" ++ "io" ++) ++ ++// SPRenderer is a struct containing state of a Smartypants renderer. ++type SPRenderer struct { ++ inSingleQuote bool ++ inDoubleQuote bool ++ callbacks [256]smartCallback ++} ++ ++func wordBoundary(c byte) bool { ++ return c == 0 || isspace(c) || ispunct(c) ++} ++ ++func tolower(c byte) byte { ++ if c >= 'A' && c <= 'Z' { ++ return c - 'A' + 'a' ++ } ++ return c ++} ++ ++func isdigit(c byte) bool { ++ return c >= '0' && c <= '9' ++} ++ ++func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool, addNBSP bool) bool { ++ // edge of the buffer is likely to be a tag that we don't get to see, ++ // so we treat it like text sometimes ++ ++ // enumerate all sixteen possibilities for (previousChar, nextChar) ++ // each can be one of {0, space, punct, other} ++ switch { ++ case previousChar == 0 && nextChar == 0: ++ // context is not any help here, so toggle ++ *isOpen = !*isOpen ++ case isspace(previousChar) && nextChar == 0: ++ // [ "] might be [ "foo...] ++ *isOpen = true ++ case ispunct(previousChar) && nextChar == 0: ++ // [!"] hmm... could be [Run!"] or [("...] ++ *isOpen = false ++ case /* isnormal(previousChar) && */ nextChar == 0: ++ // [a"] is probably a close ++ *isOpen = false ++ case previousChar == 0 && isspace(nextChar): ++ // [" ] might be [...foo" ] ++ *isOpen = false ++ case isspace(previousChar) && isspace(nextChar): ++ // [ " ] context is not any help here, so toggle ++ *isOpen = !*isOpen ++ case ispunct(previousChar) && isspace(nextChar): ++ // [!" ] is probably a close ++ *isOpen = false ++ case /* isnormal(previousChar) && */ isspace(nextChar): ++ // [a" ] this is one of the easy cases ++ *isOpen = false ++ case previousChar == 0 && ispunct(nextChar): ++ // ["!] hmm... could be ["$1.95] or ["!...] ++ *isOpen = false ++ case isspace(previousChar) && ispunct(nextChar): ++ // [ "!] looks more like [ "$1.95] ++ *isOpen = true ++ case ispunct(previousChar) && ispunct(nextChar): ++ // [!"!] context is not any help here, so toggle ++ *isOpen = !*isOpen ++ case /* isnormal(previousChar) && */ ispunct(nextChar): ++ // [a"!] is probably a close ++ *isOpen = false ++ case previousChar == 0 /* && isnormal(nextChar) */ : ++ // ["a] is probably an open ++ *isOpen = true ++ case isspace(previousChar) /* && isnormal(nextChar) */ : ++ // [ "a] this is one of the easy cases ++ *isOpen = true ++ case ispunct(previousChar) /* && isnormal(nextChar) */ : ++ // [!"a] is probably an open ++ *isOpen = true ++ default: ++ // [a'b] maybe a contraction? ++ *isOpen = false ++ } ++ ++ // Note that with the limited lookahead, this non-breaking ++ // space will also be appended to single double quotes. ++ if addNBSP && !*isOpen { ++ out.WriteString(" ") ++ } ++ ++ out.WriteByte('&') ++ if *isOpen { ++ out.WriteByte('l') ++ } else { ++ out.WriteByte('r') ++ } ++ out.WriteByte(quote) ++ out.WriteString("quo;") ++ ++ if addNBSP && *isOpen { ++ out.WriteString(" ") ++ } ++ ++ return true ++} ++ ++func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 2 { ++ t1 := tolower(text[1]) ++ ++ if t1 == '\'' { ++ nextChar := byte(0) ++ if len(text) >= 3 { ++ nextChar = text[2] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { ++ return 1 ++ } ++ } ++ ++ if (t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') && (len(text) < 3 || wordBoundary(text[2])) { ++ out.WriteString("’") ++ return 0 ++ } ++ ++ if len(text) >= 3 { ++ t2 := tolower(text[2]) ++ ++ if ((t1 == 'r' && t2 == 'e') || (t1 == 'l' && t2 == 'l') || (t1 == 'v' && t2 == 'e')) && ++ (len(text) < 4 || wordBoundary(text[3])) { ++ out.WriteString("’") ++ return 0 ++ } ++ } ++ } ++ ++ nextChar := byte(0) ++ if len(text) > 1 { ++ nextChar = text[1] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, 's', &r.inSingleQuote, false) { ++ return 0 ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 3 { ++ t1 := tolower(text[1]) ++ t2 := tolower(text[2]) ++ ++ if t1 == 'c' && t2 == ')' { ++ out.WriteString("©") ++ return 2 ++ } ++ ++ if t1 == 'r' && t2 == ')' { ++ out.WriteString("®") ++ return 2 ++ } ++ ++ if len(text) >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')' { ++ out.WriteString("™") ++ return 3 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 2 { ++ if text[1] == '-' { ++ out.WriteString("—") ++ return 1 ++ } ++ ++ if wordBoundary(previousChar) && wordBoundary(text[1]) { ++ out.WriteString("–") ++ return 0 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 3 && text[1] == '-' && text[2] == '-' { ++ out.WriteString("—") ++ return 2 ++ } ++ if len(text) >= 2 && text[1] == '-' { ++ out.WriteString("–") ++ return 1 ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte, addNBSP bool) int { ++ if bytes.HasPrefix(text, []byte(""")) { ++ nextChar := byte(0) ++ if len(text) >= 7 { ++ nextChar = text[6] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, addNBSP) { ++ return 5 ++ } ++ } ++ ++ if bytes.HasPrefix(text, []byte("�")) { ++ return 3 ++ } ++ ++ out.WriteByte('&') ++ return 0 ++} ++ ++func (r *SPRenderer) smartAmp(angledQuotes, addNBSP bool) func(*bytes.Buffer, byte, []byte) int { ++ var quote byte = 'd' ++ if angledQuotes { ++ quote = 'a' ++ } ++ ++ return func(out *bytes.Buffer, previousChar byte, text []byte) int { ++ return r.smartAmpVariant(out, previousChar, text, quote, addNBSP) ++ } ++} ++ ++func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 3 && text[1] == '.' && text[2] == '.' { ++ out.WriteString("…") ++ return 2 ++ } ++ ++ if len(text) >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.' { ++ out.WriteString("…") ++ return 4 ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if len(text) >= 2 && text[1] == '`' { ++ nextChar := byte(0) ++ if len(text) >= 3 { ++ nextChar = text[2] ++ } ++ if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { ++ return 1 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { ++ // is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b ++ // note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8) ++ // and avoid changing dates like 1/23/2005 into fractions. ++ numEnd := 0 ++ for len(text) > numEnd && isdigit(text[numEnd]) { ++ numEnd++ ++ } ++ if numEnd == 0 { ++ out.WriteByte(text[0]) ++ return 0 ++ } ++ denStart := numEnd + 1 ++ if len(text) > numEnd+3 && text[numEnd] == 0xe2 && text[numEnd+1] == 0x81 && text[numEnd+2] == 0x84 { ++ denStart = numEnd + 3 ++ } else if len(text) < numEnd+2 || text[numEnd] != '/' { ++ out.WriteByte(text[0]) ++ return 0 ++ } ++ denEnd := denStart ++ for len(text) > denEnd && isdigit(text[denEnd]) { ++ denEnd++ ++ } ++ if denEnd == denStart { ++ out.WriteByte(text[0]) ++ return 0 ++ } ++ if len(text) == denEnd || wordBoundary(text[denEnd]) && text[denEnd] != '/' { ++ out.WriteString("") ++ out.Write(text[:numEnd]) ++ out.WriteString("") ++ out.Write(text[denStart:denEnd]) ++ out.WriteString("") ++ return denEnd - 1 ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int { ++ if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { ++ if text[0] == '1' && text[1] == '/' && text[2] == '2' { ++ if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' { ++ out.WriteString("½") ++ return 2 ++ } ++ } ++ ++ if text[0] == '1' && text[1] == '/' && text[2] == '4' { ++ if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h') { ++ out.WriteString("¼") ++ return 2 ++ } ++ } ++ ++ if text[0] == '3' && text[1] == '/' && text[2] == '4' { ++ if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's') { ++ out.WriteString("¾") ++ return 2 ++ } ++ } ++ } ++ ++ out.WriteByte(text[0]) ++ return 0 ++} ++ ++func (r *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { ++ nextChar := byte(0) ++ if len(text) > 1 { ++ nextChar = text[1] ++ } ++ if !smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, false) { ++ out.WriteString(""") ++ } ++ ++ return 0 ++} ++ ++func (r *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { ++ return r.smartDoubleQuoteVariant(out, previousChar, text, 'd') ++} ++ ++func (r *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { ++ return r.smartDoubleQuoteVariant(out, previousChar, text, 'a') ++} ++ ++func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int { ++ i := 0 ++ ++ for i < len(text) && text[i] != '>' { ++ i++ ++ } ++ ++ out.Write(text[:i+1]) ++ return i ++} ++ ++type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int ++ ++// NewSmartypantsRenderer constructs a Smartypants renderer object. ++func NewSmartypantsRenderer(flags HTMLFlags) *SPRenderer { ++ var ( ++ r SPRenderer ++ ++ smartAmpAngled = r.smartAmp(true, false) ++ smartAmpAngledNBSP = r.smartAmp(true, true) ++ smartAmpRegular = r.smartAmp(false, false) ++ smartAmpRegularNBSP = r.smartAmp(false, true) ++ ++ addNBSP = flags&SmartypantsQuotesNBSP != 0 ++ ) ++ ++ if flags&SmartypantsAngledQuotes == 0 { ++ r.callbacks['"'] = r.smartDoubleQuote ++ if !addNBSP { ++ r.callbacks['&'] = smartAmpRegular ++ } else { ++ r.callbacks['&'] = smartAmpRegularNBSP ++ } ++ } else { ++ r.callbacks['"'] = r.smartAngledDoubleQuote ++ if !addNBSP { ++ r.callbacks['&'] = smartAmpAngled ++ } else { ++ r.callbacks['&'] = smartAmpAngledNBSP ++ } ++ } ++ r.callbacks['\''] = r.smartSingleQuote ++ r.callbacks['('] = r.smartParens ++ if flags&SmartypantsDashes != 0 { ++ if flags&SmartypantsLatexDashes == 0 { ++ r.callbacks['-'] = r.smartDash ++ } else { ++ r.callbacks['-'] = r.smartDashLatex ++ } ++ } ++ r.callbacks['.'] = r.smartPeriod ++ if flags&SmartypantsFractions == 0 { ++ r.callbacks['1'] = r.smartNumber ++ r.callbacks['3'] = r.smartNumber ++ } else { ++ for ch := '1'; ch <= '9'; ch++ { ++ r.callbacks[ch] = r.smartNumberGeneric ++ } ++ } ++ r.callbacks['<'] = r.smartLeftAngle ++ r.callbacks['`'] = r.smartBacktick ++ return &r ++} ++ ++// Process is the entry point of the Smartypants renderer. ++func (r *SPRenderer) Process(w io.Writer, text []byte) { ++ mark := 0 ++ for i := 0; i < len(text); i++ { ++ if action := r.callbacks[text[i]]; action != nil { ++ if i > mark { ++ w.Write(text[mark:i]) ++ } ++ previousChar := byte(0) ++ if i > 0 { ++ previousChar = text[i-1] ++ } ++ var tmp bytes.Buffer ++ i += action(&tmp, previousChar, text[i:]) ++ w.Write(tmp.Bytes()) ++ mark = i + 1 ++ } ++ } ++ if mark < len(text) { ++ w.Write(text[mark:]) ++ } ++} +diff --git a/vendor/github.com/spf13/cobra/doc/README.md b/vendor/github.com/spf13/cobra/doc/README.md +new file mode 100644 +index 000000000000..8e07baae3307 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/README.md +@@ -0,0 +1,17 @@ ++# Documentation generation ++ ++- [Man page docs](./man_docs.md) ++- [Markdown docs](./md_docs.md) ++- [Rest docs](./rest_docs.md) ++- [Yaml docs](./yaml_docs.md) ++ ++## Options ++### `DisableAutoGenTag` ++ ++You may set `cmd.DisableAutoGenTag = true` ++to _entirely_ remove the auto generated string "Auto generated by spf13/cobra..." ++from any documentation source. ++ ++### `InitDefaultCompletionCmd` ++ ++You may call `cmd.InitDefaultCompletionCmd()` to document the default autocompletion command. +diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.go b/vendor/github.com/spf13/cobra/doc/man_docs.go +new file mode 100644 +index 000000000000..b5a2c596e96f +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/man_docs.go +@@ -0,0 +1,246 @@ ++// Copyright 2013-2022 The Cobra Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package doc ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strconv" ++ "strings" ++ "time" ++ ++ "github.com/cpuguy83/go-md2man/v2/md2man" ++ "github.com/spf13/cobra" ++ "github.com/spf13/pflag" ++) ++ ++// GenManTree will generate a man page for this command and all descendants ++// in the directory given. The header may be nil. This function may not work ++// correctly if your command names have `-` in them. If you have `cmd` with two ++// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` ++// it is undefined which help output will be in the file `cmd-sub-third.1`. ++func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error { ++ return GenManTreeFromOpts(cmd, GenManTreeOptions{ ++ Header: header, ++ Path: dir, ++ CommandSeparator: "-", ++ }) ++} ++ ++// GenManTreeFromOpts generates a man page for the command and all descendants. ++// The pages are written to the opts.Path directory. ++func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error { ++ header := opts.Header ++ if header == nil { ++ header = &GenManHeader{} ++ } ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenManTreeFromOpts(c, opts); err != nil { ++ return err ++ } ++ } ++ section := "1" ++ if header.Section != "" { ++ section = header.Section ++ } ++ ++ separator := "_" ++ if opts.CommandSeparator != "" { ++ separator = opts.CommandSeparator ++ } ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", separator) ++ filename := filepath.Join(opts.Path, basename+"."+section) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ headerCopy := *header ++ return GenMan(cmd, &headerCopy, f) ++} ++ ++// GenManTreeOptions is the options for generating the man pages. ++// Used only in GenManTreeFromOpts. ++type GenManTreeOptions struct { ++ Header *GenManHeader ++ Path string ++ CommandSeparator string ++} ++ ++// GenManHeader is a lot like the .TH header at the start of man pages. These ++// include the title, section, date, source, and manual. We will use the ++// current time if Date is unset and will use "Auto generated by spf13/cobra" ++// if the Source is unset. ++type GenManHeader struct { ++ Title string ++ Section string ++ Date *time.Time ++ date string ++ Source string ++ Manual string ++} ++ ++// GenMan will generate a man page for the given command and write it to ++// w. The header argument may be nil, however obviously w may not. ++func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error { ++ if header == nil { ++ header = &GenManHeader{} ++ } ++ if err := fillHeader(header, cmd.CommandPath(), cmd.DisableAutoGenTag); err != nil { ++ return err ++ } ++ ++ b := genMan(cmd, header) ++ _, err := w.Write(md2man.Render(b)) ++ return err ++} ++ ++func fillHeader(header *GenManHeader, name string, disableAutoGen bool) error { ++ if header.Title == "" { ++ header.Title = strings.ToUpper(strings.ReplaceAll(name, " ", "\\-")) ++ } ++ if header.Section == "" { ++ header.Section = "1" ++ } ++ if header.Date == nil { ++ now := time.Now() ++ if epoch := os.Getenv("SOURCE_DATE_EPOCH"); epoch != "" { ++ unixEpoch, err := strconv.ParseInt(epoch, 10, 64) ++ if err != nil { ++ return fmt.Errorf("invalid SOURCE_DATE_EPOCH: %v", err) ++ } ++ now = time.Unix(unixEpoch, 0) ++ } ++ header.Date = &now ++ } ++ header.date = (*header.Date).Format("Jan 2006") ++ if header.Source == "" && !disableAutoGen { ++ header.Source = "Auto generated by spf13/cobra" ++ } ++ return nil ++} ++ ++func manPreamble(buf io.StringWriter, header *GenManHeader, cmd *cobra.Command, dashedName string) { ++ description := cmd.Long ++ if len(description) == 0 { ++ description = cmd.Short ++ } ++ ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf(`%% "%s" "%s" "%s" "%s" "%s" ++# NAME ++`, header.Title, header.Section, header.date, header.Source, header.Manual)) ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf("%s \\- %s\n\n", dashedName, cmd.Short)) ++ cobra.WriteStringAndCheck(buf, "# SYNOPSIS\n") ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf("**%s**\n\n", cmd.UseLine())) ++ cobra.WriteStringAndCheck(buf, "# DESCRIPTION\n") ++ cobra.WriteStringAndCheck(buf, description+"\n\n") ++} ++ ++func manPrintFlags(buf io.StringWriter, flags *pflag.FlagSet) { ++ flags.VisitAll(func(flag *pflag.Flag) { ++ if len(flag.Deprecated) > 0 || flag.Hidden { ++ return ++ } ++ format := "" ++ if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { ++ format = fmt.Sprintf("**-%s**, **--%s**", flag.Shorthand, flag.Name) ++ } else { ++ format = fmt.Sprintf("**--%s**", flag.Name) ++ } ++ if len(flag.NoOptDefVal) > 0 { ++ format += "[" ++ } ++ if flag.Value.Type() == "string" { ++ // put quotes on the value ++ format += "=%q" ++ } else { ++ format += "=%s" ++ } ++ if len(flag.NoOptDefVal) > 0 { ++ format += "]" ++ } ++ format += "\n\t%s\n\n" ++ cobra.WriteStringAndCheck(buf, fmt.Sprintf(format, flag.DefValue, flag.Usage)) ++ }) ++} ++ ++func manPrintOptions(buf io.StringWriter, command *cobra.Command) { ++ flags := command.NonInheritedFlags() ++ if flags.HasAvailableFlags() { ++ cobra.WriteStringAndCheck(buf, "# OPTIONS\n") ++ manPrintFlags(buf, flags) ++ cobra.WriteStringAndCheck(buf, "\n") ++ } ++ flags = command.InheritedFlags() ++ if flags.HasAvailableFlags() { ++ cobra.WriteStringAndCheck(buf, "# OPTIONS INHERITED FROM PARENT COMMANDS\n") ++ manPrintFlags(buf, flags) ++ cobra.WriteStringAndCheck(buf, "\n") ++ } ++} ++ ++func genMan(cmd *cobra.Command, header *GenManHeader) []byte { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ // something like `rootcmd-subcmd1-subcmd2` ++ dashCommandName := strings.ReplaceAll(cmd.CommandPath(), " ", "-") ++ ++ buf := new(bytes.Buffer) ++ ++ manPreamble(buf, header, cmd, dashCommandName) ++ manPrintOptions(buf, cmd) ++ if len(cmd.Example) > 0 { ++ buf.WriteString("# EXAMPLE\n") ++ buf.WriteString(fmt.Sprintf("```\n%s\n```\n", cmd.Example)) ++ } ++ if hasSeeAlso(cmd) { ++ buf.WriteString("# SEE ALSO\n") ++ seealsos := make([]string, 0) ++ if cmd.HasParent() { ++ parentPath := cmd.Parent().CommandPath() ++ dashParentPath := strings.ReplaceAll(parentPath, " ", "-") ++ seealso := fmt.Sprintf("**%s(%s)**", dashParentPath, header.Section) ++ seealsos = append(seealsos, seealso) ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ for _, c := range children { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section) ++ seealsos = append(seealsos, seealso) ++ } ++ buf.WriteString(strings.Join(seealsos, ", ") + "\n") ++ } ++ if !cmd.DisableAutoGenTag { ++ buf.WriteString(fmt.Sprintf("# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006"))) ++ } ++ return buf.Bytes() ++} +diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.md b/vendor/github.com/spf13/cobra/doc/man_docs.md +new file mode 100644 +index 000000000000..3709160f34f0 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/man_docs.md +@@ -0,0 +1,31 @@ ++# Generating Man Pages For Your Own cobra.Command ++ ++Generating man pages from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ header := &doc.GenManHeader{ ++ Title: "MINE", ++ Section: "3", ++ } ++ err := doc.GenManTree(cmd, header, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a man page `/tmp/test.3` +diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.go b/vendor/github.com/spf13/cobra/doc/md_docs.go +new file mode 100644 +index 000000000000..bab4b496368c +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/md_docs.go +@@ -0,0 +1,156 @@ ++// Copyright 2013-2022 The Cobra Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package doc ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ "time" ++ ++ "github.com/spf13/cobra" ++) ++ ++func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) error { ++ flags := cmd.NonInheritedFlags() ++ flags.SetOutput(buf) ++ if flags.HasAvailableFlags() { ++ buf.WriteString("### Options\n\n```\n") ++ flags.PrintDefaults() ++ buf.WriteString("```\n\n") ++ } ++ ++ parentFlags := cmd.InheritedFlags() ++ parentFlags.SetOutput(buf) ++ if parentFlags.HasAvailableFlags() { ++ buf.WriteString("### Options inherited from parent commands\n\n```\n") ++ parentFlags.PrintDefaults() ++ buf.WriteString("```\n\n") ++ } ++ return nil ++} ++ ++// GenMarkdown creates markdown output. ++func GenMarkdown(cmd *cobra.Command, w io.Writer) error { ++ return GenMarkdownCustom(cmd, w, func(s string) string { return s }) ++} ++ ++// GenMarkdownCustom creates custom markdown output. ++func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ buf := new(bytes.Buffer) ++ name := cmd.CommandPath() ++ ++ buf.WriteString("## " + name + "\n\n") ++ buf.WriteString(cmd.Short + "\n\n") ++ if len(cmd.Long) > 0 { ++ buf.WriteString("### Synopsis\n\n") ++ buf.WriteString(cmd.Long + "\n\n") ++ } ++ ++ if cmd.Runnable() { ++ buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) ++ } ++ ++ if len(cmd.Example) > 0 { ++ buf.WriteString("### Examples\n\n") ++ buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example)) ++ } ++ ++ if err := printOptions(buf, cmd, name); err != nil { ++ return err ++ } ++ if hasSeeAlso(cmd) { ++ buf.WriteString("### SEE ALSO\n\n") ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ pname := parent.CommandPath() ++ link := pname + ".md" ++ link = strings.ReplaceAll(link, " ", "_") ++ buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short)) ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ cname := name + " " + child.Name() ++ link := cname + ".md" ++ link = strings.ReplaceAll(link, " ", "_") ++ buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short)) ++ } ++ buf.WriteString("\n") ++ } ++ if !cmd.DisableAutoGenTag { ++ buf.WriteString("###### Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "\n") ++ } ++ _, err := buf.WriteTo(w) ++ return err ++} ++ ++// GenMarkdownTree will generate a markdown page for this command and all ++// descendants in the directory given. The header may be nil. ++// This function may not work correctly if your command names have `-` in them. ++// If you have `cmd` with two subcmds, `sub` and `sub-third`, ++// and `sub` has a subcommand called `third`, it is undefined which ++// help output will be in the file `cmd-sub-third.1`. ++func GenMarkdownTree(cmd *cobra.Command, dir string) error { ++ identity := func(s string) string { return s } ++ emptyStr := func(s string) string { return "" } ++ return GenMarkdownTreeCustom(cmd, dir, emptyStr, identity) ++} ++ ++// GenMarkdownTreeCustom is the the same as GenMarkdownTree, but ++// with custom filePrepender and linkHandler. ++func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil { ++ return err ++ } ++ } ++ ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", "_") + ".md" ++ filename := filepath.Join(dir, basename) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(filename)); err != nil { ++ return err ++ } ++ if err := GenMarkdownCustom(cmd, f, linkHandler); err != nil { ++ return err ++ } ++ return nil ++} +diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.md b/vendor/github.com/spf13/cobra/doc/md_docs.md +new file mode 100644 +index 000000000000..1659175cfdab +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/md_docs.md +@@ -0,0 +1,115 @@ ++# Generating Markdown Docs For Your Own cobra.Command ++ ++Generating Markdown pages from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ err := doc.GenMarkdownTree(cmd, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a Markdown document `/tmp/test.md` ++ ++## Generate markdown docs for the entire command tree ++ ++This program can actually generate docs for the kubectl command in the kubernetes project ++ ++```go ++package main ++ ++import ( ++ "log" ++ "io/ioutil" ++ "os" ++ ++ "k8s.io/kubernetes/pkg/kubectl/cmd" ++ cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ++ ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) ++ err := doc.GenMarkdownTree(kubectl, "./") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") ++ ++## Generate markdown docs for a single command ++ ++You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenMarkdown` instead of `GenMarkdownTree` ++ ++```go ++ out := new(bytes.Buffer) ++ err := doc.GenMarkdown(cmd, out) ++ if err != nil { ++ log.Fatal(err) ++ } ++``` ++ ++This will write the markdown doc for ONLY "cmd" into the out, buffer. ++ ++## Customize the output ++ ++Both `GenMarkdown` and `GenMarkdownTree` have alternate versions with callbacks to get some control of the output: ++ ++```go ++func GenMarkdownTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++```go ++func GenMarkdownCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++The `filePrepender` will prepend the return value given the full filepath to the rendered Markdown file. A common use case is to add front matter to use the generated documentation with [Hugo](https://gohugo.io/): ++ ++```go ++const fmTemplate = `--- ++date: %s ++title: "%s" ++slug: %s ++url: %s ++--- ++` ++ ++filePrepender := func(filename string) string { ++ now := time.Now().Format(time.RFC3339) ++ name := filepath.Base(filename) ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ url := "/commands/" + strings.ToLower(base) + "/" ++ return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) ++} ++``` ++ ++The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename: ++ ++```go ++linkHandler := func(name string) string { ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ return "/commands/" + strings.ToLower(base) + "/" ++} ++``` +diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.go b/vendor/github.com/spf13/cobra/doc/rest_docs.go +new file mode 100644 +index 000000000000..d65890652dde +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/rest_docs.go +@@ -0,0 +1,186 @@ ++// Copyright 2013-2022 The Cobra Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package doc ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ "time" ++ ++ "github.com/spf13/cobra" ++) ++ ++func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error { ++ flags := cmd.NonInheritedFlags() ++ flags.SetOutput(buf) ++ if flags.HasAvailableFlags() { ++ buf.WriteString("Options\n") ++ buf.WriteString("~~~~~~~\n\n::\n\n") ++ flags.PrintDefaults() ++ buf.WriteString("\n") ++ } ++ ++ parentFlags := cmd.InheritedFlags() ++ parentFlags.SetOutput(buf) ++ if parentFlags.HasAvailableFlags() { ++ buf.WriteString("Options inherited from parent commands\n") ++ buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n") ++ parentFlags.PrintDefaults() ++ buf.WriteString("\n") ++ } ++ return nil ++} ++ ++// linkHandler for default ReST hyperlink markup ++func defaultLinkHandler(name, ref string) string { ++ return fmt.Sprintf("`%s <%s.rst>`_", name, ref) ++} ++ ++// GenReST creates reStructured Text output. ++func GenReST(cmd *cobra.Command, w io.Writer) error { ++ return GenReSTCustom(cmd, w, defaultLinkHandler) ++} ++ ++// GenReSTCustom creates custom reStructured Text output. ++func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, string) string) error { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ buf := new(bytes.Buffer) ++ name := cmd.CommandPath() ++ ++ short := cmd.Short ++ long := cmd.Long ++ if len(long) == 0 { ++ long = short ++ } ++ ref := strings.ReplaceAll(name, " ", "_") ++ ++ buf.WriteString(".. _" + ref + ":\n\n") ++ buf.WriteString(name + "\n") ++ buf.WriteString(strings.Repeat("-", len(name)) + "\n\n") ++ buf.WriteString(short + "\n\n") ++ buf.WriteString("Synopsis\n") ++ buf.WriteString("~~~~~~~~\n\n") ++ buf.WriteString("\n" + long + "\n\n") ++ ++ if cmd.Runnable() { ++ buf.WriteString(fmt.Sprintf("::\n\n %s\n\n", cmd.UseLine())) ++ } ++ ++ if len(cmd.Example) > 0 { ++ buf.WriteString("Examples\n") ++ buf.WriteString("~~~~~~~~\n\n") ++ buf.WriteString(fmt.Sprintf("::\n\n%s\n\n", indentString(cmd.Example, " "))) ++ } ++ ++ if err := printOptionsReST(buf, cmd, name); err != nil { ++ return err ++ } ++ if hasSeeAlso(cmd) { ++ buf.WriteString("SEE ALSO\n") ++ buf.WriteString("~~~~~~~~\n\n") ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ pname := parent.CommandPath() ++ ref = strings.ReplaceAll(pname, " ", "_") ++ buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(pname, ref), parent.Short)) ++ cmd.VisitParents(func(c *cobra.Command) { ++ if c.DisableAutoGenTag { ++ cmd.DisableAutoGenTag = c.DisableAutoGenTag ++ } ++ }) ++ } ++ ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ cname := name + " " + child.Name() ++ ref = strings.ReplaceAll(cname, " ", "_") ++ buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(cname, ref), child.Short)) ++ } ++ buf.WriteString("\n") ++ } ++ if !cmd.DisableAutoGenTag { ++ buf.WriteString("*Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "*\n") ++ } ++ _, err := buf.WriteTo(w) ++ return err ++} ++ ++// GenReSTTree will generate a ReST page for this command and all ++// descendants in the directory given. ++// This function may not work correctly if your command names have `-` in them. ++// If you have `cmd` with two subcmds, `sub` and `sub-third`, ++// and `sub` has a subcommand called `third`, it is undefined which ++// help output will be in the file `cmd-sub-third.1`. ++func GenReSTTree(cmd *cobra.Command, dir string) error { ++ emptyStr := func(s string) string { return "" } ++ return GenReSTTreeCustom(cmd, dir, emptyStr, defaultLinkHandler) ++} ++ ++// GenReSTTreeCustom is the the same as GenReSTTree, but ++// with custom filePrepender and linkHandler. ++func GenReSTTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenReSTTreeCustom(c, dir, filePrepender, linkHandler); err != nil { ++ return err ++ } ++ } ++ ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", "_") + ".rst" ++ filename := filepath.Join(dir, basename) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(filename)); err != nil { ++ return err ++ } ++ if err := GenReSTCustom(cmd, f, linkHandler); err != nil { ++ return err ++ } ++ return nil ++} ++ ++// adapted from: https://github.com/kr/text/blob/main/indent.go ++func indentString(s, p string) string { ++ var res []byte ++ b := []byte(s) ++ prefix := []byte(p) ++ bol := true ++ for _, c := range b { ++ if bol && c != '\n' { ++ res = append(res, prefix...) ++ } ++ res = append(res, c) ++ bol = c == '\n' ++ } ++ return string(res) ++} +diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.md b/vendor/github.com/spf13/cobra/doc/rest_docs.md +new file mode 100644 +index 000000000000..3041c573ab01 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/rest_docs.md +@@ -0,0 +1,114 @@ ++# Generating ReStructured Text Docs For Your Own cobra.Command ++ ++Generating ReST pages from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ err := doc.GenReSTTree(cmd, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a ReST document `/tmp/test.rst` ++ ++## Generate ReST docs for the entire command tree ++ ++This program can actually generate docs for the kubectl command in the kubernetes project ++ ++```go ++package main ++ ++import ( ++ "log" ++ "io/ioutil" ++ "os" ++ ++ "k8s.io/kubernetes/pkg/kubectl/cmd" ++ cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ++ ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) ++ err := doc.GenReSTTree(kubectl, "./") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") ++ ++## Generate ReST docs for a single command ++ ++You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenReST` instead of `GenReSTTree` ++ ++```go ++ out := new(bytes.Buffer) ++ err := doc.GenReST(cmd, out) ++ if err != nil { ++ log.Fatal(err) ++ } ++``` ++ ++This will write the ReST doc for ONLY "cmd" into the out, buffer. ++ ++## Customize the output ++ ++Both `GenReST` and `GenReSTTree` have alternate versions with callbacks to get some control of the output: ++ ++```go ++func GenReSTTreeCustom(cmd *Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { ++ //... ++} ++``` ++ ++```go ++func GenReSTCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string, string) string) error { ++ //... ++} ++``` ++ ++The `filePrepender` will prepend the return value given the full filepath to the rendered ReST file. A common use case is to add front matter to use the generated documentation with [Hugo](https://gohugo.io/): ++ ++```go ++const fmTemplate = `--- ++date: %s ++title: "%s" ++slug: %s ++url: %s ++--- ++` ++filePrepender := func(filename string) string { ++ now := time.Now().Format(time.RFC3339) ++ name := filepath.Base(filename) ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ url := "/commands/" + strings.ToLower(base) + "/" ++ return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) ++} ++``` ++ ++The `linkHandler` can be used to customize the rendered links to the commands, given a command name and reference. This is useful while converting rst to html or while generating documentation with tools like Sphinx where `:ref:` is used: ++ ++```go ++// Sphinx cross-referencing format ++linkHandler := func(name, ref string) string { ++ return fmt.Sprintf(":ref:`%s <%s>`", name, ref) ++} ++``` +diff --git a/vendor/github.com/spf13/cobra/doc/util.go b/vendor/github.com/spf13/cobra/doc/util.go +new file mode 100644 +index 000000000000..499ecdd919b9 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/util.go +@@ -0,0 +1,52 @@ ++// Copyright 2013-2022 The Cobra Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package doc ++ ++import ( ++ "strings" ++ ++ "github.com/spf13/cobra" ++) ++ ++// Test to see if we have a reason to print See Also information in docs ++// Basically this is a test for a parent command or a subcommand which is ++// both not deprecated and not the autogenerated help command. ++func hasSeeAlso(cmd *cobra.Command) bool { ++ if cmd.HasParent() { ++ return true ++ } ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ return true ++ } ++ return false ++} ++ ++// Temporary workaround for yaml lib generating incorrect yaml with long strings ++// that do not contain \n. ++func forceMultiLine(s string) string { ++ if len(s) > 60 && !strings.Contains(s, "\n") { ++ s = s + "\n" ++ } ++ return s ++} ++ ++type byName []*cobra.Command ++ ++func (s byName) Len() int { return len(s) } ++func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } ++func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } +diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.go b/vendor/github.com/spf13/cobra/doc/yaml_docs.go +new file mode 100644 +index 000000000000..12f8cf33b8f2 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.go +@@ -0,0 +1,175 @@ ++// Copyright 2013-2022 The Cobra Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package doc ++ ++import ( ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "sort" ++ "strings" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/pflag" ++ "gopkg.in/yaml.v3" ++) ++ ++type cmdOption struct { ++ Name string ++ Shorthand string `yaml:",omitempty"` ++ DefaultValue string `yaml:"default_value,omitempty"` ++ Usage string `yaml:",omitempty"` ++} ++ ++type cmdDoc struct { ++ Name string ++ Synopsis string `yaml:",omitempty"` ++ Description string `yaml:",omitempty"` ++ Usage string `yaml:",omitempty"` ++ Options []cmdOption `yaml:",omitempty"` ++ InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` ++ Example string `yaml:",omitempty"` ++ SeeAlso []string `yaml:"see_also,omitempty"` ++} ++ ++// GenYamlTree creates yaml structured ref files for this command and all descendants ++// in the directory given. This function may not work ++// correctly if your command names have `-` in them. If you have `cmd` with two ++// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` ++// it is undefined which help output will be in the file `cmd-sub-third.1`. ++func GenYamlTree(cmd *cobra.Command, dir string) error { ++ identity := func(s string) string { return s } ++ emptyStr := func(s string) string { return "" } ++ return GenYamlTreeCustom(cmd, dir, emptyStr, identity) ++} ++ ++// GenYamlTreeCustom creates yaml structured ref files. ++func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { ++ for _, c := range cmd.Commands() { ++ if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil { ++ return err ++ } ++ } ++ ++ basename := strings.ReplaceAll(cmd.CommandPath(), " ", "_") + ".yaml" ++ filename := filepath.Join(dir, basename) ++ f, err := os.Create(filename) ++ if err != nil { ++ return err ++ } ++ defer f.Close() ++ ++ if _, err := io.WriteString(f, filePrepender(filename)); err != nil { ++ return err ++ } ++ if err := GenYamlCustom(cmd, f, linkHandler); err != nil { ++ return err ++ } ++ return nil ++} ++ ++// GenYaml creates yaml output. ++func GenYaml(cmd *cobra.Command, w io.Writer) error { ++ return GenYamlCustom(cmd, w, func(s string) string { return s }) ++} ++ ++// GenYamlCustom creates custom yaml output. ++func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { ++ cmd.InitDefaultHelpCmd() ++ cmd.InitDefaultHelpFlag() ++ ++ yamlDoc := cmdDoc{} ++ yamlDoc.Name = cmd.CommandPath() ++ ++ yamlDoc.Synopsis = forceMultiLine(cmd.Short) ++ yamlDoc.Description = forceMultiLine(cmd.Long) ++ ++ if cmd.Runnable() { ++ yamlDoc.Usage = cmd.UseLine() ++ } ++ ++ if len(cmd.Example) > 0 { ++ yamlDoc.Example = cmd.Example ++ } ++ ++ flags := cmd.NonInheritedFlags() ++ if flags.HasFlags() { ++ yamlDoc.Options = genFlagResult(flags) ++ } ++ flags = cmd.InheritedFlags() ++ if flags.HasFlags() { ++ yamlDoc.InheritedOptions = genFlagResult(flags) ++ } ++ ++ if hasSeeAlso(cmd) { ++ result := []string{} ++ if cmd.HasParent() { ++ parent := cmd.Parent() ++ result = append(result, parent.CommandPath()+" - "+parent.Short) ++ } ++ children := cmd.Commands() ++ sort.Sort(byName(children)) ++ for _, child := range children { ++ if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { ++ continue ++ } ++ result = append(result, child.CommandPath()+" - "+child.Short) ++ } ++ yamlDoc.SeeAlso = result ++ } ++ ++ final, err := yaml.Marshal(&yamlDoc) ++ if err != nil { ++ fmt.Println(err) ++ os.Exit(1) ++ } ++ ++ if _, err := w.Write(final); err != nil { ++ return err ++ } ++ return nil ++} ++ ++func genFlagResult(flags *pflag.FlagSet) []cmdOption { ++ var result []cmdOption ++ ++ flags.VisitAll(func(flag *pflag.Flag) { ++ // Todo, when we mark a shorthand is deprecated, but specify an empty message. ++ // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. ++ // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. ++ if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { ++ opt := cmdOption{ ++ flag.Name, ++ flag.Shorthand, ++ flag.DefValue, ++ forceMultiLine(flag.Usage), ++ } ++ result = append(result, opt) ++ } else { ++ opt := cmdOption{ ++ Name: flag.Name, ++ DefaultValue: forceMultiLine(flag.DefValue), ++ Usage: forceMultiLine(flag.Usage), ++ } ++ result = append(result, opt) ++ } ++ }) ++ ++ return result ++} +diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.md b/vendor/github.com/spf13/cobra/doc/yaml_docs.md +new file mode 100644 +index 000000000000..172e61d12145 +--- /dev/null ++++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.md +@@ -0,0 +1,112 @@ ++# Generating Yaml Docs For Your Own cobra.Command ++ ++Generating yaml files from a cobra command is incredibly easy. An example is as follows: ++ ++```go ++package main ++ ++import ( ++ "log" ++ ++ "github.com/spf13/cobra" ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ cmd := &cobra.Command{ ++ Use: "test", ++ Short: "my test program", ++ } ++ err := doc.GenYamlTree(cmd, "/tmp") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++That will get you a Yaml document `/tmp/test.yaml` ++ ++## Generate yaml docs for the entire command tree ++ ++This program can actually generate docs for the kubectl command in the kubernetes project ++ ++```go ++package main ++ ++import ( ++ "io/ioutil" ++ "log" ++ "os" ++ ++ "k8s.io/kubernetes/pkg/kubectl/cmd" ++ cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ++ ++ "github.com/spf13/cobra/doc" ++) ++ ++func main() { ++ kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) ++ err := doc.GenYamlTree(kubectl, "./") ++ if err != nil { ++ log.Fatal(err) ++ } ++} ++``` ++ ++This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") ++ ++## Generate yaml docs for a single command ++ ++You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenYaml` instead of `GenYamlTree` ++ ++```go ++ out := new(bytes.Buffer) ++ doc.GenYaml(cmd, out) ++``` ++ ++This will write the yaml doc for ONLY "cmd" into the out, buffer. ++ ++## Customize the output ++ ++Both `GenYaml` and `GenYamlTree` have alternate versions with callbacks to get some control of the output: ++ ++```go ++func GenYamlTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++```go ++func GenYamlCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error { ++ //... ++} ++``` ++ ++The `filePrepender` will prepend the return value given the full filepath to the rendered Yaml file. A common use case is to add front matter to use the generated documentation with [Hugo](https://gohugo.io/): ++ ++```go ++const fmTemplate = `--- ++date: %s ++title: "%s" ++slug: %s ++url: %s ++--- ++` ++ ++filePrepender := func(filename string) string { ++ now := time.Now().Format(time.RFC3339) ++ name := filepath.Base(filename) ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ url := "/commands/" + strings.ToLower(base) + "/" ++ return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) ++} ++``` ++ ++The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename: ++ ++```go ++linkHandler := func(name string) string { ++ base := strings.TrimSuffix(name, path.Ext(name)) ++ return "/commands/" + strings.ToLower(base) + "/" ++} ++``` +diff --git a/vendor/gopkg.in/yaml.v3/LICENSE b/vendor/gopkg.in/yaml.v3/LICENSE +new file mode 100644 +index 000000000000..2683e4bb1f24 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/LICENSE +@@ -0,0 +1,50 @@ ++ ++This project is covered by two different licenses: MIT and Apache. ++ ++#### MIT License #### ++ ++The following files were ported to Go from C files of libyaml, and thus ++are still covered by their original MIT license, with the additional ++copyright staring in 2011 when the project was ported over: ++ ++ apic.go emitterc.go parserc.go readerc.go scannerc.go ++ writerc.go yamlh.go yamlprivateh.go ++ ++Copyright (c) 2006-2010 Kirill Simonov ++Copyright (c) 2006-2011 Kirill Simonov ++ ++Permission is hereby granted, free of charge, to any person obtaining a copy of ++this software and associated documentation files (the "Software"), to deal in ++the Software without restriction, including without limitation the rights to ++use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++of the Software, and to permit persons to whom the Software is furnished to do ++so, subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in all ++copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++SOFTWARE. ++ ++### Apache License ### ++ ++All the remaining project files are covered by the Apache license: ++ ++Copyright (c) 2011-2019 Canonical Ltd ++ ++Licensed under the Apache License, Version 2.0 (the "License"); ++you may not use this file except in compliance with the License. ++You may obtain a copy of the License at ++ ++ http://www.apache.org/licenses/LICENSE-2.0 ++ ++Unless required by applicable law or agreed to in writing, software ++distributed under the License is distributed on an "AS IS" BASIS, ++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++See the License for the specific language governing permissions and ++limitations under the License. +diff --git a/vendor/gopkg.in/yaml.v3/NOTICE b/vendor/gopkg.in/yaml.v3/NOTICE +new file mode 100644 +index 000000000000..866d74a7ad79 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/NOTICE +@@ -0,0 +1,13 @@ ++Copyright 2011-2016 Canonical Ltd. ++ ++Licensed under the Apache License, Version 2.0 (the "License"); ++you may not use this file except in compliance with the License. ++You may obtain a copy of the License at ++ ++ http://www.apache.org/licenses/LICENSE-2.0 ++ ++Unless required by applicable law or agreed to in writing, software ++distributed under the License is distributed on an "AS IS" BASIS, ++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++See the License for the specific language governing permissions and ++limitations under the License. +diff --git a/vendor/gopkg.in/yaml.v3/README.md b/vendor/gopkg.in/yaml.v3/README.md +new file mode 100644 +index 000000000000..08eb1babddfa +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/README.md +@@ -0,0 +1,150 @@ ++# YAML support for the Go language ++ ++Introduction ++------------ ++ ++The yaml package enables Go programs to comfortably encode and decode YAML ++values. It was developed within [Canonical](https://www.canonical.com) as ++part of the [juju](https://juju.ubuntu.com) project, and is based on a ++pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) ++C library to parse and generate YAML data quickly and reliably. ++ ++Compatibility ++------------- ++ ++The yaml package supports most of YAML 1.2, but preserves some behavior ++from 1.1 for backwards compatibility. ++ ++Specifically, as of v3 of the yaml package: ++ ++ - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being ++ decoded into a typed bool value. Otherwise they behave as a string. Booleans ++ in YAML 1.2 are _true/false_ only. ++ - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_ ++ as specified in YAML 1.2, because most parsers still use the old format. ++ Octals in the _0o777_ format are supported though, so new files work. ++ - Does not support base-60 floats. These are gone from YAML 1.2, and were ++ actually never supported by this package as it's clearly a poor choice. ++ ++and offers backwards ++compatibility with YAML 1.1 in some cases. ++1.2, including support for ++anchors, tags, map merging, etc. Multi-document unmarshalling is not yet ++implemented, and base-60 floats from YAML 1.1 are purposefully not ++supported since they're a poor design and are gone in YAML 1.2. ++ ++Installation and usage ++---------------------- ++ ++The import path for the package is *gopkg.in/yaml.v3*. ++ ++To install it, run: ++ ++ go get gopkg.in/yaml.v3 ++ ++API documentation ++----------------- ++ ++If opened in a browser, the import path itself leads to the API documentation: ++ ++ - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) ++ ++API stability ++------------- ++ ++The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). ++ ++ ++License ++------- ++ ++The yaml package is licensed under the MIT and Apache License 2.0 licenses. ++Please see the LICENSE file for details. ++ ++ ++Example ++------- ++ ++```Go ++package main ++ ++import ( ++ "fmt" ++ "log" ++ ++ "gopkg.in/yaml.v3" ++) ++ ++var data = ` ++a: Easy! ++b: ++ c: 2 ++ d: [3, 4] ++` ++ ++// Note: struct fields must be public in order for unmarshal to ++// correctly populate the data. ++type T struct { ++ A string ++ B struct { ++ RenamedC int `yaml:"c"` ++ D []int `yaml:",flow"` ++ } ++} ++ ++func main() { ++ t := T{} ++ ++ err := yaml.Unmarshal([]byte(data), &t) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- t:\n%v\n\n", t) ++ ++ d, err := yaml.Marshal(&t) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- t dump:\n%s\n\n", string(d)) ++ ++ m := make(map[interface{}]interface{}) ++ ++ err = yaml.Unmarshal([]byte(data), &m) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- m:\n%v\n\n", m) ++ ++ d, err = yaml.Marshal(&m) ++ if err != nil { ++ log.Fatalf("error: %v", err) ++ } ++ fmt.Printf("--- m dump:\n%s\n\n", string(d)) ++} ++``` ++ ++This example will generate the following output: ++ ++``` ++--- t: ++{Easy! {2 [3 4]}} ++ ++--- t dump: ++a: Easy! ++b: ++ c: 2 ++ d: [3, 4] ++ ++ ++--- m: ++map[a:Easy! b:map[c:2 d:[3 4]]] ++ ++--- m dump: ++a: Easy! ++b: ++ c: 2 ++ d: ++ - 3 ++ - 4 ++``` ++ +diff --git a/vendor/gopkg.in/yaml.v3/apic.go b/vendor/gopkg.in/yaml.v3/apic.go +new file mode 100644 +index 000000000000..ae7d049f182a +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/apic.go +@@ -0,0 +1,747 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++import ( ++ "io" ++) ++ ++func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { ++ //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) ++ ++ // Check if we can move the queue at the beginning of the buffer. ++ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { ++ if parser.tokens_head != len(parser.tokens) { ++ copy(parser.tokens, parser.tokens[parser.tokens_head:]) ++ } ++ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] ++ parser.tokens_head = 0 ++ } ++ parser.tokens = append(parser.tokens, *token) ++ if pos < 0 { ++ return ++ } ++ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) ++ parser.tokens[parser.tokens_head+pos] = *token ++} ++ ++// Create a new parser object. ++func yaml_parser_initialize(parser *yaml_parser_t) bool { ++ *parser = yaml_parser_t{ ++ raw_buffer: make([]byte, 0, input_raw_buffer_size), ++ buffer: make([]byte, 0, input_buffer_size), ++ } ++ return true ++} ++ ++// Destroy a parser object. ++func yaml_parser_delete(parser *yaml_parser_t) { ++ *parser = yaml_parser_t{} ++} ++ ++// String read handler. ++func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { ++ if parser.input_pos == len(parser.input) { ++ return 0, io.EOF ++ } ++ n = copy(buffer, parser.input[parser.input_pos:]) ++ parser.input_pos += n ++ return n, nil ++} ++ ++// Reader read handler. ++func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { ++ return parser.input_reader.Read(buffer) ++} ++ ++// Set a string input. ++func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { ++ if parser.read_handler != nil { ++ panic("must set the input source only once") ++ } ++ parser.read_handler = yaml_string_read_handler ++ parser.input = input ++ parser.input_pos = 0 ++} ++ ++// Set a file input. ++func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { ++ if parser.read_handler != nil { ++ panic("must set the input source only once") ++ } ++ parser.read_handler = yaml_reader_read_handler ++ parser.input_reader = r ++} ++ ++// Set the source encoding. ++func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { ++ if parser.encoding != yaml_ANY_ENCODING { ++ panic("must set the encoding only once") ++ } ++ parser.encoding = encoding ++} ++ ++// Create a new emitter object. ++func yaml_emitter_initialize(emitter *yaml_emitter_t) { ++ *emitter = yaml_emitter_t{ ++ buffer: make([]byte, output_buffer_size), ++ raw_buffer: make([]byte, 0, output_raw_buffer_size), ++ states: make([]yaml_emitter_state_t, 0, initial_stack_size), ++ events: make([]yaml_event_t, 0, initial_queue_size), ++ best_width: -1, ++ } ++} ++ ++// Destroy an emitter object. ++func yaml_emitter_delete(emitter *yaml_emitter_t) { ++ *emitter = yaml_emitter_t{} ++} ++ ++// String write handler. ++func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { ++ *emitter.output_buffer = append(*emitter.output_buffer, buffer...) ++ return nil ++} ++ ++// yaml_writer_write_handler uses emitter.output_writer to write the ++// emitted text. ++func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { ++ _, err := emitter.output_writer.Write(buffer) ++ return err ++} ++ ++// Set a string output. ++func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { ++ if emitter.write_handler != nil { ++ panic("must set the output target only once") ++ } ++ emitter.write_handler = yaml_string_write_handler ++ emitter.output_buffer = output_buffer ++} ++ ++// Set a file output. ++func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { ++ if emitter.write_handler != nil { ++ panic("must set the output target only once") ++ } ++ emitter.write_handler = yaml_writer_write_handler ++ emitter.output_writer = w ++} ++ ++// Set the output encoding. ++func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { ++ if emitter.encoding != yaml_ANY_ENCODING { ++ panic("must set the output encoding only once") ++ } ++ emitter.encoding = encoding ++} ++ ++// Set the canonical output style. ++func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { ++ emitter.canonical = canonical ++} ++ ++// Set the indentation increment. ++func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { ++ if indent < 2 || indent > 9 { ++ indent = 2 ++ } ++ emitter.best_indent = indent ++} ++ ++// Set the preferred line width. ++func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { ++ if width < 0 { ++ width = -1 ++ } ++ emitter.best_width = width ++} ++ ++// Set if unescaped non-ASCII characters are allowed. ++func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { ++ emitter.unicode = unicode ++} ++ ++// Set the preferred line break character. ++func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { ++ emitter.line_break = line_break ++} ++ ++///* ++// * Destroy a token object. ++// */ ++// ++//YAML_DECLARE(void) ++//yaml_token_delete(yaml_token_t *token) ++//{ ++// assert(token); // Non-NULL token object expected. ++// ++// switch (token.type) ++// { ++// case YAML_TAG_DIRECTIVE_TOKEN: ++// yaml_free(token.data.tag_directive.handle); ++// yaml_free(token.data.tag_directive.prefix); ++// break; ++// ++// case YAML_ALIAS_TOKEN: ++// yaml_free(token.data.alias.value); ++// break; ++// ++// case YAML_ANCHOR_TOKEN: ++// yaml_free(token.data.anchor.value); ++// break; ++// ++// case YAML_TAG_TOKEN: ++// yaml_free(token.data.tag.handle); ++// yaml_free(token.data.tag.suffix); ++// break; ++// ++// case YAML_SCALAR_TOKEN: ++// yaml_free(token.data.scalar.value); ++// break; ++// ++// default: ++// break; ++// } ++// ++// memset(token, 0, sizeof(yaml_token_t)); ++//} ++// ++///* ++// * Check if a string is a valid UTF-8 sequence. ++// * ++// * Check 'reader.c' for more details on UTF-8 encoding. ++// */ ++// ++//static int ++//yaml_check_utf8(yaml_char_t *start, size_t length) ++//{ ++// yaml_char_t *end = start+length; ++// yaml_char_t *pointer = start; ++// ++// while (pointer < end) { ++// unsigned char octet; ++// unsigned int width; ++// unsigned int value; ++// size_t k; ++// ++// octet = pointer[0]; ++// width = (octet & 0x80) == 0x00 ? 1 : ++// (octet & 0xE0) == 0xC0 ? 2 : ++// (octet & 0xF0) == 0xE0 ? 3 : ++// (octet & 0xF8) == 0xF0 ? 4 : 0; ++// value = (octet & 0x80) == 0x00 ? octet & 0x7F : ++// (octet & 0xE0) == 0xC0 ? octet & 0x1F : ++// (octet & 0xF0) == 0xE0 ? octet & 0x0F : ++// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; ++// if (!width) return 0; ++// if (pointer+width > end) return 0; ++// for (k = 1; k < width; k ++) { ++// octet = pointer[k]; ++// if ((octet & 0xC0) != 0x80) return 0; ++// value = (value << 6) + (octet & 0x3F); ++// } ++// if (!((width == 1) || ++// (width == 2 && value >= 0x80) || ++// (width == 3 && value >= 0x800) || ++// (width == 4 && value >= 0x10000))) return 0; ++// ++// pointer += width; ++// } ++// ++// return 1; ++//} ++// ++ ++// Create STREAM-START. ++func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_START_EVENT, ++ encoding: encoding, ++ } ++} ++ ++// Create STREAM-END. ++func yaml_stream_end_event_initialize(event *yaml_event_t) { ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_END_EVENT, ++ } ++} ++ ++// Create DOCUMENT-START. ++func yaml_document_start_event_initialize( ++ event *yaml_event_t, ++ version_directive *yaml_version_directive_t, ++ tag_directives []yaml_tag_directive_t, ++ implicit bool, ++) { ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_START_EVENT, ++ version_directive: version_directive, ++ tag_directives: tag_directives, ++ implicit: implicit, ++ } ++} ++ ++// Create DOCUMENT-END. ++func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_END_EVENT, ++ implicit: implicit, ++ } ++} ++ ++// Create ALIAS. ++func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool { ++ *event = yaml_event_t{ ++ typ: yaml_ALIAS_EVENT, ++ anchor: anchor, ++ } ++ return true ++} ++ ++// Create SCALAR. ++func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ anchor: anchor, ++ tag: tag, ++ value: value, ++ implicit: plain_implicit, ++ quoted_implicit: quoted_implicit, ++ style: yaml_style_t(style), ++ } ++ return true ++} ++ ++// Create SEQUENCE-START. ++func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(style), ++ } ++ return true ++} ++ ++// Create SEQUENCE-END. ++func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ } ++ return true ++} ++ ++// Create MAPPING-START. ++func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(style), ++ } ++} ++ ++// Create MAPPING-END. ++func yaml_mapping_end_event_initialize(event *yaml_event_t) { ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ } ++} ++ ++// Destroy an event object. ++func yaml_event_delete(event *yaml_event_t) { ++ *event = yaml_event_t{} ++} ++ ++///* ++// * Create a document object. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_initialize(document *yaml_document_t, ++// version_directive *yaml_version_directive_t, ++// tag_directives_start *yaml_tag_directive_t, ++// tag_directives_end *yaml_tag_directive_t, ++// start_implicit int, end_implicit int) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// struct { ++// start *yaml_node_t ++// end *yaml_node_t ++// top *yaml_node_t ++// } nodes = { NULL, NULL, NULL } ++// version_directive_copy *yaml_version_directive_t = NULL ++// struct { ++// start *yaml_tag_directive_t ++// end *yaml_tag_directive_t ++// top *yaml_tag_directive_t ++// } tag_directives_copy = { NULL, NULL, NULL } ++// value yaml_tag_directive_t = { NULL, NULL } ++// mark yaml_mark_t = { 0, 0, 0 } ++// ++// assert(document) // Non-NULL document object is expected. ++// assert((tag_directives_start && tag_directives_end) || ++// (tag_directives_start == tag_directives_end)) ++// // Valid tag directives are expected. ++// ++// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error ++// ++// if (version_directive) { ++// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) ++// if (!version_directive_copy) goto error ++// version_directive_copy.major = version_directive.major ++// version_directive_copy.minor = version_directive.minor ++// } ++// ++// if (tag_directives_start != tag_directives_end) { ++// tag_directive *yaml_tag_directive_t ++// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) ++// goto error ++// for (tag_directive = tag_directives_start ++// tag_directive != tag_directives_end; tag_directive ++) { ++// assert(tag_directive.handle) ++// assert(tag_directive.prefix) ++// if (!yaml_check_utf8(tag_directive.handle, ++// strlen((char *)tag_directive.handle))) ++// goto error ++// if (!yaml_check_utf8(tag_directive.prefix, ++// strlen((char *)tag_directive.prefix))) ++// goto error ++// value.handle = yaml_strdup(tag_directive.handle) ++// value.prefix = yaml_strdup(tag_directive.prefix) ++// if (!value.handle || !value.prefix) goto error ++// if (!PUSH(&context, tag_directives_copy, value)) ++// goto error ++// value.handle = NULL ++// value.prefix = NULL ++// } ++// } ++// ++// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, ++// tag_directives_copy.start, tag_directives_copy.top, ++// start_implicit, end_implicit, mark, mark) ++// ++// return 1 ++// ++//error: ++// STACK_DEL(&context, nodes) ++// yaml_free(version_directive_copy) ++// while (!STACK_EMPTY(&context, tag_directives_copy)) { ++// value yaml_tag_directive_t = POP(&context, tag_directives_copy) ++// yaml_free(value.handle) ++// yaml_free(value.prefix) ++// } ++// STACK_DEL(&context, tag_directives_copy) ++// yaml_free(value.handle) ++// yaml_free(value.prefix) ++// ++// return 0 ++//} ++// ++///* ++// * Destroy a document object. ++// */ ++// ++//YAML_DECLARE(void) ++//yaml_document_delete(document *yaml_document_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// tag_directive *yaml_tag_directive_t ++// ++// context.error = YAML_NO_ERROR // Eliminate a compiler warning. ++// ++// assert(document) // Non-NULL document object is expected. ++// ++// while (!STACK_EMPTY(&context, document.nodes)) { ++// node yaml_node_t = POP(&context, document.nodes) ++// yaml_free(node.tag) ++// switch (node.type) { ++// case YAML_SCALAR_NODE: ++// yaml_free(node.data.scalar.value) ++// break ++// case YAML_SEQUENCE_NODE: ++// STACK_DEL(&context, node.data.sequence.items) ++// break ++// case YAML_MAPPING_NODE: ++// STACK_DEL(&context, node.data.mapping.pairs) ++// break ++// default: ++// assert(0) // Should not happen. ++// } ++// } ++// STACK_DEL(&context, document.nodes) ++// ++// yaml_free(document.version_directive) ++// for (tag_directive = document.tag_directives.start ++// tag_directive != document.tag_directives.end ++// tag_directive++) { ++// yaml_free(tag_directive.handle) ++// yaml_free(tag_directive.prefix) ++// } ++// yaml_free(document.tag_directives.start) ++// ++// memset(document, 0, sizeof(yaml_document_t)) ++//} ++// ++///** ++// * Get a document node. ++// */ ++// ++//YAML_DECLARE(yaml_node_t *) ++//yaml_document_get_node(document *yaml_document_t, index int) ++//{ ++// assert(document) // Non-NULL document object is expected. ++// ++// if (index > 0 && document.nodes.start + index <= document.nodes.top) { ++// return document.nodes.start + index - 1 ++// } ++// return NULL ++//} ++// ++///** ++// * Get the root object. ++// */ ++// ++//YAML_DECLARE(yaml_node_t *) ++//yaml_document_get_root_node(document *yaml_document_t) ++//{ ++// assert(document) // Non-NULL document object is expected. ++// ++// if (document.nodes.top != document.nodes.start) { ++// return document.nodes.start ++// } ++// return NULL ++//} ++// ++///* ++// * Add a scalar node to a document. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_add_scalar(document *yaml_document_t, ++// tag *yaml_char_t, value *yaml_char_t, length int, ++// style yaml_scalar_style_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// mark yaml_mark_t = { 0, 0, 0 } ++// tag_copy *yaml_char_t = NULL ++// value_copy *yaml_char_t = NULL ++// node yaml_node_t ++// ++// assert(document) // Non-NULL document object is expected. ++// assert(value) // Non-NULL value is expected. ++// ++// if (!tag) { ++// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG ++// } ++// ++// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error ++// tag_copy = yaml_strdup(tag) ++// if (!tag_copy) goto error ++// ++// if (length < 0) { ++// length = strlen((char *)value) ++// } ++// ++// if (!yaml_check_utf8(value, length)) goto error ++// value_copy = yaml_malloc(length+1) ++// if (!value_copy) goto error ++// memcpy(value_copy, value, length) ++// value_copy[length] = '\0' ++// ++// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) ++// if (!PUSH(&context, document.nodes, node)) goto error ++// ++// return document.nodes.top - document.nodes.start ++// ++//error: ++// yaml_free(tag_copy) ++// yaml_free(value_copy) ++// ++// return 0 ++//} ++// ++///* ++// * Add a sequence node to a document. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_add_sequence(document *yaml_document_t, ++// tag *yaml_char_t, style yaml_sequence_style_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// mark yaml_mark_t = { 0, 0, 0 } ++// tag_copy *yaml_char_t = NULL ++// struct { ++// start *yaml_node_item_t ++// end *yaml_node_item_t ++// top *yaml_node_item_t ++// } items = { NULL, NULL, NULL } ++// node yaml_node_t ++// ++// assert(document) // Non-NULL document object is expected. ++// ++// if (!tag) { ++// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG ++// } ++// ++// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error ++// tag_copy = yaml_strdup(tag) ++// if (!tag_copy) goto error ++// ++// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error ++// ++// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, ++// style, mark, mark) ++// if (!PUSH(&context, document.nodes, node)) goto error ++// ++// return document.nodes.top - document.nodes.start ++// ++//error: ++// STACK_DEL(&context, items) ++// yaml_free(tag_copy) ++// ++// return 0 ++//} ++// ++///* ++// * Add a mapping node to a document. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_add_mapping(document *yaml_document_t, ++// tag *yaml_char_t, style yaml_mapping_style_t) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// mark yaml_mark_t = { 0, 0, 0 } ++// tag_copy *yaml_char_t = NULL ++// struct { ++// start *yaml_node_pair_t ++// end *yaml_node_pair_t ++// top *yaml_node_pair_t ++// } pairs = { NULL, NULL, NULL } ++// node yaml_node_t ++// ++// assert(document) // Non-NULL document object is expected. ++// ++// if (!tag) { ++// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG ++// } ++// ++// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error ++// tag_copy = yaml_strdup(tag) ++// if (!tag_copy) goto error ++// ++// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error ++// ++// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, ++// style, mark, mark) ++// if (!PUSH(&context, document.nodes, node)) goto error ++// ++// return document.nodes.top - document.nodes.start ++// ++//error: ++// STACK_DEL(&context, pairs) ++// yaml_free(tag_copy) ++// ++// return 0 ++//} ++// ++///* ++// * Append an item to a sequence node. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_append_sequence_item(document *yaml_document_t, ++// sequence int, item int) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// ++// assert(document) // Non-NULL document is required. ++// assert(sequence > 0 ++// && document.nodes.start + sequence <= document.nodes.top) ++// // Valid sequence id is required. ++// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) ++// // A sequence node is required. ++// assert(item > 0 && document.nodes.start + item <= document.nodes.top) ++// // Valid item id is required. ++// ++// if (!PUSH(&context, ++// document.nodes.start[sequence-1].data.sequence.items, item)) ++// return 0 ++// ++// return 1 ++//} ++// ++///* ++// * Append a pair of a key and a value to a mapping node. ++// */ ++// ++//YAML_DECLARE(int) ++//yaml_document_append_mapping_pair(document *yaml_document_t, ++// mapping int, key int, value int) ++//{ ++// struct { ++// error yaml_error_type_t ++// } context ++// ++// pair yaml_node_pair_t ++// ++// assert(document) // Non-NULL document is required. ++// assert(mapping > 0 ++// && document.nodes.start + mapping <= document.nodes.top) ++// // Valid mapping id is required. ++// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) ++// // A mapping node is required. ++// assert(key > 0 && document.nodes.start + key <= document.nodes.top) ++// // Valid key id is required. ++// assert(value > 0 && document.nodes.start + value <= document.nodes.top) ++// // Valid value id is required. ++// ++// pair.key = key ++// pair.value = value ++// ++// if (!PUSH(&context, ++// document.nodes.start[mapping-1].data.mapping.pairs, pair)) ++// return 0 ++// ++// return 1 ++//} ++// ++// +diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go +new file mode 100644 +index 000000000000..0173b6982e84 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/decode.go +@@ -0,0 +1,1000 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package yaml ++ ++import ( ++ "encoding" ++ "encoding/base64" ++ "fmt" ++ "io" ++ "math" ++ "reflect" ++ "strconv" ++ "time" ++) ++ ++// ---------------------------------------------------------------------------- ++// Parser, produces a node tree out of a libyaml event stream. ++ ++type parser struct { ++ parser yaml_parser_t ++ event yaml_event_t ++ doc *Node ++ anchors map[string]*Node ++ doneInit bool ++ textless bool ++} ++ ++func newParser(b []byte) *parser { ++ p := parser{} ++ if !yaml_parser_initialize(&p.parser) { ++ panic("failed to initialize YAML emitter") ++ } ++ if len(b) == 0 { ++ b = []byte{'\n'} ++ } ++ yaml_parser_set_input_string(&p.parser, b) ++ return &p ++} ++ ++func newParserFromReader(r io.Reader) *parser { ++ p := parser{} ++ if !yaml_parser_initialize(&p.parser) { ++ panic("failed to initialize YAML emitter") ++ } ++ yaml_parser_set_input_reader(&p.parser, r) ++ return &p ++} ++ ++func (p *parser) init() { ++ if p.doneInit { ++ return ++ } ++ p.anchors = make(map[string]*Node) ++ p.expect(yaml_STREAM_START_EVENT) ++ p.doneInit = true ++} ++ ++func (p *parser) destroy() { ++ if p.event.typ != yaml_NO_EVENT { ++ yaml_event_delete(&p.event) ++ } ++ yaml_parser_delete(&p.parser) ++} ++ ++// expect consumes an event from the event stream and ++// checks that it's of the expected type. ++func (p *parser) expect(e yaml_event_type_t) { ++ if p.event.typ == yaml_NO_EVENT { ++ if !yaml_parser_parse(&p.parser, &p.event) { ++ p.fail() ++ } ++ } ++ if p.event.typ == yaml_STREAM_END_EVENT { ++ failf("attempted to go past the end of stream; corrupted value?") ++ } ++ if p.event.typ != e { ++ p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) ++ p.fail() ++ } ++ yaml_event_delete(&p.event) ++ p.event.typ = yaml_NO_EVENT ++} ++ ++// peek peeks at the next event in the event stream, ++// puts the results into p.event and returns the event type. ++func (p *parser) peek() yaml_event_type_t { ++ if p.event.typ != yaml_NO_EVENT { ++ return p.event.typ ++ } ++ // It's curious choice from the underlying API to generally return a ++ // positive result on success, but on this case return true in an error ++ // scenario. This was the source of bugs in the past (issue #666). ++ if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { ++ p.fail() ++ } ++ return p.event.typ ++} ++ ++func (p *parser) fail() { ++ var where string ++ var line int ++ if p.parser.context_mark.line != 0 { ++ line = p.parser.context_mark.line ++ // Scanner errors don't iterate line before returning error ++ if p.parser.error == yaml_SCANNER_ERROR { ++ line++ ++ } ++ } else if p.parser.problem_mark.line != 0 { ++ line = p.parser.problem_mark.line ++ // Scanner errors don't iterate line before returning error ++ if p.parser.error == yaml_SCANNER_ERROR { ++ line++ ++ } ++ } ++ if line != 0 { ++ where = "line " + strconv.Itoa(line) + ": " ++ } ++ var msg string ++ if len(p.parser.problem) > 0 { ++ msg = p.parser.problem ++ } else { ++ msg = "unknown problem parsing YAML content" ++ } ++ failf("%s%s", where, msg) ++} ++ ++func (p *parser) anchor(n *Node, anchor []byte) { ++ if anchor != nil { ++ n.Anchor = string(anchor) ++ p.anchors[n.Anchor] = n ++ } ++} ++ ++func (p *parser) parse() *Node { ++ p.init() ++ switch p.peek() { ++ case yaml_SCALAR_EVENT: ++ return p.scalar() ++ case yaml_ALIAS_EVENT: ++ return p.alias() ++ case yaml_MAPPING_START_EVENT: ++ return p.mapping() ++ case yaml_SEQUENCE_START_EVENT: ++ return p.sequence() ++ case yaml_DOCUMENT_START_EVENT: ++ return p.document() ++ case yaml_STREAM_END_EVENT: ++ // Happens when attempting to decode an empty buffer. ++ return nil ++ case yaml_TAIL_COMMENT_EVENT: ++ panic("internal error: unexpected tail comment event (please report)") ++ default: ++ panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) ++ } ++} ++ ++func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { ++ var style Style ++ if tag != "" && tag != "!" { ++ tag = shortTag(tag) ++ style = TaggedStyle ++ } else if defaultTag != "" { ++ tag = defaultTag ++ } else if kind == ScalarNode { ++ tag, _ = resolve("", value) ++ } ++ n := &Node{ ++ Kind: kind, ++ Tag: tag, ++ Value: value, ++ Style: style, ++ } ++ if !p.textless { ++ n.Line = p.event.start_mark.line + 1 ++ n.Column = p.event.start_mark.column + 1 ++ n.HeadComment = string(p.event.head_comment) ++ n.LineComment = string(p.event.line_comment) ++ n.FootComment = string(p.event.foot_comment) ++ } ++ return n ++} ++ ++func (p *parser) parseChild(parent *Node) *Node { ++ child := p.parse() ++ parent.Content = append(parent.Content, child) ++ return child ++} ++ ++func (p *parser) document() *Node { ++ n := p.node(DocumentNode, "", "", "") ++ p.doc = n ++ p.expect(yaml_DOCUMENT_START_EVENT) ++ p.parseChild(n) ++ if p.peek() == yaml_DOCUMENT_END_EVENT { ++ n.FootComment = string(p.event.foot_comment) ++ } ++ p.expect(yaml_DOCUMENT_END_EVENT) ++ return n ++} ++ ++func (p *parser) alias() *Node { ++ n := p.node(AliasNode, "", "", string(p.event.anchor)) ++ n.Alias = p.anchors[n.Value] ++ if n.Alias == nil { ++ failf("unknown anchor '%s' referenced", n.Value) ++ } ++ p.expect(yaml_ALIAS_EVENT) ++ return n ++} ++ ++func (p *parser) scalar() *Node { ++ var parsedStyle = p.event.scalar_style() ++ var nodeStyle Style ++ switch { ++ case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: ++ nodeStyle = DoubleQuotedStyle ++ case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: ++ nodeStyle = SingleQuotedStyle ++ case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: ++ nodeStyle = LiteralStyle ++ case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: ++ nodeStyle = FoldedStyle ++ } ++ var nodeValue = string(p.event.value) ++ var nodeTag = string(p.event.tag) ++ var defaultTag string ++ if nodeStyle == 0 { ++ if nodeValue == "<<" { ++ defaultTag = mergeTag ++ } ++ } else { ++ defaultTag = strTag ++ } ++ n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) ++ n.Style |= nodeStyle ++ p.anchor(n, p.event.anchor) ++ p.expect(yaml_SCALAR_EVENT) ++ return n ++} ++ ++func (p *parser) sequence() *Node { ++ n := p.node(SequenceNode, seqTag, string(p.event.tag), "") ++ if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { ++ n.Style |= FlowStyle ++ } ++ p.anchor(n, p.event.anchor) ++ p.expect(yaml_SEQUENCE_START_EVENT) ++ for p.peek() != yaml_SEQUENCE_END_EVENT { ++ p.parseChild(n) ++ } ++ n.LineComment = string(p.event.line_comment) ++ n.FootComment = string(p.event.foot_comment) ++ p.expect(yaml_SEQUENCE_END_EVENT) ++ return n ++} ++ ++func (p *parser) mapping() *Node { ++ n := p.node(MappingNode, mapTag, string(p.event.tag), "") ++ block := true ++ if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { ++ block = false ++ n.Style |= FlowStyle ++ } ++ p.anchor(n, p.event.anchor) ++ p.expect(yaml_MAPPING_START_EVENT) ++ for p.peek() != yaml_MAPPING_END_EVENT { ++ k := p.parseChild(n) ++ if block && k.FootComment != "" { ++ // Must be a foot comment for the prior value when being dedented. ++ if len(n.Content) > 2 { ++ n.Content[len(n.Content)-3].FootComment = k.FootComment ++ k.FootComment = "" ++ } ++ } ++ v := p.parseChild(n) ++ if k.FootComment == "" && v.FootComment != "" { ++ k.FootComment = v.FootComment ++ v.FootComment = "" ++ } ++ if p.peek() == yaml_TAIL_COMMENT_EVENT { ++ if k.FootComment == "" { ++ k.FootComment = string(p.event.foot_comment) ++ } ++ p.expect(yaml_TAIL_COMMENT_EVENT) ++ } ++ } ++ n.LineComment = string(p.event.line_comment) ++ n.FootComment = string(p.event.foot_comment) ++ if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { ++ n.Content[len(n.Content)-2].FootComment = n.FootComment ++ n.FootComment = "" ++ } ++ p.expect(yaml_MAPPING_END_EVENT) ++ return n ++} ++ ++// ---------------------------------------------------------------------------- ++// Decoder, unmarshals a node into a provided value. ++ ++type decoder struct { ++ doc *Node ++ aliases map[*Node]bool ++ terrors []string ++ ++ stringMapType reflect.Type ++ generalMapType reflect.Type ++ ++ knownFields bool ++ uniqueKeys bool ++ decodeCount int ++ aliasCount int ++ aliasDepth int ++ ++ mergedFields map[interface{}]bool ++} ++ ++var ( ++ nodeType = reflect.TypeOf(Node{}) ++ durationType = reflect.TypeOf(time.Duration(0)) ++ stringMapType = reflect.TypeOf(map[string]interface{}{}) ++ generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) ++ ifaceType = generalMapType.Elem() ++ timeType = reflect.TypeOf(time.Time{}) ++ ptrTimeType = reflect.TypeOf(&time.Time{}) ++) ++ ++func newDecoder() *decoder { ++ d := &decoder{ ++ stringMapType: stringMapType, ++ generalMapType: generalMapType, ++ uniqueKeys: true, ++ } ++ d.aliases = make(map[*Node]bool) ++ return d ++} ++ ++func (d *decoder) terror(n *Node, tag string, out reflect.Value) { ++ if n.Tag != "" { ++ tag = n.Tag ++ } ++ value := n.Value ++ if tag != seqTag && tag != mapTag { ++ if len(value) > 10 { ++ value = " `" + value[:7] + "...`" ++ } else { ++ value = " `" + value + "`" ++ } ++ } ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) ++} ++ ++func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { ++ err := u.UnmarshalYAML(n) ++ if e, ok := err.(*TypeError); ok { ++ d.terrors = append(d.terrors, e.Errors...) ++ return false ++ } ++ if err != nil { ++ fail(err) ++ } ++ return true ++} ++ ++func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { ++ terrlen := len(d.terrors) ++ err := u.UnmarshalYAML(func(v interface{}) (err error) { ++ defer handleErr(&err) ++ d.unmarshal(n, reflect.ValueOf(v)) ++ if len(d.terrors) > terrlen { ++ issues := d.terrors[terrlen:] ++ d.terrors = d.terrors[:terrlen] ++ return &TypeError{issues} ++ } ++ return nil ++ }) ++ if e, ok := err.(*TypeError); ok { ++ d.terrors = append(d.terrors, e.Errors...) ++ return false ++ } ++ if err != nil { ++ fail(err) ++ } ++ return true ++} ++ ++// d.prepare initializes and dereferences pointers and calls UnmarshalYAML ++// if a value is found to implement it. ++// It returns the initialized and dereferenced out value, whether ++// unmarshalling was already done by UnmarshalYAML, and if so whether ++// its types unmarshalled appropriately. ++// ++// If n holds a null value, prepare returns before doing anything. ++func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { ++ if n.ShortTag() == nullTag { ++ return out, false, false ++ } ++ again := true ++ for again { ++ again = false ++ if out.Kind() == reflect.Ptr { ++ if out.IsNil() { ++ out.Set(reflect.New(out.Type().Elem())) ++ } ++ out = out.Elem() ++ again = true ++ } ++ if out.CanAddr() { ++ outi := out.Addr().Interface() ++ if u, ok := outi.(Unmarshaler); ok { ++ good = d.callUnmarshaler(n, u) ++ return out, true, good ++ } ++ if u, ok := outi.(obsoleteUnmarshaler); ok { ++ good = d.callObsoleteUnmarshaler(n, u) ++ return out, true, good ++ } ++ } ++ } ++ return out, false, false ++} ++ ++func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { ++ if n.ShortTag() == nullTag { ++ return reflect.Value{} ++ } ++ for _, num := range index { ++ for { ++ if v.Kind() == reflect.Ptr { ++ if v.IsNil() { ++ v.Set(reflect.New(v.Type().Elem())) ++ } ++ v = v.Elem() ++ continue ++ } ++ break ++ } ++ v = v.Field(num) ++ } ++ return v ++} ++ ++const ( ++ // 400,000 decode operations is ~500kb of dense object declarations, or ++ // ~5kb of dense object declarations with 10000% alias expansion ++ alias_ratio_range_low = 400000 ++ ++ // 4,000,000 decode operations is ~5MB of dense object declarations, or ++ // ~4.5MB of dense object declarations with 10% alias expansion ++ alias_ratio_range_high = 4000000 ++ ++ // alias_ratio_range is the range over which we scale allowed alias ratios ++ alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) ++) ++ ++func allowedAliasRatio(decodeCount int) float64 { ++ switch { ++ case decodeCount <= alias_ratio_range_low: ++ // allow 99% to come from alias expansion for small-to-medium documents ++ return 0.99 ++ case decodeCount >= alias_ratio_range_high: ++ // allow 10% to come from alias expansion for very large documents ++ return 0.10 ++ default: ++ // scale smoothly from 99% down to 10% over the range. ++ // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. ++ // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). ++ return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) ++ } ++} ++ ++func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { ++ d.decodeCount++ ++ if d.aliasDepth > 0 { ++ d.aliasCount++ ++ } ++ if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { ++ failf("document contains excessive aliasing") ++ } ++ if out.Type() == nodeType { ++ out.Set(reflect.ValueOf(n).Elem()) ++ return true ++ } ++ switch n.Kind { ++ case DocumentNode: ++ return d.document(n, out) ++ case AliasNode: ++ return d.alias(n, out) ++ } ++ out, unmarshaled, good := d.prepare(n, out) ++ if unmarshaled { ++ return good ++ } ++ switch n.Kind { ++ case ScalarNode: ++ good = d.scalar(n, out) ++ case MappingNode: ++ good = d.mapping(n, out) ++ case SequenceNode: ++ good = d.sequence(n, out) ++ case 0: ++ if n.IsZero() { ++ return d.null(out) ++ } ++ fallthrough ++ default: ++ failf("cannot decode node with unknown kind %d", n.Kind) ++ } ++ return good ++} ++ ++func (d *decoder) document(n *Node, out reflect.Value) (good bool) { ++ if len(n.Content) == 1 { ++ d.doc = n ++ d.unmarshal(n.Content[0], out) ++ return true ++ } ++ return false ++} ++ ++func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { ++ if d.aliases[n] { ++ // TODO this could actually be allowed in some circumstances. ++ failf("anchor '%s' value contains itself", n.Value) ++ } ++ d.aliases[n] = true ++ d.aliasDepth++ ++ good = d.unmarshal(n.Alias, out) ++ d.aliasDepth-- ++ delete(d.aliases, n) ++ return good ++} ++ ++var zeroValue reflect.Value ++ ++func resetMap(out reflect.Value) { ++ for _, k := range out.MapKeys() { ++ out.SetMapIndex(k, zeroValue) ++ } ++} ++ ++func (d *decoder) null(out reflect.Value) bool { ++ if out.CanAddr() { ++ switch out.Kind() { ++ case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: ++ out.Set(reflect.Zero(out.Type())) ++ return true ++ } ++ } ++ return false ++} ++ ++func (d *decoder) scalar(n *Node, out reflect.Value) bool { ++ var tag string ++ var resolved interface{} ++ if n.indicatedString() { ++ tag = strTag ++ resolved = n.Value ++ } else { ++ tag, resolved = resolve(n.Tag, n.Value) ++ if tag == binaryTag { ++ data, err := base64.StdEncoding.DecodeString(resolved.(string)) ++ if err != nil { ++ failf("!!binary value contains invalid base64 data") ++ } ++ resolved = string(data) ++ } ++ } ++ if resolved == nil { ++ return d.null(out) ++ } ++ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { ++ // We've resolved to exactly the type we want, so use that. ++ out.Set(resolvedv) ++ return true ++ } ++ // Perhaps we can use the value as a TextUnmarshaler to ++ // set its value. ++ if out.CanAddr() { ++ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) ++ if ok { ++ var text []byte ++ if tag == binaryTag { ++ text = []byte(resolved.(string)) ++ } else { ++ // We let any value be unmarshaled into TextUnmarshaler. ++ // That might be more lax than we'd like, but the ++ // TextUnmarshaler itself should bowl out any dubious values. ++ text = []byte(n.Value) ++ } ++ err := u.UnmarshalText(text) ++ if err != nil { ++ fail(err) ++ } ++ return true ++ } ++ } ++ switch out.Kind() { ++ case reflect.String: ++ if tag == binaryTag { ++ out.SetString(resolved.(string)) ++ return true ++ } ++ out.SetString(n.Value) ++ return true ++ case reflect.Interface: ++ out.Set(reflect.ValueOf(resolved)) ++ return true ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ // This used to work in v2, but it's very unfriendly. ++ isDuration := out.Type() == durationType ++ ++ switch resolved := resolved.(type) { ++ case int: ++ if !isDuration && !out.OverflowInt(int64(resolved)) { ++ out.SetInt(int64(resolved)) ++ return true ++ } ++ case int64: ++ if !isDuration && !out.OverflowInt(resolved) { ++ out.SetInt(resolved) ++ return true ++ } ++ case uint64: ++ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { ++ out.SetInt(int64(resolved)) ++ return true ++ } ++ case float64: ++ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { ++ out.SetInt(int64(resolved)) ++ return true ++ } ++ case string: ++ if out.Type() == durationType { ++ d, err := time.ParseDuration(resolved) ++ if err == nil { ++ out.SetInt(int64(d)) ++ return true ++ } ++ } ++ } ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ switch resolved := resolved.(type) { ++ case int: ++ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ case int64: ++ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ case uint64: ++ if !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ case float64: ++ if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { ++ out.SetUint(uint64(resolved)) ++ return true ++ } ++ } ++ case reflect.Bool: ++ switch resolved := resolved.(type) { ++ case bool: ++ out.SetBool(resolved) ++ return true ++ case string: ++ // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). ++ // It only works if explicitly attempting to unmarshal into a typed bool value. ++ switch resolved { ++ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": ++ out.SetBool(true) ++ return true ++ case "n", "N", "no", "No", "NO", "off", "Off", "OFF": ++ out.SetBool(false) ++ return true ++ } ++ } ++ case reflect.Float32, reflect.Float64: ++ switch resolved := resolved.(type) { ++ case int: ++ out.SetFloat(float64(resolved)) ++ return true ++ case int64: ++ out.SetFloat(float64(resolved)) ++ return true ++ case uint64: ++ out.SetFloat(float64(resolved)) ++ return true ++ case float64: ++ out.SetFloat(resolved) ++ return true ++ } ++ case reflect.Struct: ++ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { ++ out.Set(resolvedv) ++ return true ++ } ++ case reflect.Ptr: ++ panic("yaml internal error: please report the issue") ++ } ++ d.terror(n, tag, out) ++ return false ++} ++ ++func settableValueOf(i interface{}) reflect.Value { ++ v := reflect.ValueOf(i) ++ sv := reflect.New(v.Type()).Elem() ++ sv.Set(v) ++ return sv ++} ++ ++func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { ++ l := len(n.Content) ++ ++ var iface reflect.Value ++ switch out.Kind() { ++ case reflect.Slice: ++ out.Set(reflect.MakeSlice(out.Type(), l, l)) ++ case reflect.Array: ++ if l != out.Len() { ++ failf("invalid array: want %d elements but got %d", out.Len(), l) ++ } ++ case reflect.Interface: ++ // No type hints. Will have to use a generic sequence. ++ iface = out ++ out = settableValueOf(make([]interface{}, l)) ++ default: ++ d.terror(n, seqTag, out) ++ return false ++ } ++ et := out.Type().Elem() ++ ++ j := 0 ++ for i := 0; i < l; i++ { ++ e := reflect.New(et).Elem() ++ if ok := d.unmarshal(n.Content[i], e); ok { ++ out.Index(j).Set(e) ++ j++ ++ } ++ } ++ if out.Kind() != reflect.Array { ++ out.Set(out.Slice(0, j)) ++ } ++ if iface.IsValid() { ++ iface.Set(out) ++ } ++ return true ++} ++ ++func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { ++ l := len(n.Content) ++ if d.uniqueKeys { ++ nerrs := len(d.terrors) ++ for i := 0; i < l; i += 2 { ++ ni := n.Content[i] ++ for j := i + 2; j < l; j += 2 { ++ nj := n.Content[j] ++ if ni.Kind == nj.Kind && ni.Value == nj.Value { ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) ++ } ++ } ++ } ++ if len(d.terrors) > nerrs { ++ return false ++ } ++ } ++ switch out.Kind() { ++ case reflect.Struct: ++ return d.mappingStruct(n, out) ++ case reflect.Map: ++ // okay ++ case reflect.Interface: ++ iface := out ++ if isStringMap(n) { ++ out = reflect.MakeMap(d.stringMapType) ++ } else { ++ out = reflect.MakeMap(d.generalMapType) ++ } ++ iface.Set(out) ++ default: ++ d.terror(n, mapTag, out) ++ return false ++ } ++ ++ outt := out.Type() ++ kt := outt.Key() ++ et := outt.Elem() ++ ++ stringMapType := d.stringMapType ++ generalMapType := d.generalMapType ++ if outt.Elem() == ifaceType { ++ if outt.Key().Kind() == reflect.String { ++ d.stringMapType = outt ++ } else if outt.Key() == ifaceType { ++ d.generalMapType = outt ++ } ++ } ++ ++ mergedFields := d.mergedFields ++ d.mergedFields = nil ++ ++ var mergeNode *Node ++ ++ mapIsNew := false ++ if out.IsNil() { ++ out.Set(reflect.MakeMap(outt)) ++ mapIsNew = true ++ } ++ for i := 0; i < l; i += 2 { ++ if isMerge(n.Content[i]) { ++ mergeNode = n.Content[i+1] ++ continue ++ } ++ k := reflect.New(kt).Elem() ++ if d.unmarshal(n.Content[i], k) { ++ if mergedFields != nil { ++ ki := k.Interface() ++ if mergedFields[ki] { ++ continue ++ } ++ mergedFields[ki] = true ++ } ++ kkind := k.Kind() ++ if kkind == reflect.Interface { ++ kkind = k.Elem().Kind() ++ } ++ if kkind == reflect.Map || kkind == reflect.Slice { ++ failf("invalid map key: %#v", k.Interface()) ++ } ++ e := reflect.New(et).Elem() ++ if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { ++ out.SetMapIndex(k, e) ++ } ++ } ++ } ++ ++ d.mergedFields = mergedFields ++ if mergeNode != nil { ++ d.merge(n, mergeNode, out) ++ } ++ ++ d.stringMapType = stringMapType ++ d.generalMapType = generalMapType ++ return true ++} ++ ++func isStringMap(n *Node) bool { ++ if n.Kind != MappingNode { ++ return false ++ } ++ l := len(n.Content) ++ for i := 0; i < l; i += 2 { ++ shortTag := n.Content[i].ShortTag() ++ if shortTag != strTag && shortTag != mergeTag { ++ return false ++ } ++ } ++ return true ++} ++ ++func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { ++ sinfo, err := getStructInfo(out.Type()) ++ if err != nil { ++ panic(err) ++ } ++ ++ var inlineMap reflect.Value ++ var elemType reflect.Type ++ if sinfo.InlineMap != -1 { ++ inlineMap = out.Field(sinfo.InlineMap) ++ elemType = inlineMap.Type().Elem() ++ } ++ ++ for _, index := range sinfo.InlineUnmarshalers { ++ field := d.fieldByIndex(n, out, index) ++ d.prepare(n, field) ++ } ++ ++ mergedFields := d.mergedFields ++ d.mergedFields = nil ++ var mergeNode *Node ++ var doneFields []bool ++ if d.uniqueKeys { ++ doneFields = make([]bool, len(sinfo.FieldsList)) ++ } ++ name := settableValueOf("") ++ l := len(n.Content) ++ for i := 0; i < l; i += 2 { ++ ni := n.Content[i] ++ if isMerge(ni) { ++ mergeNode = n.Content[i+1] ++ continue ++ } ++ if !d.unmarshal(ni, name) { ++ continue ++ } ++ sname := name.String() ++ if mergedFields != nil { ++ if mergedFields[sname] { ++ continue ++ } ++ mergedFields[sname] = true ++ } ++ if info, ok := sinfo.FieldsMap[sname]; ok { ++ if d.uniqueKeys { ++ if doneFields[info.Id] { ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) ++ continue ++ } ++ doneFields[info.Id] = true ++ } ++ var field reflect.Value ++ if info.Inline == nil { ++ field = out.Field(info.Num) ++ } else { ++ field = d.fieldByIndex(n, out, info.Inline) ++ } ++ d.unmarshal(n.Content[i+1], field) ++ } else if sinfo.InlineMap != -1 { ++ if inlineMap.IsNil() { ++ inlineMap.Set(reflect.MakeMap(inlineMap.Type())) ++ } ++ value := reflect.New(elemType).Elem() ++ d.unmarshal(n.Content[i+1], value) ++ inlineMap.SetMapIndex(name, value) ++ } else if d.knownFields { ++ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) ++ } ++ } ++ ++ d.mergedFields = mergedFields ++ if mergeNode != nil { ++ d.merge(n, mergeNode, out) ++ } ++ return true ++} ++ ++func failWantMap() { ++ failf("map merge requires map or sequence of maps as the value") ++} ++ ++func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { ++ mergedFields := d.mergedFields ++ if mergedFields == nil { ++ d.mergedFields = make(map[interface{}]bool) ++ for i := 0; i < len(parent.Content); i += 2 { ++ k := reflect.New(ifaceType).Elem() ++ if d.unmarshal(parent.Content[i], k) { ++ d.mergedFields[k.Interface()] = true ++ } ++ } ++ } ++ ++ switch merge.Kind { ++ case MappingNode: ++ d.unmarshal(merge, out) ++ case AliasNode: ++ if merge.Alias != nil && merge.Alias.Kind != MappingNode { ++ failWantMap() ++ } ++ d.unmarshal(merge, out) ++ case SequenceNode: ++ for i := 0; i < len(merge.Content); i++ { ++ ni := merge.Content[i] ++ if ni.Kind == AliasNode { ++ if ni.Alias != nil && ni.Alias.Kind != MappingNode { ++ failWantMap() ++ } ++ } else if ni.Kind != MappingNode { ++ failWantMap() ++ } ++ d.unmarshal(ni, out) ++ } ++ default: ++ failWantMap() ++ } ++ ++ d.mergedFields = mergedFields ++} ++ ++func isMerge(n *Node) bool { ++ return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) ++} +diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go +new file mode 100644 +index 000000000000..0f47c9ca8add +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/emitterc.go +@@ -0,0 +1,2020 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++import ( ++ "bytes" ++ "fmt" ++) ++ ++// Flush the buffer if needed. ++func flush(emitter *yaml_emitter_t) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) { ++ return yaml_emitter_flush(emitter) ++ } ++ return true ++} ++ ++// Put a character to the output buffer. ++func put(emitter *yaml_emitter_t, value byte) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { ++ return false ++ } ++ emitter.buffer[emitter.buffer_pos] = value ++ emitter.buffer_pos++ ++ emitter.column++ ++ return true ++} ++ ++// Put a line break to the output buffer. ++func put_break(emitter *yaml_emitter_t) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { ++ return false ++ } ++ switch emitter.line_break { ++ case yaml_CR_BREAK: ++ emitter.buffer[emitter.buffer_pos] = '\r' ++ emitter.buffer_pos += 1 ++ case yaml_LN_BREAK: ++ emitter.buffer[emitter.buffer_pos] = '\n' ++ emitter.buffer_pos += 1 ++ case yaml_CRLN_BREAK: ++ emitter.buffer[emitter.buffer_pos+0] = '\r' ++ emitter.buffer[emitter.buffer_pos+1] = '\n' ++ emitter.buffer_pos += 2 ++ default: ++ panic("unknown line break setting") ++ } ++ if emitter.column == 0 { ++ emitter.space_above = true ++ } ++ emitter.column = 0 ++ emitter.line++ ++ // [Go] Do this here and below and drop from everywhere else (see commented lines). ++ emitter.indention = true ++ return true ++} ++ ++// Copy a character from a string into buffer. ++func write(emitter *yaml_emitter_t, s []byte, i *int) bool { ++ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { ++ return false ++ } ++ p := emitter.buffer_pos ++ w := width(s[*i]) ++ switch w { ++ case 4: ++ emitter.buffer[p+3] = s[*i+3] ++ fallthrough ++ case 3: ++ emitter.buffer[p+2] = s[*i+2] ++ fallthrough ++ case 2: ++ emitter.buffer[p+1] = s[*i+1] ++ fallthrough ++ case 1: ++ emitter.buffer[p+0] = s[*i+0] ++ default: ++ panic("unknown character width") ++ } ++ emitter.column++ ++ emitter.buffer_pos += w ++ *i += w ++ return true ++} ++ ++// Write a whole string into buffer. ++func write_all(emitter *yaml_emitter_t, s []byte) bool { ++ for i := 0; i < len(s); { ++ if !write(emitter, s, &i) { ++ return false ++ } ++ } ++ return true ++} ++ ++// Copy a line break character from a string into buffer. ++func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { ++ if s[*i] == '\n' { ++ if !put_break(emitter) { ++ return false ++ } ++ *i++ ++ } else { ++ if !write(emitter, s, i) { ++ return false ++ } ++ if emitter.column == 0 { ++ emitter.space_above = true ++ } ++ emitter.column = 0 ++ emitter.line++ ++ // [Go] Do this here and above and drop from everywhere else (see commented lines). ++ emitter.indention = true ++ } ++ return true ++} ++ ++// Set an emitter error and return false. ++func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { ++ emitter.error = yaml_EMITTER_ERROR ++ emitter.problem = problem ++ return false ++} ++ ++// Emit an event. ++func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ emitter.events = append(emitter.events, *event) ++ for !yaml_emitter_need_more_events(emitter) { ++ event := &emitter.events[emitter.events_head] ++ if !yaml_emitter_analyze_event(emitter, event) { ++ return false ++ } ++ if !yaml_emitter_state_machine(emitter, event) { ++ return false ++ } ++ yaml_event_delete(event) ++ emitter.events_head++ ++ } ++ return true ++} ++ ++// Check if we need to accumulate more events before emitting. ++// ++// We accumulate extra ++// - 1 event for DOCUMENT-START ++// - 2 events for SEQUENCE-START ++// - 3 events for MAPPING-START ++// ++func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { ++ if emitter.events_head == len(emitter.events) { ++ return true ++ } ++ var accumulate int ++ switch emitter.events[emitter.events_head].typ { ++ case yaml_DOCUMENT_START_EVENT: ++ accumulate = 1 ++ break ++ case yaml_SEQUENCE_START_EVENT: ++ accumulate = 2 ++ break ++ case yaml_MAPPING_START_EVENT: ++ accumulate = 3 ++ break ++ default: ++ return false ++ } ++ if len(emitter.events)-emitter.events_head > accumulate { ++ return false ++ } ++ var level int ++ for i := emitter.events_head; i < len(emitter.events); i++ { ++ switch emitter.events[i].typ { ++ case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: ++ level++ ++ case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: ++ level-- ++ } ++ if level == 0 { ++ return false ++ } ++ } ++ return true ++} ++ ++// Append a directive to the directives stack. ++func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { ++ for i := 0; i < len(emitter.tag_directives); i++ { ++ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { ++ if allow_duplicates { ++ return true ++ } ++ return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") ++ } ++ } ++ ++ // [Go] Do we actually need to copy this given garbage collection ++ // and the lack of deallocating destructors? ++ tag_copy := yaml_tag_directive_t{ ++ handle: make([]byte, len(value.handle)), ++ prefix: make([]byte, len(value.prefix)), ++ } ++ copy(tag_copy.handle, value.handle) ++ copy(tag_copy.prefix, value.prefix) ++ emitter.tag_directives = append(emitter.tag_directives, tag_copy) ++ return true ++} ++ ++// Increase the indentation level. ++func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { ++ emitter.indents = append(emitter.indents, emitter.indent) ++ if emitter.indent < 0 { ++ if flow { ++ emitter.indent = emitter.best_indent ++ } else { ++ emitter.indent = 0 ++ } ++ } else if !indentless { ++ // [Go] This was changed so that indentations are more regular. ++ if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { ++ // The first indent inside a sequence will just skip the "- " indicator. ++ emitter.indent += 2 ++ } else { ++ // Everything else aligns to the chosen indentation. ++ emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent) ++ } ++ } ++ return true ++} ++ ++// State dispatcher. ++func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ switch emitter.state { ++ default: ++ case yaml_EMIT_STREAM_START_STATE: ++ return yaml_emitter_emit_stream_start(emitter, event) ++ ++ case yaml_EMIT_FIRST_DOCUMENT_START_STATE: ++ return yaml_emitter_emit_document_start(emitter, event, true) ++ ++ case yaml_EMIT_DOCUMENT_START_STATE: ++ return yaml_emitter_emit_document_start(emitter, event, false) ++ ++ case yaml_EMIT_DOCUMENT_CONTENT_STATE: ++ return yaml_emitter_emit_document_content(emitter, event) ++ ++ case yaml_EMIT_DOCUMENT_END_STATE: ++ return yaml_emitter_emit_document_end(emitter, event) ++ ++ case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: ++ return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false) ++ ++ case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE: ++ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true) ++ ++ case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: ++ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false) ++ ++ case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: ++ return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false) ++ ++ case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE: ++ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true) ++ ++ case yaml_EMIT_FLOW_MAPPING_KEY_STATE: ++ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false) ++ ++ case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: ++ return yaml_emitter_emit_flow_mapping_value(emitter, event, true) ++ ++ case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: ++ return yaml_emitter_emit_flow_mapping_value(emitter, event, false) ++ ++ case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: ++ return yaml_emitter_emit_block_sequence_item(emitter, event, true) ++ ++ case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: ++ return yaml_emitter_emit_block_sequence_item(emitter, event, false) ++ ++ case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: ++ return yaml_emitter_emit_block_mapping_key(emitter, event, true) ++ ++ case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: ++ return yaml_emitter_emit_block_mapping_key(emitter, event, false) ++ ++ case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: ++ return yaml_emitter_emit_block_mapping_value(emitter, event, true) ++ ++ case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: ++ return yaml_emitter_emit_block_mapping_value(emitter, event, false) ++ ++ case yaml_EMIT_END_STATE: ++ return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") ++ } ++ panic("invalid emitter state") ++} ++ ++// Expect STREAM-START. ++func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if event.typ != yaml_STREAM_START_EVENT { ++ return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") ++ } ++ if emitter.encoding == yaml_ANY_ENCODING { ++ emitter.encoding = event.encoding ++ if emitter.encoding == yaml_ANY_ENCODING { ++ emitter.encoding = yaml_UTF8_ENCODING ++ } ++ } ++ if emitter.best_indent < 2 || emitter.best_indent > 9 { ++ emitter.best_indent = 2 ++ } ++ if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { ++ emitter.best_width = 80 ++ } ++ if emitter.best_width < 0 { ++ emitter.best_width = 1<<31 - 1 ++ } ++ if emitter.line_break == yaml_ANY_BREAK { ++ emitter.line_break = yaml_LN_BREAK ++ } ++ ++ emitter.indent = -1 ++ emitter.line = 0 ++ emitter.column = 0 ++ emitter.whitespace = true ++ emitter.indention = true ++ emitter.space_above = true ++ emitter.foot_indent = -1 ++ ++ if emitter.encoding != yaml_UTF8_ENCODING { ++ if !yaml_emitter_write_bom(emitter) { ++ return false ++ } ++ } ++ emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE ++ return true ++} ++ ++// Expect DOCUMENT-START or STREAM-END. ++func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { ++ ++ if event.typ == yaml_DOCUMENT_START_EVENT { ++ ++ if event.version_directive != nil { ++ if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { ++ return false ++ } ++ } ++ ++ for i := 0; i < len(event.tag_directives); i++ { ++ tag_directive := &event.tag_directives[i] ++ if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { ++ return false ++ } ++ if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { ++ return false ++ } ++ } ++ ++ for i := 0; i < len(default_tag_directives); i++ { ++ tag_directive := &default_tag_directives[i] ++ if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { ++ return false ++ } ++ } ++ ++ implicit := event.implicit ++ if !first || emitter.canonical { ++ implicit = false ++ } ++ ++ if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { ++ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if event.version_directive != nil { ++ implicit = false ++ if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if len(event.tag_directives) > 0 { ++ implicit = false ++ for i := 0; i < len(event.tag_directives); i++ { ++ tag_directive := &event.tag_directives[i] ++ if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { ++ return false ++ } ++ if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ } ++ ++ if yaml_emitter_check_empty_document(emitter) { ++ implicit = false ++ } ++ if !implicit { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { ++ return false ++ } ++ if emitter.canonical || true { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ } ++ ++ if len(emitter.head_comment) > 0 { ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ ++ emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE ++ return true ++ } ++ ++ if event.typ == yaml_STREAM_END_EVENT { ++ if emitter.open_ended { ++ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_flush(emitter) { ++ return false ++ } ++ emitter.state = yaml_EMIT_END_STATE ++ return true ++ } ++ ++ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") ++} ++ ++// Expect the root node. ++func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) ++ ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_emit_node(emitter, event, true, false, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect DOCUMENT-END. ++func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if event.typ != yaml_DOCUMENT_END_EVENT { ++ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") ++ } ++ // [Go] Force document foot separation. ++ emitter.foot_indent = 0 ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ emitter.foot_indent = -1 ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !event.implicit { ++ // [Go] Allocate the slice elsewhere. ++ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_flush(emitter) { ++ return false ++ } ++ emitter.state = yaml_EMIT_DOCUMENT_START_STATE ++ emitter.tag_directives = emitter.tag_directives[:0] ++ return true ++} ++ ++// Expect a flow item node. ++func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { ++ if first { ++ if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { ++ return false ++ } ++ if !yaml_emitter_increase_indent(emitter, true, false) { ++ return false ++ } ++ emitter.flow_level++ ++ } ++ ++ if event.typ == yaml_SEQUENCE_END_EVENT { ++ if emitter.canonical && !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ emitter.flow_level-- ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ if emitter.column == 0 || emitter.canonical && !first { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ ++ return true ++ } ++ ++ if !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if emitter.column == 0 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if emitter.canonical || emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE) ++ } else { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) ++ } ++ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { ++ return false ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect a flow key node. ++func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { ++ if first { ++ if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { ++ return false ++ } ++ if !yaml_emitter_increase_indent(emitter, true, false) { ++ return false ++ } ++ emitter.flow_level++ ++ } ++ ++ if event.typ == yaml_MAPPING_END_EVENT { ++ if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ emitter.flow_level-- ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ if emitter.canonical && !first { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++ } ++ ++ if !first && !trail { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ ++ if emitter.column == 0 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if emitter.canonical || emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ ++ if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, true) ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { ++ return false ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, false) ++} ++ ++// Expect a flow value node. ++func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { ++ if simple { ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { ++ return false ++ } ++ } else { ++ if emitter.canonical || emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { ++ return false ++ } ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE) ++ } else { ++ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) ++ } ++ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { ++ return false ++ } ++ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { ++ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect a block item node. ++func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { ++ if first { ++ if !yaml_emitter_increase_indent(emitter, false, false) { ++ return false ++ } ++ } ++ if event.typ == yaml_SEQUENCE_END_EVENT { ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++ } ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { ++ return false ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) ++ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++// Expect a block key node. ++func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { ++ if first { ++ if !yaml_emitter_increase_indent(emitter, false, false) { ++ return false ++ } ++ } ++ if !yaml_emitter_process_head_comment(emitter) { ++ return false ++ } ++ if event.typ == yaml_MAPPING_END_EVENT { ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if len(emitter.line_comment) > 0 { ++ // [Go] A line comment was provided for the key. That's unusual as the ++ // scanner associates line comments with the value. Either way, ++ // save the line comment and render it appropriately later. ++ emitter.key_line_comment = emitter.line_comment ++ emitter.line_comment = nil ++ } ++ if yaml_emitter_check_simple_key(emitter) { ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, true) ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { ++ return false ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) ++ return yaml_emitter_emit_node(emitter, event, false, false, true, false) ++} ++ ++// Expect a block value node. ++func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { ++ if simple { ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { ++ return false ++ } ++ } else { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { ++ return false ++ } ++ } ++ if len(emitter.key_line_comment) > 0 { ++ // [Go] Line comments are generally associated with the value, but when there's ++ // no value on the same line as a mapping key they end up attached to the ++ // key itself. ++ if event.typ == yaml_SCALAR_EVENT { ++ if len(emitter.line_comment) == 0 { ++ // A scalar is coming and it has no line comments by itself yet, ++ // so just let it handle the line comment as usual. If it has a ++ // line comment, we can't have both so the one from the key is lost. ++ emitter.line_comment = emitter.key_line_comment ++ emitter.key_line_comment = nil ++ } ++ } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { ++ // An indented block follows, so write the comment right now. ++ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment ++ } ++ } ++ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) ++ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_foot_comment(emitter) { ++ return false ++ } ++ return true ++} ++ ++func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 ++} ++ ++// Expect a node. ++func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, ++ root bool, sequence bool, mapping bool, simple_key bool) bool { ++ ++ emitter.root_context = root ++ emitter.sequence_context = sequence ++ emitter.mapping_context = mapping ++ emitter.simple_key_context = simple_key ++ ++ switch event.typ { ++ case yaml_ALIAS_EVENT: ++ return yaml_emitter_emit_alias(emitter, event) ++ case yaml_SCALAR_EVENT: ++ return yaml_emitter_emit_scalar(emitter, event) ++ case yaml_SEQUENCE_START_EVENT: ++ return yaml_emitter_emit_sequence_start(emitter, event) ++ case yaml_MAPPING_START_EVENT: ++ return yaml_emitter_emit_mapping_start(emitter, event) ++ default: ++ return yaml_emitter_set_emitter_error(emitter, ++ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) ++ } ++} ++ ++// Expect ALIAS. ++func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++} ++ ++// Expect SCALAR. ++func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_select_scalar_style(emitter, event) { ++ return false ++ } ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_tag(emitter) { ++ return false ++ } ++ if !yaml_emitter_increase_indent(emitter, true, false) { ++ return false ++ } ++ if !yaml_emitter_process_scalar(emitter) { ++ return false ++ } ++ emitter.indent = emitter.indents[len(emitter.indents)-1] ++ emitter.indents = emitter.indents[:len(emitter.indents)-1] ++ emitter.state = emitter.states[len(emitter.states)-1] ++ emitter.states = emitter.states[:len(emitter.states)-1] ++ return true ++} ++ ++// Expect SEQUENCE-START. ++func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_tag(emitter) { ++ return false ++ } ++ if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || ++ yaml_emitter_check_empty_sequence(emitter) { ++ emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE ++ } else { ++ emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE ++ } ++ return true ++} ++ ++// Expect MAPPING-START. ++func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ if !yaml_emitter_process_anchor(emitter) { ++ return false ++ } ++ if !yaml_emitter_process_tag(emitter) { ++ return false ++ } ++ if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || ++ yaml_emitter_check_empty_mapping(emitter) { ++ emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE ++ } else { ++ emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE ++ } ++ return true ++} ++ ++// Check if the document content is an empty scalar. ++func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { ++ return false // [Go] Huh? ++} ++ ++// Check if the next events represent an empty sequence. ++func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { ++ if len(emitter.events)-emitter.events_head < 2 { ++ return false ++ } ++ return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && ++ emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT ++} ++ ++// Check if the next events represent an empty mapping. ++func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { ++ if len(emitter.events)-emitter.events_head < 2 { ++ return false ++ } ++ return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && ++ emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT ++} ++ ++// Check if the next node can be expressed as a simple key. ++func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { ++ length := 0 ++ switch emitter.events[emitter.events_head].typ { ++ case yaml_ALIAS_EVENT: ++ length += len(emitter.anchor_data.anchor) ++ case yaml_SCALAR_EVENT: ++ if emitter.scalar_data.multiline { ++ return false ++ } ++ length += len(emitter.anchor_data.anchor) + ++ len(emitter.tag_data.handle) + ++ len(emitter.tag_data.suffix) + ++ len(emitter.scalar_data.value) ++ case yaml_SEQUENCE_START_EVENT: ++ if !yaml_emitter_check_empty_sequence(emitter) { ++ return false ++ } ++ length += len(emitter.anchor_data.anchor) + ++ len(emitter.tag_data.handle) + ++ len(emitter.tag_data.suffix) ++ case yaml_MAPPING_START_EVENT: ++ if !yaml_emitter_check_empty_mapping(emitter) { ++ return false ++ } ++ length += len(emitter.anchor_data.anchor) + ++ len(emitter.tag_data.handle) + ++ len(emitter.tag_data.suffix) ++ default: ++ return false ++ } ++ return length <= 128 ++} ++ ++// Determine an acceptable scalar style. ++func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ ++ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 ++ if no_tag && !event.implicit && !event.quoted_implicit { ++ return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") ++ } ++ ++ style := event.scalar_style() ++ if style == yaml_ANY_SCALAR_STYLE { ++ style = yaml_PLAIN_SCALAR_STYLE ++ } ++ if emitter.canonical { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ if emitter.simple_key_context && emitter.scalar_data.multiline { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ ++ if style == yaml_PLAIN_SCALAR_STYLE { ++ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || ++ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ } ++ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ } ++ if no_tag && !event.implicit { ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ } ++ } ++ if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { ++ if !emitter.scalar_data.single_quoted_allowed { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ } ++ if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { ++ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ } ++ ++ if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { ++ emitter.tag_data.handle = []byte{'!'} ++ } ++ emitter.scalar_data.style = style ++ return true ++} ++ ++// Write an anchor. ++func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { ++ if emitter.anchor_data.anchor == nil { ++ return true ++ } ++ c := []byte{'&'} ++ if emitter.anchor_data.alias { ++ c[0] = '*' ++ } ++ if !yaml_emitter_write_indicator(emitter, c, true, false, false) { ++ return false ++ } ++ return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) ++} ++ ++// Write a tag. ++func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { ++ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { ++ return true ++ } ++ if len(emitter.tag_data.handle) > 0 { ++ if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { ++ return false ++ } ++ if len(emitter.tag_data.suffix) > 0 { ++ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { ++ return false ++ } ++ } ++ } else { ++ // [Go] Allocate these slices elsewhere. ++ if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { ++ return false ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { ++ return false ++ } ++ } ++ return true ++} ++ ++// Write a scalar. ++func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { ++ switch emitter.scalar_data.style { ++ case yaml_PLAIN_SCALAR_STYLE: ++ return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) ++ ++ case yaml_SINGLE_QUOTED_SCALAR_STYLE: ++ return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) ++ ++ case yaml_DOUBLE_QUOTED_SCALAR_STYLE: ++ return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) ++ ++ case yaml_LITERAL_SCALAR_STYLE: ++ return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) ++ ++ case yaml_FOLDED_SCALAR_STYLE: ++ return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) ++ } ++ panic("unknown scalar style") ++} ++ ++// Write a head comment. ++func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { ++ if len(emitter.tail_comment) > 0 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.tail_comment) { ++ return false ++ } ++ emitter.tail_comment = emitter.tail_comment[:0] ++ emitter.foot_indent = emitter.indent ++ if emitter.foot_indent < 0 { ++ emitter.foot_indent = 0 ++ } ++ } ++ ++ if len(emitter.head_comment) == 0 { ++ return true ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.head_comment) { ++ return false ++ } ++ emitter.head_comment = emitter.head_comment[:0] ++ return true ++} ++ ++// Write an line comment. ++func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool { ++ if len(emitter.line_comment) == 0 { ++ return true ++ } ++ if !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.line_comment) { ++ return false ++ } ++ emitter.line_comment = emitter.line_comment[:0] ++ return true ++} ++ ++// Write a foot comment. ++func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { ++ if len(emitter.foot_comment) == 0 { ++ return true ++ } ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !yaml_emitter_write_comment(emitter, emitter.foot_comment) { ++ return false ++ } ++ emitter.foot_comment = emitter.foot_comment[:0] ++ emitter.foot_indent = emitter.indent ++ if emitter.foot_indent < 0 { ++ emitter.foot_indent = 0 ++ } ++ return true ++} ++ ++// Check if a %YAML directive is valid. ++func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { ++ if version_directive.major != 1 || version_directive.minor != 1 { ++ return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") ++ } ++ return true ++} ++ ++// Check if a %TAG directive is valid. ++func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { ++ handle := tag_directive.handle ++ prefix := tag_directive.prefix ++ if len(handle) == 0 { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") ++ } ++ if handle[0] != '!' { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") ++ } ++ if handle[len(handle)-1] != '!' { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") ++ } ++ for i := 1; i < len(handle)-1; i += width(handle[i]) { ++ if !is_alpha(handle, i) { ++ return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") ++ } ++ } ++ if len(prefix) == 0 { ++ return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") ++ } ++ return true ++} ++ ++// Check if an anchor is valid. ++func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { ++ if len(anchor) == 0 { ++ problem := "anchor value must not be empty" ++ if alias { ++ problem = "alias value must not be empty" ++ } ++ return yaml_emitter_set_emitter_error(emitter, problem) ++ } ++ for i := 0; i < len(anchor); i += width(anchor[i]) { ++ if !is_alpha(anchor, i) { ++ problem := "anchor value must contain alphanumerical characters only" ++ if alias { ++ problem = "alias value must contain alphanumerical characters only" ++ } ++ return yaml_emitter_set_emitter_error(emitter, problem) ++ } ++ } ++ emitter.anchor_data.anchor = anchor ++ emitter.anchor_data.alias = alias ++ return true ++} ++ ++// Check if a tag is valid. ++func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { ++ if len(tag) == 0 { ++ return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") ++ } ++ for i := 0; i < len(emitter.tag_directives); i++ { ++ tag_directive := &emitter.tag_directives[i] ++ if bytes.HasPrefix(tag, tag_directive.prefix) { ++ emitter.tag_data.handle = tag_directive.handle ++ emitter.tag_data.suffix = tag[len(tag_directive.prefix):] ++ return true ++ } ++ } ++ emitter.tag_data.suffix = tag ++ return true ++} ++ ++// Check if a scalar is valid. ++func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { ++ var ( ++ block_indicators = false ++ flow_indicators = false ++ line_breaks = false ++ special_characters = false ++ tab_characters = false ++ ++ leading_space = false ++ leading_break = false ++ trailing_space = false ++ trailing_break = false ++ break_space = false ++ space_break = false ++ ++ preceded_by_whitespace = false ++ followed_by_whitespace = false ++ previous_space = false ++ previous_break = false ++ ) ++ ++ emitter.scalar_data.value = value ++ ++ if len(value) == 0 { ++ emitter.scalar_data.multiline = false ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = true ++ emitter.scalar_data.single_quoted_allowed = true ++ emitter.scalar_data.block_allowed = false ++ return true ++ } ++ ++ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { ++ block_indicators = true ++ flow_indicators = true ++ } ++ ++ preceded_by_whitespace = true ++ for i, w := 0, 0; i < len(value); i += w { ++ w = width(value[i]) ++ followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) ++ ++ if i == 0 { ++ switch value[i] { ++ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': ++ flow_indicators = true ++ block_indicators = true ++ case '?', ':': ++ flow_indicators = true ++ if followed_by_whitespace { ++ block_indicators = true ++ } ++ case '-': ++ if followed_by_whitespace { ++ flow_indicators = true ++ block_indicators = true ++ } ++ } ++ } else { ++ switch value[i] { ++ case ',', '?', '[', ']', '{', '}': ++ flow_indicators = true ++ case ':': ++ flow_indicators = true ++ if followed_by_whitespace { ++ block_indicators = true ++ } ++ case '#': ++ if preceded_by_whitespace { ++ flow_indicators = true ++ block_indicators = true ++ } ++ } ++ } ++ ++ if value[i] == '\t' { ++ tab_characters = true ++ } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { ++ special_characters = true ++ } ++ if is_space(value, i) { ++ if i == 0 { ++ leading_space = true ++ } ++ if i+width(value[i]) == len(value) { ++ trailing_space = true ++ } ++ if previous_break { ++ break_space = true ++ } ++ previous_space = true ++ previous_break = false ++ } else if is_break(value, i) { ++ line_breaks = true ++ if i == 0 { ++ leading_break = true ++ } ++ if i+width(value[i]) == len(value) { ++ trailing_break = true ++ } ++ if previous_space { ++ space_break = true ++ } ++ previous_space = false ++ previous_break = true ++ } else { ++ previous_space = false ++ previous_break = false ++ } ++ ++ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. ++ preceded_by_whitespace = is_blankz(value, i) ++ } ++ ++ emitter.scalar_data.multiline = line_breaks ++ emitter.scalar_data.flow_plain_allowed = true ++ emitter.scalar_data.block_plain_allowed = true ++ emitter.scalar_data.single_quoted_allowed = true ++ emitter.scalar_data.block_allowed = true ++ ++ if leading_space || leading_break || trailing_space || trailing_break { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ } ++ if trailing_space { ++ emitter.scalar_data.block_allowed = false ++ } ++ if break_space { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ emitter.scalar_data.single_quoted_allowed = false ++ } ++ if space_break || tab_characters || special_characters { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ emitter.scalar_data.single_quoted_allowed = false ++ } ++ if space_break || special_characters { ++ emitter.scalar_data.block_allowed = false ++ } ++ if line_breaks { ++ emitter.scalar_data.flow_plain_allowed = false ++ emitter.scalar_data.block_plain_allowed = false ++ } ++ if flow_indicators { ++ emitter.scalar_data.flow_plain_allowed = false ++ } ++ if block_indicators { ++ emitter.scalar_data.block_plain_allowed = false ++ } ++ return true ++} ++ ++// Check if the event data is valid. ++func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { ++ ++ emitter.anchor_data.anchor = nil ++ emitter.tag_data.handle = nil ++ emitter.tag_data.suffix = nil ++ emitter.scalar_data.value = nil ++ ++ if len(event.head_comment) > 0 { ++ emitter.head_comment = event.head_comment ++ } ++ if len(event.line_comment) > 0 { ++ emitter.line_comment = event.line_comment ++ } ++ if len(event.foot_comment) > 0 { ++ emitter.foot_comment = event.foot_comment ++ } ++ if len(event.tail_comment) > 0 { ++ emitter.tail_comment = event.tail_comment ++ } ++ ++ switch event.typ { ++ case yaml_ALIAS_EVENT: ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { ++ return false ++ } ++ ++ case yaml_SCALAR_EVENT: ++ if len(event.anchor) > 0 { ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { ++ return false ++ } ++ } ++ if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { ++ if !yaml_emitter_analyze_tag(emitter, event.tag) { ++ return false ++ } ++ } ++ if !yaml_emitter_analyze_scalar(emitter, event.value) { ++ return false ++ } ++ ++ case yaml_SEQUENCE_START_EVENT: ++ if len(event.anchor) > 0 { ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { ++ return false ++ } ++ } ++ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { ++ if !yaml_emitter_analyze_tag(emitter, event.tag) { ++ return false ++ } ++ } ++ ++ case yaml_MAPPING_START_EVENT: ++ if len(event.anchor) > 0 { ++ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { ++ return false ++ } ++ } ++ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { ++ if !yaml_emitter_analyze_tag(emitter, event.tag) { ++ return false ++ } ++ } ++ } ++ return true ++} ++ ++// Write the BOM character. ++func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { ++ if !flush(emitter) { ++ return false ++ } ++ pos := emitter.buffer_pos ++ emitter.buffer[pos+0] = '\xEF' ++ emitter.buffer[pos+1] = '\xBB' ++ emitter.buffer[pos+2] = '\xBF' ++ emitter.buffer_pos += 3 ++ return true ++} ++ ++func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { ++ indent := emitter.indent ++ if indent < 0 { ++ indent = 0 ++ } ++ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ if emitter.foot_indent == indent { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ for emitter.column < indent { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ emitter.whitespace = true ++ //emitter.indention = true ++ emitter.space_above = false ++ emitter.foot_indent = -1 ++ return true ++} ++ ++func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { ++ if need_whitespace && !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ if !write_all(emitter, indicator) { ++ return false ++ } ++ emitter.whitespace = is_whitespace ++ emitter.indention = (emitter.indention && is_indention) ++ emitter.open_ended = false ++ return true ++} ++ ++func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { ++ if !write_all(emitter, value) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { ++ if !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ if !write_all(emitter, value) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { ++ if need_whitespace && !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ for i := 0; i < len(value); { ++ var must_write bool ++ switch value[i] { ++ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': ++ must_write = true ++ default: ++ must_write = is_alpha(value, i) ++ } ++ if must_write { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } else { ++ w := width(value[i]) ++ for k := 0; k < w; k++ { ++ octet := value[i] ++ i++ ++ if !put(emitter, '%') { ++ return false ++ } ++ ++ c := octet >> 4 ++ if c < 10 { ++ c += '0' ++ } else { ++ c += 'A' - 10 ++ } ++ if !put(emitter, c) { ++ return false ++ } ++ ++ c = octet & 0x0f ++ if c < 10 { ++ c += '0' ++ } else { ++ c += 'A' - 10 ++ } ++ if !put(emitter, c) { ++ return false ++ } ++ } ++ } ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { ++ if len(value) > 0 && !emitter.whitespace { ++ if !put(emitter, ' ') { ++ return false ++ } ++ } ++ ++ spaces := false ++ breaks := false ++ for i := 0; i < len(value); { ++ if is_space(value, i) { ++ if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ i += width(value[i]) ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } ++ spaces = true ++ } else if is_break(value, i) { ++ if !breaks && value[i] == '\n' { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !write(emitter, value, &i) { ++ return false ++ } ++ emitter.indention = false ++ spaces = false ++ breaks = false ++ } ++ } ++ ++ if len(value) > 0 { ++ emitter.whitespace = false ++ } ++ emitter.indention = false ++ if emitter.root_context { ++ emitter.open_ended = true ++ } ++ ++ return true ++} ++ ++func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { ++ ++ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { ++ return false ++ } ++ ++ spaces := false ++ breaks := false ++ for i := 0; i < len(value); { ++ if is_space(value, i) { ++ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ i += width(value[i]) ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } ++ spaces = true ++ } else if is_break(value, i) { ++ if !breaks && value[i] == '\n' { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if value[i] == '\'' { ++ if !put(emitter, '\'') { ++ return false ++ } ++ } ++ if !write(emitter, value, &i) { ++ return false ++ } ++ emitter.indention = false ++ spaces = false ++ breaks = false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { ++ spaces := false ++ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { ++ return false ++ } ++ ++ for i := 0; i < len(value); { ++ if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || ++ is_bom(value, i) || is_break(value, i) || ++ value[i] == '"' || value[i] == '\\' { ++ ++ octet := value[i] ++ ++ var w int ++ var v rune ++ switch { ++ case octet&0x80 == 0x00: ++ w, v = 1, rune(octet&0x7F) ++ case octet&0xE0 == 0xC0: ++ w, v = 2, rune(octet&0x1F) ++ case octet&0xF0 == 0xE0: ++ w, v = 3, rune(octet&0x0F) ++ case octet&0xF8 == 0xF0: ++ w, v = 4, rune(octet&0x07) ++ } ++ for k := 1; k < w; k++ { ++ octet = value[i+k] ++ v = (v << 6) + (rune(octet) & 0x3F) ++ } ++ i += w ++ ++ if !put(emitter, '\\') { ++ return false ++ } ++ ++ var ok bool ++ switch v { ++ case 0x00: ++ ok = put(emitter, '0') ++ case 0x07: ++ ok = put(emitter, 'a') ++ case 0x08: ++ ok = put(emitter, 'b') ++ case 0x09: ++ ok = put(emitter, 't') ++ case 0x0A: ++ ok = put(emitter, 'n') ++ case 0x0b: ++ ok = put(emitter, 'v') ++ case 0x0c: ++ ok = put(emitter, 'f') ++ case 0x0d: ++ ok = put(emitter, 'r') ++ case 0x1b: ++ ok = put(emitter, 'e') ++ case 0x22: ++ ok = put(emitter, '"') ++ case 0x5c: ++ ok = put(emitter, '\\') ++ case 0x85: ++ ok = put(emitter, 'N') ++ case 0xA0: ++ ok = put(emitter, '_') ++ case 0x2028: ++ ok = put(emitter, 'L') ++ case 0x2029: ++ ok = put(emitter, 'P') ++ default: ++ if v <= 0xFF { ++ ok = put(emitter, 'x') ++ w = 2 ++ } else if v <= 0xFFFF { ++ ok = put(emitter, 'u') ++ w = 4 ++ } else { ++ ok = put(emitter, 'U') ++ w = 8 ++ } ++ for k := (w - 1) * 4; ok && k >= 0; k -= 4 { ++ digit := byte((v >> uint(k)) & 0x0F) ++ if digit < 10 { ++ ok = put(emitter, digit+'0') ++ } else { ++ ok = put(emitter, digit+'A'-10) ++ } ++ } ++ } ++ if !ok { ++ return false ++ } ++ spaces = false ++ } else if is_space(value, i) { ++ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if is_space(value, i+1) { ++ if !put(emitter, '\\') { ++ return false ++ } ++ } ++ i += width(value[i]) ++ } else if !write(emitter, value, &i) { ++ return false ++ } ++ spaces = true ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ spaces = false ++ } ++ } ++ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { ++ return false ++ } ++ emitter.whitespace = false ++ emitter.indention = false ++ return true ++} ++ ++func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { ++ if is_space(value, 0) || is_break(value, 0) { ++ indent_hint := []byte{'0' + byte(emitter.best_indent)} ++ if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { ++ return false ++ } ++ } ++ ++ emitter.open_ended = false ++ ++ var chomp_hint [1]byte ++ if len(value) == 0 { ++ chomp_hint[0] = '-' ++ } else { ++ i := len(value) - 1 ++ for value[i]&0xC0 == 0x80 { ++ i-- ++ } ++ if !is_break(value, i) { ++ chomp_hint[0] = '-' ++ } else if i == 0 { ++ chomp_hint[0] = '+' ++ emitter.open_ended = true ++ } else { ++ i-- ++ for value[i]&0xC0 == 0x80 { ++ i-- ++ } ++ if is_break(value, i) { ++ chomp_hint[0] = '+' ++ emitter.open_ended = true ++ } ++ } ++ } ++ if chomp_hint[0] != 0 { ++ if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { ++ return false ++ } ++ } ++ return true ++} ++ ++func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { ++ if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_block_scalar_hints(emitter, value) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ //emitter.indention = true ++ emitter.whitespace = true ++ breaks := true ++ for i := 0; i < len(value); { ++ if is_break(value, i) { ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ } ++ if !write(emitter, value, &i) { ++ return false ++ } ++ emitter.indention = false ++ breaks = false ++ } ++ } ++ ++ return true ++} ++ ++func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { ++ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { ++ return false ++ } ++ if !yaml_emitter_write_block_scalar_hints(emitter, value) { ++ return false ++ } ++ if !yaml_emitter_process_line_comment(emitter) { ++ return false ++ } ++ ++ //emitter.indention = true ++ emitter.whitespace = true ++ ++ breaks := true ++ leading_spaces := true ++ for i := 0; i < len(value); { ++ if is_break(value, i) { ++ if !breaks && !leading_spaces && value[i] == '\n' { ++ k := 0 ++ for is_break(value, k) { ++ k += width(value[k]) ++ } ++ if !is_blankz(value, k) { ++ if !put_break(emitter) { ++ return false ++ } ++ } ++ } ++ if !write_break(emitter, value, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ } else { ++ if breaks { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ leading_spaces = is_blank(value, i) ++ } ++ if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { ++ if !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ i += width(value[i]) ++ } else { ++ if !write(emitter, value, &i) { ++ return false ++ } ++ } ++ emitter.indention = false ++ breaks = false ++ } ++ } ++ return true ++} ++ ++func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool { ++ breaks := false ++ pound := false ++ for i := 0; i < len(comment); { ++ if is_break(comment, i) { ++ if !write_break(emitter, comment, &i) { ++ return false ++ } ++ //emitter.indention = true ++ breaks = true ++ pound = false ++ } else { ++ if breaks && !yaml_emitter_write_indent(emitter) { ++ return false ++ } ++ if !pound { ++ if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) { ++ return false ++ } ++ pound = true ++ } ++ if !write(emitter, comment, &i) { ++ return false ++ } ++ emitter.indention = false ++ breaks = false ++ } ++ } ++ if !breaks && !put_break(emitter) { ++ return false ++ } ++ ++ emitter.whitespace = true ++ //emitter.indention = true ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go +new file mode 100644 +index 000000000000..de9e72a3e638 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/encode.go +@@ -0,0 +1,577 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package yaml ++ ++import ( ++ "encoding" ++ "fmt" ++ "io" ++ "reflect" ++ "regexp" ++ "sort" ++ "strconv" ++ "strings" ++ "time" ++ "unicode/utf8" ++) ++ ++type encoder struct { ++ emitter yaml_emitter_t ++ event yaml_event_t ++ out []byte ++ flow bool ++ indent int ++ doneInit bool ++} ++ ++func newEncoder() *encoder { ++ e := &encoder{} ++ yaml_emitter_initialize(&e.emitter) ++ yaml_emitter_set_output_string(&e.emitter, &e.out) ++ yaml_emitter_set_unicode(&e.emitter, true) ++ return e ++} ++ ++func newEncoderWithWriter(w io.Writer) *encoder { ++ e := &encoder{} ++ yaml_emitter_initialize(&e.emitter) ++ yaml_emitter_set_output_writer(&e.emitter, w) ++ yaml_emitter_set_unicode(&e.emitter, true) ++ return e ++} ++ ++func (e *encoder) init() { ++ if e.doneInit { ++ return ++ } ++ if e.indent == 0 { ++ e.indent = 4 ++ } ++ e.emitter.best_indent = e.indent ++ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) ++ e.emit() ++ e.doneInit = true ++} ++ ++func (e *encoder) finish() { ++ e.emitter.open_ended = false ++ yaml_stream_end_event_initialize(&e.event) ++ e.emit() ++} ++ ++func (e *encoder) destroy() { ++ yaml_emitter_delete(&e.emitter) ++} ++ ++func (e *encoder) emit() { ++ // This will internally delete the e.event value. ++ e.must(yaml_emitter_emit(&e.emitter, &e.event)) ++} ++ ++func (e *encoder) must(ok bool) { ++ if !ok { ++ msg := e.emitter.problem ++ if msg == "" { ++ msg = "unknown problem generating YAML content" ++ } ++ failf("%s", msg) ++ } ++} ++ ++func (e *encoder) marshalDoc(tag string, in reflect.Value) { ++ e.init() ++ var node *Node ++ if in.IsValid() { ++ node, _ = in.Interface().(*Node) ++ } ++ if node != nil && node.Kind == DocumentNode { ++ e.nodev(in) ++ } else { ++ yaml_document_start_event_initialize(&e.event, nil, nil, true) ++ e.emit() ++ e.marshal(tag, in) ++ yaml_document_end_event_initialize(&e.event, true) ++ e.emit() ++ } ++} ++ ++func (e *encoder) marshal(tag string, in reflect.Value) { ++ tag = shortTag(tag) ++ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { ++ e.nilv() ++ return ++ } ++ iface := in.Interface() ++ switch value := iface.(type) { ++ case *Node: ++ e.nodev(in) ++ return ++ case Node: ++ if !in.CanAddr() { ++ var n = reflect.New(in.Type()).Elem() ++ n.Set(in) ++ in = n ++ } ++ e.nodev(in.Addr()) ++ return ++ case time.Time: ++ e.timev(tag, in) ++ return ++ case *time.Time: ++ e.timev(tag, in.Elem()) ++ return ++ case time.Duration: ++ e.stringv(tag, reflect.ValueOf(value.String())) ++ return ++ case Marshaler: ++ v, err := value.MarshalYAML() ++ if err != nil { ++ fail(err) ++ } ++ if v == nil { ++ e.nilv() ++ return ++ } ++ e.marshal(tag, reflect.ValueOf(v)) ++ return ++ case encoding.TextMarshaler: ++ text, err := value.MarshalText() ++ if err != nil { ++ fail(err) ++ } ++ in = reflect.ValueOf(string(text)) ++ case nil: ++ e.nilv() ++ return ++ } ++ switch in.Kind() { ++ case reflect.Interface: ++ e.marshal(tag, in.Elem()) ++ case reflect.Map: ++ e.mapv(tag, in) ++ case reflect.Ptr: ++ e.marshal(tag, in.Elem()) ++ case reflect.Struct: ++ e.structv(tag, in) ++ case reflect.Slice, reflect.Array: ++ e.slicev(tag, in) ++ case reflect.String: ++ e.stringv(tag, in) ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ e.intv(tag, in) ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ e.uintv(tag, in) ++ case reflect.Float32, reflect.Float64: ++ e.floatv(tag, in) ++ case reflect.Bool: ++ e.boolv(tag, in) ++ default: ++ panic("cannot marshal type: " + in.Type().String()) ++ } ++} ++ ++func (e *encoder) mapv(tag string, in reflect.Value) { ++ e.mappingv(tag, func() { ++ keys := keyList(in.MapKeys()) ++ sort.Sort(keys) ++ for _, k := range keys { ++ e.marshal("", k) ++ e.marshal("", in.MapIndex(k)) ++ } ++ }) ++} ++ ++func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { ++ for _, num := range index { ++ for { ++ if v.Kind() == reflect.Ptr { ++ if v.IsNil() { ++ return reflect.Value{} ++ } ++ v = v.Elem() ++ continue ++ } ++ break ++ } ++ v = v.Field(num) ++ } ++ return v ++} ++ ++func (e *encoder) structv(tag string, in reflect.Value) { ++ sinfo, err := getStructInfo(in.Type()) ++ if err != nil { ++ panic(err) ++ } ++ e.mappingv(tag, func() { ++ for _, info := range sinfo.FieldsList { ++ var value reflect.Value ++ if info.Inline == nil { ++ value = in.Field(info.Num) ++ } else { ++ value = e.fieldByIndex(in, info.Inline) ++ if !value.IsValid() { ++ continue ++ } ++ } ++ if info.OmitEmpty && isZero(value) { ++ continue ++ } ++ e.marshal("", reflect.ValueOf(info.Key)) ++ e.flow = info.Flow ++ e.marshal("", value) ++ } ++ if sinfo.InlineMap >= 0 { ++ m := in.Field(sinfo.InlineMap) ++ if m.Len() > 0 { ++ e.flow = false ++ keys := keyList(m.MapKeys()) ++ sort.Sort(keys) ++ for _, k := range keys { ++ if _, found := sinfo.FieldsMap[k.String()]; found { ++ panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) ++ } ++ e.marshal("", k) ++ e.flow = false ++ e.marshal("", m.MapIndex(k)) ++ } ++ } ++ } ++ }) ++} ++ ++func (e *encoder) mappingv(tag string, f func()) { ++ implicit := tag == "" ++ style := yaml_BLOCK_MAPPING_STYLE ++ if e.flow { ++ e.flow = false ++ style = yaml_FLOW_MAPPING_STYLE ++ } ++ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) ++ e.emit() ++ f() ++ yaml_mapping_end_event_initialize(&e.event) ++ e.emit() ++} ++ ++func (e *encoder) slicev(tag string, in reflect.Value) { ++ implicit := tag == "" ++ style := yaml_BLOCK_SEQUENCE_STYLE ++ if e.flow { ++ e.flow = false ++ style = yaml_FLOW_SEQUENCE_STYLE ++ } ++ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) ++ e.emit() ++ n := in.Len() ++ for i := 0; i < n; i++ { ++ e.marshal("", in.Index(i)) ++ } ++ e.must(yaml_sequence_end_event_initialize(&e.event)) ++ e.emit() ++} ++ ++// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. ++// ++// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported ++// in YAML 1.2 and by this package, but these should be marshalled quoted for ++// the time being for compatibility with other parsers. ++func isBase60Float(s string) (result bool) { ++ // Fast path. ++ if s == "" { ++ return false ++ } ++ c := s[0] ++ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { ++ return false ++ } ++ // Do the full match. ++ return base60float.MatchString(s) ++} ++ ++// From http://yaml.org/type/float.html, except the regular expression there ++// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. ++var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) ++ ++// isOldBool returns whether s is bool notation as defined in YAML 1.1. ++// ++// We continue to force strings that YAML 1.1 would interpret as booleans to be ++// rendered as quotes strings so that the marshalled output valid for YAML 1.1 ++// parsing. ++func isOldBool(s string) (result bool) { ++ switch s { ++ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", ++ "n", "N", "no", "No", "NO", "off", "Off", "OFF": ++ return true ++ default: ++ return false ++ } ++} ++ ++func (e *encoder) stringv(tag string, in reflect.Value) { ++ var style yaml_scalar_style_t ++ s := in.String() ++ canUsePlain := true ++ switch { ++ case !utf8.ValidString(s): ++ if tag == binaryTag { ++ failf("explicitly tagged !!binary data must be base64-encoded") ++ } ++ if tag != "" { ++ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) ++ } ++ // It can't be encoded directly as YAML so use a binary tag ++ // and encode it as base64. ++ tag = binaryTag ++ s = encodeBase64(s) ++ case tag == "": ++ // Check to see if it would resolve to a specific ++ // tag when encoded unquoted. If it doesn't, ++ // there's no need to quote it. ++ rtag, _ := resolve("", s) ++ canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) ++ } ++ // Note: it's possible for user code to emit invalid YAML ++ // if they explicitly specify a tag and a string containing ++ // text that's incompatible with that tag. ++ switch { ++ case strings.Contains(s, "\n"): ++ if e.flow { ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } else { ++ style = yaml_LITERAL_SCALAR_STYLE ++ } ++ case canUsePlain: ++ style = yaml_PLAIN_SCALAR_STYLE ++ default: ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ e.emitScalar(s, "", tag, style, nil, nil, nil, nil) ++} ++ ++func (e *encoder) boolv(tag string, in reflect.Value) { ++ var s string ++ if in.Bool() { ++ s = "true" ++ } else { ++ s = "false" ++ } ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) intv(tag string, in reflect.Value) { ++ s := strconv.FormatInt(in.Int(), 10) ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) uintv(tag string, in reflect.Value) { ++ s := strconv.FormatUint(in.Uint(), 10) ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) timev(tag string, in reflect.Value) { ++ t := in.Interface().(time.Time) ++ s := t.Format(time.RFC3339Nano) ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) floatv(tag string, in reflect.Value) { ++ // Issue #352: When formatting, use the precision of the underlying value ++ precision := 64 ++ if in.Kind() == reflect.Float32 { ++ precision = 32 ++ } ++ ++ s := strconv.FormatFloat(in.Float(), 'g', -1, precision) ++ switch s { ++ case "+Inf": ++ s = ".inf" ++ case "-Inf": ++ s = "-.inf" ++ case "NaN": ++ s = ".nan" ++ } ++ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) nilv() { ++ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) ++} ++ ++func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { ++ // TODO Kill this function. Replace all initialize calls by their underlining Go literals. ++ implicit := tag == "" ++ if !implicit { ++ tag = longTag(tag) ++ } ++ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) ++ e.event.head_comment = head ++ e.event.line_comment = line ++ e.event.foot_comment = foot ++ e.event.tail_comment = tail ++ e.emit() ++} ++ ++func (e *encoder) nodev(in reflect.Value) { ++ e.node(in.Interface().(*Node), "") ++} ++ ++func (e *encoder) node(node *Node, tail string) { ++ // Zero nodes behave as nil. ++ if node.Kind == 0 && node.IsZero() { ++ e.nilv() ++ return ++ } ++ ++ // If the tag was not explicitly requested, and dropping it won't change the ++ // implicit tag of the value, don't include it in the presentation. ++ var tag = node.Tag ++ var stag = shortTag(tag) ++ var forceQuoting bool ++ if tag != "" && node.Style&TaggedStyle == 0 { ++ if node.Kind == ScalarNode { ++ if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { ++ tag = "" ++ } else { ++ rtag, _ := resolve("", node.Value) ++ if rtag == stag { ++ tag = "" ++ } else if stag == strTag { ++ tag = "" ++ forceQuoting = true ++ } ++ } ++ } else { ++ var rtag string ++ switch node.Kind { ++ case MappingNode: ++ rtag = mapTag ++ case SequenceNode: ++ rtag = seqTag ++ } ++ if rtag == stag { ++ tag = "" ++ } ++ } ++ } ++ ++ switch node.Kind { ++ case DocumentNode: ++ yaml_document_start_event_initialize(&e.event, nil, nil, true) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.emit() ++ for _, node := range node.Content { ++ e.node(node, "") ++ } ++ yaml_document_end_event_initialize(&e.event, true) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case SequenceNode: ++ style := yaml_BLOCK_SEQUENCE_STYLE ++ if node.Style&FlowStyle != 0 { ++ style = yaml_FLOW_SEQUENCE_STYLE ++ } ++ e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.emit() ++ for _, node := range node.Content { ++ e.node(node, "") ++ } ++ e.must(yaml_sequence_end_event_initialize(&e.event)) ++ e.event.line_comment = []byte(node.LineComment) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case MappingNode: ++ style := yaml_BLOCK_MAPPING_STYLE ++ if node.Style&FlowStyle != 0 { ++ style = yaml_FLOW_MAPPING_STYLE ++ } ++ yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) ++ e.event.tail_comment = []byte(tail) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.emit() ++ ++ // The tail logic below moves the foot comment of prior keys to the following key, ++ // since the value for each key may be a nested structure and the foot needs to be ++ // processed only the entirety of the value is streamed. The last tail is processed ++ // with the mapping end event. ++ var tail string ++ for i := 0; i+1 < len(node.Content); i += 2 { ++ k := node.Content[i] ++ foot := k.FootComment ++ if foot != "" { ++ kopy := *k ++ kopy.FootComment = "" ++ k = &kopy ++ } ++ e.node(k, tail) ++ tail = foot ++ ++ v := node.Content[i+1] ++ e.node(v, "") ++ } ++ ++ yaml_mapping_end_event_initialize(&e.event) ++ e.event.tail_comment = []byte(tail) ++ e.event.line_comment = []byte(node.LineComment) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case AliasNode: ++ yaml_alias_event_initialize(&e.event, []byte(node.Value)) ++ e.event.head_comment = []byte(node.HeadComment) ++ e.event.line_comment = []byte(node.LineComment) ++ e.event.foot_comment = []byte(node.FootComment) ++ e.emit() ++ ++ case ScalarNode: ++ value := node.Value ++ if !utf8.ValidString(value) { ++ if stag == binaryTag { ++ failf("explicitly tagged !!binary data must be base64-encoded") ++ } ++ if stag != "" { ++ failf("cannot marshal invalid UTF-8 data as %s", stag) ++ } ++ // It can't be encoded directly as YAML so use a binary tag ++ // and encode it as base64. ++ tag = binaryTag ++ value = encodeBase64(value) ++ } ++ ++ style := yaml_PLAIN_SCALAR_STYLE ++ switch { ++ case node.Style&DoubleQuotedStyle != 0: ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ case node.Style&SingleQuotedStyle != 0: ++ style = yaml_SINGLE_QUOTED_SCALAR_STYLE ++ case node.Style&LiteralStyle != 0: ++ style = yaml_LITERAL_SCALAR_STYLE ++ case node.Style&FoldedStyle != 0: ++ style = yaml_FOLDED_SCALAR_STYLE ++ case strings.Contains(value, "\n"): ++ style = yaml_LITERAL_SCALAR_STYLE ++ case forceQuoting: ++ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ ++ e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) ++ default: ++ failf("cannot encode node with unknown kind %d", node.Kind) ++ } ++} +diff --git a/vendor/gopkg.in/yaml.v3/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go +new file mode 100644 +index 000000000000..268558a0d632 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/parserc.go +@@ -0,0 +1,1258 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++import ( ++ "bytes" ++) ++ ++// The parser implements the following grammar: ++// ++// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END ++// implicit_document ::= block_node DOCUMENT-END* ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// block_node_or_indentless_sequence ::= ++// ALIAS ++// | properties (block_content | indentless_block_sequence)? ++// | block_content ++// | indentless_block_sequence ++// block_node ::= ALIAS ++// | properties block_content? ++// | block_content ++// flow_node ::= ALIAS ++// | properties flow_content? ++// | flow_content ++// properties ::= TAG ANCHOR? | ANCHOR TAG? ++// block_content ::= block_collection | flow_collection | SCALAR ++// flow_content ::= flow_collection | SCALAR ++// block_collection ::= block_sequence | block_mapping ++// flow_collection ::= flow_sequence | flow_mapping ++// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END ++// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ ++// block_mapping ::= BLOCK-MAPPING_START ++// ((KEY block_node_or_indentless_sequence?)? ++// (VALUE block_node_or_indentless_sequence?)?)* ++// BLOCK-END ++// flow_sequence ::= FLOW-SEQUENCE-START ++// (flow_sequence_entry FLOW-ENTRY)* ++// flow_sequence_entry? ++// FLOW-SEQUENCE-END ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// flow_mapping ::= FLOW-MAPPING-START ++// (flow_mapping_entry FLOW-ENTRY)* ++// flow_mapping_entry? ++// FLOW-MAPPING-END ++// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++ ++// Peek the next token in the token queue. ++func peek_token(parser *yaml_parser_t) *yaml_token_t { ++ if parser.token_available || yaml_parser_fetch_more_tokens(parser) { ++ token := &parser.tokens[parser.tokens_head] ++ yaml_parser_unfold_comments(parser, token) ++ return token ++ } ++ return nil ++} ++ ++// yaml_parser_unfold_comments walks through the comments queue and joins all ++// comments behind the position of the provided token into the respective ++// top-level comment slices in the parser. ++func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) { ++ for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index { ++ comment := &parser.comments[parser.comments_head] ++ if len(comment.head) > 0 { ++ if token.typ == yaml_BLOCK_END_TOKEN { ++ // No heads on ends, so keep comment.head for a follow up token. ++ break ++ } ++ if len(parser.head_comment) > 0 { ++ parser.head_comment = append(parser.head_comment, '\n') ++ } ++ parser.head_comment = append(parser.head_comment, comment.head...) ++ } ++ if len(comment.foot) > 0 { ++ if len(parser.foot_comment) > 0 { ++ parser.foot_comment = append(parser.foot_comment, '\n') ++ } ++ parser.foot_comment = append(parser.foot_comment, comment.foot...) ++ } ++ if len(comment.line) > 0 { ++ if len(parser.line_comment) > 0 { ++ parser.line_comment = append(parser.line_comment, '\n') ++ } ++ parser.line_comment = append(parser.line_comment, comment.line...) ++ } ++ *comment = yaml_comment_t{} ++ parser.comments_head++ ++ } ++} ++ ++// Remove the next token from the queue (must be called after peek_token). ++func skip_token(parser *yaml_parser_t) { ++ parser.token_available = false ++ parser.tokens_parsed++ ++ parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN ++ parser.tokens_head++ ++} ++ ++// Get the next event. ++func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { ++ // Erase the event object. ++ *event = yaml_event_t{} ++ ++ // No events after the end of the stream or error. ++ if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { ++ return true ++ } ++ ++ // Generate the next event. ++ return yaml_parser_state_machine(parser, event) ++} ++ ++// Set parser error. ++func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { ++ parser.error = yaml_PARSER_ERROR ++ parser.problem = problem ++ parser.problem_mark = problem_mark ++ return false ++} ++ ++func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { ++ parser.error = yaml_PARSER_ERROR ++ parser.context = context ++ parser.context_mark = context_mark ++ parser.problem = problem ++ parser.problem_mark = problem_mark ++ return false ++} ++ ++// State dispatcher. ++func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { ++ //trace("yaml_parser_state_machine", "state:", parser.state.String()) ++ ++ switch parser.state { ++ case yaml_PARSE_STREAM_START_STATE: ++ return yaml_parser_parse_stream_start(parser, event) ++ ++ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: ++ return yaml_parser_parse_document_start(parser, event, true) ++ ++ case yaml_PARSE_DOCUMENT_START_STATE: ++ return yaml_parser_parse_document_start(parser, event, false) ++ ++ case yaml_PARSE_DOCUMENT_CONTENT_STATE: ++ return yaml_parser_parse_document_content(parser, event) ++ ++ case yaml_PARSE_DOCUMENT_END_STATE: ++ return yaml_parser_parse_document_end(parser, event) ++ ++ case yaml_PARSE_BLOCK_NODE_STATE: ++ return yaml_parser_parse_node(parser, event, true, false) ++ ++ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: ++ return yaml_parser_parse_node(parser, event, true, true) ++ ++ case yaml_PARSE_FLOW_NODE_STATE: ++ return yaml_parser_parse_node(parser, event, false, false) ++ ++ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: ++ return yaml_parser_parse_block_sequence_entry(parser, event, true) ++ ++ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: ++ return yaml_parser_parse_block_sequence_entry(parser, event, false) ++ ++ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: ++ return yaml_parser_parse_indentless_sequence_entry(parser, event) ++ ++ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: ++ return yaml_parser_parse_block_mapping_key(parser, event, true) ++ ++ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: ++ return yaml_parser_parse_block_mapping_key(parser, event, false) ++ ++ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: ++ return yaml_parser_parse_block_mapping_value(parser, event) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: ++ return yaml_parser_parse_flow_sequence_entry(parser, event, true) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: ++ return yaml_parser_parse_flow_sequence_entry(parser, event, false) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: ++ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: ++ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) ++ ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: ++ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) ++ ++ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: ++ return yaml_parser_parse_flow_mapping_key(parser, event, true) ++ ++ case yaml_PARSE_FLOW_MAPPING_KEY_STATE: ++ return yaml_parser_parse_flow_mapping_key(parser, event, false) ++ ++ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: ++ return yaml_parser_parse_flow_mapping_value(parser, event, false) ++ ++ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: ++ return yaml_parser_parse_flow_mapping_value(parser, event, true) ++ ++ default: ++ panic("invalid parser state") ++ } ++} ++ ++// Parse the production: ++// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END ++// ************ ++func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_STREAM_START_TOKEN { ++ return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) ++ } ++ parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_START_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ encoding: token.encoding, ++ } ++ skip_token(parser) ++ return true ++} ++ ++// Parse the productions: ++// implicit_document ::= block_node DOCUMENT-END* ++// * ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// ************************* ++func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ // Parse extra document end indicators. ++ if !implicit { ++ for token.typ == yaml_DOCUMENT_END_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ } ++ ++ if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && ++ token.typ != yaml_TAG_DIRECTIVE_TOKEN && ++ token.typ != yaml_DOCUMENT_START_TOKEN && ++ token.typ != yaml_STREAM_END_TOKEN { ++ // Parse an implicit document. ++ if !yaml_parser_process_directives(parser, nil, nil) { ++ return false ++ } ++ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) ++ parser.state = yaml_PARSE_BLOCK_NODE_STATE ++ ++ var head_comment []byte ++ if len(parser.head_comment) > 0 { ++ // [Go] Scan the header comment backwards, and if an empty line is found, break ++ // the header so the part before the last empty line goes into the ++ // document header, while the bottom of it goes into a follow up event. ++ for i := len(parser.head_comment) - 1; i > 0; i-- { ++ if parser.head_comment[i] == '\n' { ++ if i == len(parser.head_comment)-1 { ++ head_comment = parser.head_comment[:i] ++ parser.head_comment = parser.head_comment[i+1:] ++ break ++ } else if parser.head_comment[i-1] == '\n' { ++ head_comment = parser.head_comment[:i-1] ++ parser.head_comment = parser.head_comment[i+1:] ++ break ++ } ++ } ++ } ++ } ++ ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_START_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ ++ head_comment: head_comment, ++ } ++ ++ } else if token.typ != yaml_STREAM_END_TOKEN { ++ // Parse an explicit document. ++ var version_directive *yaml_version_directive_t ++ var tag_directives []yaml_tag_directive_t ++ start_mark := token.start_mark ++ if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { ++ return false ++ } ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_DOCUMENT_START_TOKEN { ++ yaml_parser_set_parser_error(parser, ++ "did not find expected ", token.start_mark) ++ return false ++ } ++ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) ++ parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE ++ end_mark := token.end_mark ++ ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ version_directive: version_directive, ++ tag_directives: tag_directives, ++ implicit: false, ++ } ++ skip_token(parser) ++ ++ } else { ++ // Parse the stream end. ++ parser.state = yaml_PARSE_END_STATE ++ *event = yaml_event_t{ ++ typ: yaml_STREAM_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ skip_token(parser) ++ } ++ ++ return true ++} ++ ++// Parse the productions: ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// *********** ++// ++func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || ++ token.typ == yaml_TAG_DIRECTIVE_TOKEN || ++ token.typ == yaml_DOCUMENT_START_TOKEN || ++ token.typ == yaml_DOCUMENT_END_TOKEN || ++ token.typ == yaml_STREAM_END_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ return yaml_parser_process_empty_scalar(parser, event, ++ token.start_mark) ++ } ++ return yaml_parser_parse_node(parser, event, true, false) ++} ++ ++// Parse the productions: ++// implicit_document ::= block_node DOCUMENT-END* ++// ************* ++// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* ++// ++func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ start_mark := token.start_mark ++ end_mark := token.start_mark ++ ++ implicit := true ++ if token.typ == yaml_DOCUMENT_END_TOKEN { ++ end_mark = token.end_mark ++ skip_token(parser) ++ implicit = false ++ } ++ ++ parser.tag_directives = parser.tag_directives[:0] ++ ++ parser.state = yaml_PARSE_DOCUMENT_START_STATE ++ *event = yaml_event_t{ ++ typ: yaml_DOCUMENT_END_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ implicit: implicit, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ if len(event.head_comment) > 0 && len(event.foot_comment) == 0 { ++ event.foot_comment = event.head_comment ++ event.head_comment = nil ++ } ++ return true ++} ++ ++func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) { ++ event.head_comment = parser.head_comment ++ event.line_comment = parser.line_comment ++ event.foot_comment = parser.foot_comment ++ parser.head_comment = nil ++ parser.line_comment = nil ++ parser.foot_comment = nil ++ parser.tail_comment = nil ++ parser.stem_comment = nil ++} ++ ++// Parse the productions: ++// block_node_or_indentless_sequence ::= ++// ALIAS ++// ***** ++// | properties (block_content | indentless_block_sequence)? ++// ********** * ++// | block_content | indentless_block_sequence ++// * ++// block_node ::= ALIAS ++// ***** ++// | properties block_content? ++// ********** * ++// | block_content ++// * ++// flow_node ::= ALIAS ++// ***** ++// | properties flow_content? ++// ********** * ++// | flow_content ++// * ++// properties ::= TAG ANCHOR? | ANCHOR TAG? ++// ************************* ++// block_content ::= block_collection | flow_collection | SCALAR ++// ****** ++// flow_content ::= flow_collection | SCALAR ++// ****** ++func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { ++ //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_ALIAS_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ *event = yaml_event_t{ ++ typ: yaml_ALIAS_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ anchor: token.value, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++ } ++ ++ start_mark := token.start_mark ++ end_mark := token.start_mark ++ ++ var tag_token bool ++ var tag_handle, tag_suffix, anchor []byte ++ var tag_mark yaml_mark_t ++ if token.typ == yaml_ANCHOR_TOKEN { ++ anchor = token.value ++ start_mark = token.start_mark ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_TAG_TOKEN { ++ tag_token = true ++ tag_handle = token.value ++ tag_suffix = token.suffix ++ tag_mark = token.start_mark ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ } else if token.typ == yaml_TAG_TOKEN { ++ tag_token = true ++ tag_handle = token.value ++ tag_suffix = token.suffix ++ start_mark = token.start_mark ++ tag_mark = token.start_mark ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_ANCHOR_TOKEN { ++ anchor = token.value ++ end_mark = token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ } ++ ++ var tag []byte ++ if tag_token { ++ if len(tag_handle) == 0 { ++ tag = tag_suffix ++ tag_suffix = nil ++ } else { ++ for i := range parser.tag_directives { ++ if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { ++ tag = append([]byte(nil), parser.tag_directives[i].prefix...) ++ tag = append(tag, tag_suffix...) ++ break ++ } ++ } ++ if len(tag) == 0 { ++ yaml_parser_set_parser_error_context(parser, ++ "while parsing a node", start_mark, ++ "found undefined tag handle", tag_mark) ++ return false ++ } ++ } ++ } ++ ++ implicit := len(tag) == 0 ++ if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), ++ } ++ return true ++ } ++ if token.typ == yaml_SCALAR_TOKEN { ++ var plain_implicit, quoted_implicit bool ++ end_mark = token.end_mark ++ if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { ++ plain_implicit = true ++ } else if len(tag) == 0 { ++ quoted_implicit = true ++ } ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ value: token.value, ++ implicit: plain_implicit, ++ quoted_implicit: quoted_implicit, ++ style: yaml_style_t(token.style), ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++ } ++ if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { ++ // [Go] Some of the events below can be merged as they differ only on style. ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), ++ } ++ yaml_parser_set_event_comments(parser, event) ++ return true ++ } ++ if token.typ == yaml_FLOW_MAPPING_START_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), ++ } ++ yaml_parser_set_event_comments(parser, event) ++ return true ++ } ++ if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), ++ } ++ if parser.stem_comment != nil { ++ event.head_comment = parser.stem_comment ++ parser.stem_comment = nil ++ } ++ return true ++ } ++ if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { ++ end_mark = token.end_mark ++ parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), ++ } ++ if parser.stem_comment != nil { ++ event.head_comment = parser.stem_comment ++ parser.stem_comment = nil ++ } ++ return true ++ } ++ if len(anchor) > 0 || len(tag) > 0 { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ anchor: anchor, ++ tag: tag, ++ implicit: implicit, ++ quoted_implicit: false, ++ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), ++ } ++ return true ++ } ++ ++ context := "while parsing a flow node" ++ if block { ++ context = "while parsing a block node" ++ } ++ yaml_parser_set_parser_error_context(parser, context, start_mark, ++ "did not find expected node content", token.start_mark) ++ return false ++} ++ ++// Parse the productions: ++// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END ++// ******************** *********** * ********* ++// ++func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_BLOCK_ENTRY_TOKEN { ++ mark := token.end_mark ++ prior_head_len := len(parser.head_comment) ++ skip_token(parser) ++ yaml_parser_split_stem_comment(parser, prior_head_len) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) ++ return yaml_parser_parse_node(parser, event, true, false) ++ } else { ++ parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ } ++ if token.typ == yaml_BLOCK_END_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ ++ skip_token(parser) ++ return true ++ } ++ ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a block collection", context_mark, ++ "did not find expected '-' indicator", token.start_mark) ++} ++ ++// Parse the productions: ++// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ ++// *********** * ++func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ == yaml_BLOCK_ENTRY_TOKEN { ++ mark := token.end_mark ++ prior_head_len := len(parser.head_comment) ++ skip_token(parser) ++ yaml_parser_split_stem_comment(parser, prior_head_len) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_BLOCK_ENTRY_TOKEN && ++ token.typ != yaml_KEY_TOKEN && ++ token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) ++ return yaml_parser_parse_node(parser, event, true, false) ++ } ++ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? ++ } ++ return true ++} ++ ++// Split stem comment from head comment. ++// ++// When a sequence or map is found under a sequence entry, the former head comment ++// is assigned to the underlying sequence or map as a whole, not the individual ++// sequence or map entry as would be expected otherwise. To handle this case the ++// previous head comment is moved aside as the stem comment. ++func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { ++ if stem_len == 0 { ++ return ++ } ++ ++ token := peek_token(parser) ++ if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { ++ return ++ } ++ ++ parser.stem_comment = parser.head_comment[:stem_len] ++ if len(parser.head_comment) == stem_len { ++ parser.head_comment = nil ++ } else { ++ // Copy suffix to prevent very strange bugs if someone ever appends ++ // further bytes to the prefix in the stem_comment slice above. ++ parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) ++ } ++} ++ ++// Parse the productions: ++// block_mapping ::= BLOCK-MAPPING_START ++// ******************* ++// ((KEY block_node_or_indentless_sequence?)? ++// *** * ++// (VALUE block_node_or_indentless_sequence?)?)* ++// ++// BLOCK-END ++// ********* ++// ++func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ // [Go] A tail comment was left from the prior mapping value processed. Emit an event ++ // as it needs to be processed with that value and not the following key. ++ if len(parser.tail_comment) > 0 { ++ *event = yaml_event_t{ ++ typ: yaml_TAIL_COMMENT_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ foot_comment: parser.tail_comment, ++ } ++ parser.tail_comment = nil ++ return true ++ } ++ ++ if token.typ == yaml_KEY_TOKEN { ++ mark := token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_KEY_TOKEN && ++ token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, true, true) ++ } else { ++ parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ } else if token.typ == yaml_BLOCK_END_TOKEN { ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++ } ++ ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a block mapping", context_mark, ++ "did not find expected key", token.start_mark) ++} ++ ++// Parse the productions: ++// block_mapping ::= BLOCK-MAPPING_START ++// ++// ((KEY block_node_or_indentless_sequence?)? ++// ++// (VALUE block_node_or_indentless_sequence?)?)* ++// ***** * ++// BLOCK-END ++// ++// ++func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_VALUE_TOKEN { ++ mark := token.end_mark ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_KEY_TOKEN && ++ token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_BLOCK_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) ++ return yaml_parser_parse_node(parser, event, true, true) ++ } ++ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++ } ++ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++} ++ ++// Parse the productions: ++// flow_sequence ::= FLOW-SEQUENCE-START ++// ******************* ++// (flow_sequence_entry FLOW-ENTRY)* ++// * ********** ++// flow_sequence_entry? ++// * ++// FLOW-SEQUENCE-END ++// ***************** ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * ++// ++func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ if !first { ++ if token.typ == yaml_FLOW_ENTRY_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } else { ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a flow sequence", context_mark, ++ "did not find expected ',' or ']'", token.start_mark) ++ } ++ } ++ ++ if token.typ == yaml_KEY_TOKEN { ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_START_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ implicit: true, ++ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), ++ } ++ skip_token(parser) ++ return true ++ } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ ++ *event = yaml_event_t{ ++ typ: yaml_SEQUENCE_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ ++ skip_token(parser) ++ return true ++} ++ ++// ++// Parse the productions: ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// *** * ++// ++func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_FLOW_ENTRY_TOKEN && ++ token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ mark := token.end_mark ++ skip_token(parser) ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE ++ return yaml_parser_process_empty_scalar(parser, event, mark) ++} ++ ++// Parse the productions: ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// ***** * ++// ++func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ == yaml_VALUE_TOKEN { ++ skip_token(parser) ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++} ++ ++// Parse the productions: ++// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * ++// ++func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? ++ } ++ return true ++} ++ ++// Parse the productions: ++// flow_mapping ::= FLOW-MAPPING-START ++// ****************** ++// (flow_mapping_entry FLOW-ENTRY)* ++// * ********** ++// flow_mapping_entry? ++// ****************** ++// FLOW-MAPPING-END ++// **************** ++// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * *** * ++// ++func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { ++ if first { ++ token := peek_token(parser) ++ parser.marks = append(parser.marks, token.start_mark) ++ skip_token(parser) ++ } ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ if token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ if !first { ++ if token.typ == yaml_FLOW_ENTRY_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } else { ++ context_mark := parser.marks[len(parser.marks)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ return yaml_parser_set_parser_error_context(parser, ++ "while parsing a flow mapping", context_mark, ++ "did not find expected ',' or '}'", token.start_mark) ++ } ++ } ++ ++ if token.typ == yaml_KEY_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_VALUE_TOKEN && ++ token.typ != yaml_FLOW_ENTRY_TOKEN && ++ token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } else { ++ parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++ } ++ } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ ++ parser.state = parser.states[len(parser.states)-1] ++ parser.states = parser.states[:len(parser.states)-1] ++ parser.marks = parser.marks[:len(parser.marks)-1] ++ *event = yaml_event_t{ ++ typ: yaml_MAPPING_END_EVENT, ++ start_mark: token.start_mark, ++ end_mark: token.end_mark, ++ } ++ yaml_parser_set_event_comments(parser, event) ++ skip_token(parser) ++ return true ++} ++ ++// Parse the productions: ++// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? ++// * ***** * ++// ++func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if empty { ++ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++ } ++ if token.typ == yaml_VALUE_TOKEN { ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { ++ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) ++ return yaml_parser_parse_node(parser, event, false, false) ++ } ++ } ++ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE ++ return yaml_parser_process_empty_scalar(parser, event, token.start_mark) ++} ++ ++// Generate an empty scalar event. ++func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { ++ *event = yaml_event_t{ ++ typ: yaml_SCALAR_EVENT, ++ start_mark: mark, ++ end_mark: mark, ++ value: nil, // Empty ++ implicit: true, ++ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), ++ } ++ return true ++} ++ ++var default_tag_directives = []yaml_tag_directive_t{ ++ {[]byte("!"), []byte("!")}, ++ {[]byte("!!"), []byte("tag:yaml.org,2002:")}, ++} ++ ++// Parse directives. ++func yaml_parser_process_directives(parser *yaml_parser_t, ++ version_directive_ref **yaml_version_directive_t, ++ tag_directives_ref *[]yaml_tag_directive_t) bool { ++ ++ var version_directive *yaml_version_directive_t ++ var tag_directives []yaml_tag_directive_t ++ ++ token := peek_token(parser) ++ if token == nil { ++ return false ++ } ++ ++ for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { ++ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { ++ if version_directive != nil { ++ yaml_parser_set_parser_error(parser, ++ "found duplicate %YAML directive", token.start_mark) ++ return false ++ } ++ if token.major != 1 || token.minor != 1 { ++ yaml_parser_set_parser_error(parser, ++ "found incompatible YAML document", token.start_mark) ++ return false ++ } ++ version_directive = &yaml_version_directive_t{ ++ major: token.major, ++ minor: token.minor, ++ } ++ } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { ++ value := yaml_tag_directive_t{ ++ handle: token.value, ++ prefix: token.prefix, ++ } ++ if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { ++ return false ++ } ++ tag_directives = append(tag_directives, value) ++ } ++ ++ skip_token(parser) ++ token = peek_token(parser) ++ if token == nil { ++ return false ++ } ++ } ++ ++ for i := range default_tag_directives { ++ if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { ++ return false ++ } ++ } ++ ++ if version_directive_ref != nil { ++ *version_directive_ref = version_directive ++ } ++ if tag_directives_ref != nil { ++ *tag_directives_ref = tag_directives ++ } ++ return true ++} ++ ++// Append a tag directive to the directives stack. ++func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { ++ for i := range parser.tag_directives { ++ if bytes.Equal(value.handle, parser.tag_directives[i].handle) { ++ if allow_duplicates { ++ return true ++ } ++ return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) ++ } ++ } ++ ++ // [Go] I suspect the copy is unnecessary. This was likely done ++ // because there was no way to track ownership of the data. ++ value_copy := yaml_tag_directive_t{ ++ handle: make([]byte, len(value.handle)), ++ prefix: make([]byte, len(value.prefix)), ++ } ++ copy(value_copy.handle, value.handle) ++ copy(value_copy.prefix, value.prefix) ++ parser.tag_directives = append(parser.tag_directives, value_copy) ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/readerc.go b/vendor/gopkg.in/yaml.v3/readerc.go +new file mode 100644 +index 000000000000..b7de0a89c462 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/readerc.go +@@ -0,0 +1,434 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++import ( ++ "io" ++) ++ ++// Set the reader error and return 0. ++func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { ++ parser.error = yaml_READER_ERROR ++ parser.problem = problem ++ parser.problem_offset = offset ++ parser.problem_value = value ++ return false ++} ++ ++// Byte order marks. ++const ( ++ bom_UTF8 = "\xef\xbb\xbf" ++ bom_UTF16LE = "\xff\xfe" ++ bom_UTF16BE = "\xfe\xff" ++) ++ ++// Determine the input stream encoding by checking the BOM symbol. If no BOM is ++// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. ++func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { ++ // Ensure that we had enough bytes in the raw buffer. ++ for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { ++ if !yaml_parser_update_raw_buffer(parser) { ++ return false ++ } ++ } ++ ++ // Determine the encoding. ++ buf := parser.raw_buffer ++ pos := parser.raw_buffer_pos ++ avail := len(buf) - pos ++ if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { ++ parser.encoding = yaml_UTF16LE_ENCODING ++ parser.raw_buffer_pos += 2 ++ parser.offset += 2 ++ } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { ++ parser.encoding = yaml_UTF16BE_ENCODING ++ parser.raw_buffer_pos += 2 ++ parser.offset += 2 ++ } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { ++ parser.encoding = yaml_UTF8_ENCODING ++ parser.raw_buffer_pos += 3 ++ parser.offset += 3 ++ } else { ++ parser.encoding = yaml_UTF8_ENCODING ++ } ++ return true ++} ++ ++// Update the raw buffer. ++func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { ++ size_read := 0 ++ ++ // Return if the raw buffer is full. ++ if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { ++ return true ++ } ++ ++ // Return on EOF. ++ if parser.eof { ++ return true ++ } ++ ++ // Move the remaining bytes in the raw buffer to the beginning. ++ if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { ++ copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) ++ } ++ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] ++ parser.raw_buffer_pos = 0 ++ ++ // Call the read handler to fill the buffer. ++ size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) ++ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] ++ if err == io.EOF { ++ parser.eof = true ++ } else if err != nil { ++ return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) ++ } ++ return true ++} ++ ++// Ensure that the buffer contains at least `length` characters. ++// Return true on success, false on failure. ++// ++// The length is supposed to be significantly less that the buffer size. ++func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { ++ if parser.read_handler == nil { ++ panic("read handler must be set") ++ } ++ ++ // [Go] This function was changed to guarantee the requested length size at EOF. ++ // The fact we need to do this is pretty awful, but the description above implies ++ // for that to be the case, and there are tests ++ ++ // If the EOF flag is set and the raw buffer is empty, do nothing. ++ if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { ++ // [Go] ACTUALLY! Read the documentation of this function above. ++ // This is just broken. To return true, we need to have the ++ // given length in the buffer. Not doing that means every single ++ // check that calls this function to make sure the buffer has a ++ // given length is Go) panicking; or C) accessing invalid memory. ++ //return true ++ } ++ ++ // Return if the buffer contains enough characters. ++ if parser.unread >= length { ++ return true ++ } ++ ++ // Determine the input encoding if it is not known yet. ++ if parser.encoding == yaml_ANY_ENCODING { ++ if !yaml_parser_determine_encoding(parser) { ++ return false ++ } ++ } ++ ++ // Move the unread characters to the beginning of the buffer. ++ buffer_len := len(parser.buffer) ++ if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { ++ copy(parser.buffer, parser.buffer[parser.buffer_pos:]) ++ buffer_len -= parser.buffer_pos ++ parser.buffer_pos = 0 ++ } else if parser.buffer_pos == buffer_len { ++ buffer_len = 0 ++ parser.buffer_pos = 0 ++ } ++ ++ // Open the whole buffer for writing, and cut it before returning. ++ parser.buffer = parser.buffer[:cap(parser.buffer)] ++ ++ // Fill the buffer until it has enough characters. ++ first := true ++ for parser.unread < length { ++ ++ // Fill the raw buffer if necessary. ++ if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { ++ if !yaml_parser_update_raw_buffer(parser) { ++ parser.buffer = parser.buffer[:buffer_len] ++ return false ++ } ++ } ++ first = false ++ ++ // Decode the raw buffer. ++ inner: ++ for parser.raw_buffer_pos != len(parser.raw_buffer) { ++ var value rune ++ var width int ++ ++ raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos ++ ++ // Decode the next character. ++ switch parser.encoding { ++ case yaml_UTF8_ENCODING: ++ // Decode a UTF-8 character. Check RFC 3629 ++ // (http://www.ietf.org/rfc/rfc3629.txt) for more details. ++ // ++ // The following table (taken from the RFC) is used for ++ // decoding. ++ // ++ // Char. number range | UTF-8 octet sequence ++ // (hexadecimal) | (binary) ++ // --------------------+------------------------------------ ++ // 0000 0000-0000 007F | 0xxxxxxx ++ // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx ++ // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx ++ // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx ++ // ++ // Additionally, the characters in the range 0xD800-0xDFFF ++ // are prohibited as they are reserved for use with UTF-16 ++ // surrogate pairs. ++ ++ // Determine the length of the UTF-8 sequence. ++ octet := parser.raw_buffer[parser.raw_buffer_pos] ++ switch { ++ case octet&0x80 == 0x00: ++ width = 1 ++ case octet&0xE0 == 0xC0: ++ width = 2 ++ case octet&0xF0 == 0xE0: ++ width = 3 ++ case octet&0xF8 == 0xF0: ++ width = 4 ++ default: ++ // The leading octet is invalid. ++ return yaml_parser_set_reader_error(parser, ++ "invalid leading UTF-8 octet", ++ parser.offset, int(octet)) ++ } ++ ++ // Check if the raw buffer contains an incomplete character. ++ if width > raw_unread { ++ if parser.eof { ++ return yaml_parser_set_reader_error(parser, ++ "incomplete UTF-8 octet sequence", ++ parser.offset, -1) ++ } ++ break inner ++ } ++ ++ // Decode the leading octet. ++ switch { ++ case octet&0x80 == 0x00: ++ value = rune(octet & 0x7F) ++ case octet&0xE0 == 0xC0: ++ value = rune(octet & 0x1F) ++ case octet&0xF0 == 0xE0: ++ value = rune(octet & 0x0F) ++ case octet&0xF8 == 0xF0: ++ value = rune(octet & 0x07) ++ default: ++ value = 0 ++ } ++ ++ // Check and decode the trailing octets. ++ for k := 1; k < width; k++ { ++ octet = parser.raw_buffer[parser.raw_buffer_pos+k] ++ ++ // Check if the octet is valid. ++ if (octet & 0xC0) != 0x80 { ++ return yaml_parser_set_reader_error(parser, ++ "invalid trailing UTF-8 octet", ++ parser.offset+k, int(octet)) ++ } ++ ++ // Decode the octet. ++ value = (value << 6) + rune(octet&0x3F) ++ } ++ ++ // Check the length of the sequence against the value. ++ switch { ++ case width == 1: ++ case width == 2 && value >= 0x80: ++ case width == 3 && value >= 0x800: ++ case width == 4 && value >= 0x10000: ++ default: ++ return yaml_parser_set_reader_error(parser, ++ "invalid length of a UTF-8 sequence", ++ parser.offset, -1) ++ } ++ ++ // Check the range of the value. ++ if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { ++ return yaml_parser_set_reader_error(parser, ++ "invalid Unicode character", ++ parser.offset, int(value)) ++ } ++ ++ case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: ++ var low, high int ++ if parser.encoding == yaml_UTF16LE_ENCODING { ++ low, high = 0, 1 ++ } else { ++ low, high = 1, 0 ++ } ++ ++ // The UTF-16 encoding is not as simple as one might ++ // naively think. Check RFC 2781 ++ // (http://www.ietf.org/rfc/rfc2781.txt). ++ // ++ // Normally, two subsequent bytes describe a Unicode ++ // character. However a special technique (called a ++ // surrogate pair) is used for specifying character ++ // values larger than 0xFFFF. ++ // ++ // A surrogate pair consists of two pseudo-characters: ++ // high surrogate area (0xD800-0xDBFF) ++ // low surrogate area (0xDC00-0xDFFF) ++ // ++ // The following formulas are used for decoding ++ // and encoding characters using surrogate pairs: ++ // ++ // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) ++ // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) ++ // W1 = 110110yyyyyyyyyy ++ // W2 = 110111xxxxxxxxxx ++ // ++ // where U is the character value, W1 is the high surrogate ++ // area, W2 is the low surrogate area. ++ ++ // Check for incomplete UTF-16 character. ++ if raw_unread < 2 { ++ if parser.eof { ++ return yaml_parser_set_reader_error(parser, ++ "incomplete UTF-16 character", ++ parser.offset, -1) ++ } ++ break inner ++ } ++ ++ // Get the character. ++ value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + ++ (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) ++ ++ // Check for unexpected low surrogate area. ++ if value&0xFC00 == 0xDC00 { ++ return yaml_parser_set_reader_error(parser, ++ "unexpected low surrogate area", ++ parser.offset, int(value)) ++ } ++ ++ // Check for a high surrogate area. ++ if value&0xFC00 == 0xD800 { ++ width = 4 ++ ++ // Check for incomplete surrogate pair. ++ if raw_unread < 4 { ++ if parser.eof { ++ return yaml_parser_set_reader_error(parser, ++ "incomplete UTF-16 surrogate pair", ++ parser.offset, -1) ++ } ++ break inner ++ } ++ ++ // Get the next character. ++ value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + ++ (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) ++ ++ // Check for a low surrogate area. ++ if value2&0xFC00 != 0xDC00 { ++ return yaml_parser_set_reader_error(parser, ++ "expected low surrogate area", ++ parser.offset+2, int(value2)) ++ } ++ ++ // Generate the value of the surrogate pair. ++ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) ++ } else { ++ width = 2 ++ } ++ ++ default: ++ panic("impossible") ++ } ++ ++ // Check if the character is in the allowed range: ++ // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) ++ // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) ++ // | [#x10000-#x10FFFF] (32 bit) ++ switch { ++ case value == 0x09: ++ case value == 0x0A: ++ case value == 0x0D: ++ case value >= 0x20 && value <= 0x7E: ++ case value == 0x85: ++ case value >= 0xA0 && value <= 0xD7FF: ++ case value >= 0xE000 && value <= 0xFFFD: ++ case value >= 0x10000 && value <= 0x10FFFF: ++ default: ++ return yaml_parser_set_reader_error(parser, ++ "control characters are not allowed", ++ parser.offset, int(value)) ++ } ++ ++ // Move the raw pointers. ++ parser.raw_buffer_pos += width ++ parser.offset += width ++ ++ // Finally put the character into the buffer. ++ if value <= 0x7F { ++ // 0000 0000-0000 007F . 0xxxxxxx ++ parser.buffer[buffer_len+0] = byte(value) ++ buffer_len += 1 ++ } else if value <= 0x7FF { ++ // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx ++ parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) ++ parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) ++ buffer_len += 2 ++ } else if value <= 0xFFFF { ++ // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx ++ parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) ++ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) ++ parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) ++ buffer_len += 3 ++ } else { ++ // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx ++ parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) ++ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) ++ parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) ++ parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) ++ buffer_len += 4 ++ } ++ ++ parser.unread++ ++ } ++ ++ // On EOF, put NUL into the buffer and return. ++ if parser.eof { ++ parser.buffer[buffer_len] = 0 ++ buffer_len++ ++ parser.unread++ ++ break ++ } ++ } ++ // [Go] Read the documentation of this function above. To return true, ++ // we need to have the given length in the buffer. Not doing that means ++ // every single check that calls this function to make sure the buffer ++ // has a given length is Go) panicking; or C) accessing invalid memory. ++ // This happens here due to the EOF above breaking early. ++ for buffer_len < length { ++ parser.buffer[buffer_len] = 0 ++ buffer_len++ ++ } ++ parser.buffer = parser.buffer[:buffer_len] ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/resolve.go b/vendor/gopkg.in/yaml.v3/resolve.go +new file mode 100644 +index 000000000000..64ae888057a5 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/resolve.go +@@ -0,0 +1,326 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package yaml ++ ++import ( ++ "encoding/base64" ++ "math" ++ "regexp" ++ "strconv" ++ "strings" ++ "time" ++) ++ ++type resolveMapItem struct { ++ value interface{} ++ tag string ++} ++ ++var resolveTable = make([]byte, 256) ++var resolveMap = make(map[string]resolveMapItem) ++ ++func init() { ++ t := resolveTable ++ t[int('+')] = 'S' // Sign ++ t[int('-')] = 'S' ++ for _, c := range "0123456789" { ++ t[int(c)] = 'D' // Digit ++ } ++ for _, c := range "yYnNtTfFoO~" { ++ t[int(c)] = 'M' // In map ++ } ++ t[int('.')] = '.' // Float (potentially in map) ++ ++ var resolveMapList = []struct { ++ v interface{} ++ tag string ++ l []string ++ }{ ++ {true, boolTag, []string{"true", "True", "TRUE"}}, ++ {false, boolTag, []string{"false", "False", "FALSE"}}, ++ {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, ++ {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, ++ {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, ++ {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, ++ {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, ++ {"<<", mergeTag, []string{"<<"}}, ++ } ++ ++ m := resolveMap ++ for _, item := range resolveMapList { ++ for _, s := range item.l { ++ m[s] = resolveMapItem{item.v, item.tag} ++ } ++ } ++} ++ ++const ( ++ nullTag = "!!null" ++ boolTag = "!!bool" ++ strTag = "!!str" ++ intTag = "!!int" ++ floatTag = "!!float" ++ timestampTag = "!!timestamp" ++ seqTag = "!!seq" ++ mapTag = "!!map" ++ binaryTag = "!!binary" ++ mergeTag = "!!merge" ++) ++ ++var longTags = make(map[string]string) ++var shortTags = make(map[string]string) ++ ++func init() { ++ for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { ++ ltag := longTag(stag) ++ longTags[stag] = ltag ++ shortTags[ltag] = stag ++ } ++} ++ ++const longTagPrefix = "tag:yaml.org,2002:" ++ ++func shortTag(tag string) string { ++ if strings.HasPrefix(tag, longTagPrefix) { ++ if stag, ok := shortTags[tag]; ok { ++ return stag ++ } ++ return "!!" + tag[len(longTagPrefix):] ++ } ++ return tag ++} ++ ++func longTag(tag string) string { ++ if strings.HasPrefix(tag, "!!") { ++ if ltag, ok := longTags[tag]; ok { ++ return ltag ++ } ++ return longTagPrefix + tag[2:] ++ } ++ return tag ++} ++ ++func resolvableTag(tag string) bool { ++ switch tag { ++ case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: ++ return true ++ } ++ return false ++} ++ ++var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) ++ ++func resolve(tag string, in string) (rtag string, out interface{}) { ++ tag = shortTag(tag) ++ if !resolvableTag(tag) { ++ return tag, in ++ } ++ ++ defer func() { ++ switch tag { ++ case "", rtag, strTag, binaryTag: ++ return ++ case floatTag: ++ if rtag == intTag { ++ switch v := out.(type) { ++ case int64: ++ rtag = floatTag ++ out = float64(v) ++ return ++ case int: ++ rtag = floatTag ++ out = float64(v) ++ return ++ } ++ } ++ } ++ failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) ++ }() ++ ++ // Any data is accepted as a !!str or !!binary. ++ // Otherwise, the prefix is enough of a hint about what it might be. ++ hint := byte('N') ++ if in != "" { ++ hint = resolveTable[in[0]] ++ } ++ if hint != 0 && tag != strTag && tag != binaryTag { ++ // Handle things we can lookup in a map. ++ if item, ok := resolveMap[in]; ok { ++ return item.tag, item.value ++ } ++ ++ // Base 60 floats are a bad idea, were dropped in YAML 1.2, and ++ // are purposefully unsupported here. They're still quoted on ++ // the way out for compatibility with other parser, though. ++ ++ switch hint { ++ case 'M': ++ // We've already checked the map above. ++ ++ case '.': ++ // Not in the map, so maybe a normal float. ++ floatv, err := strconv.ParseFloat(in, 64) ++ if err == nil { ++ return floatTag, floatv ++ } ++ ++ case 'D', 'S': ++ // Int, float, or timestamp. ++ // Only try values as a timestamp if the value is unquoted or there's an explicit ++ // !!timestamp tag. ++ if tag == "" || tag == timestampTag { ++ t, ok := parseTimestamp(in) ++ if ok { ++ return timestampTag, t ++ } ++ } ++ ++ plain := strings.Replace(in, "_", "", -1) ++ intv, err := strconv.ParseInt(plain, 0, 64) ++ if err == nil { ++ if intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ uintv, err := strconv.ParseUint(plain, 0, 64) ++ if err == nil { ++ return intTag, uintv ++ } ++ if yamlStyleFloat.MatchString(plain) { ++ floatv, err := strconv.ParseFloat(plain, 64) ++ if err == nil { ++ return floatTag, floatv ++ } ++ } ++ if strings.HasPrefix(plain, "0b") { ++ intv, err := strconv.ParseInt(plain[2:], 2, 64) ++ if err == nil { ++ if intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ uintv, err := strconv.ParseUint(plain[2:], 2, 64) ++ if err == nil { ++ return intTag, uintv ++ } ++ } else if strings.HasPrefix(plain, "-0b") { ++ intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) ++ if err == nil { ++ if true || intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ } ++ // Octals as introduced in version 1.2 of the spec. ++ // Octals from the 1.1 spec, spelled as 0777, are still ++ // decoded by default in v3 as well for compatibility. ++ // May be dropped in v4 depending on how usage evolves. ++ if strings.HasPrefix(plain, "0o") { ++ intv, err := strconv.ParseInt(plain[2:], 8, 64) ++ if err == nil { ++ if intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ uintv, err := strconv.ParseUint(plain[2:], 8, 64) ++ if err == nil { ++ return intTag, uintv ++ } ++ } else if strings.HasPrefix(plain, "-0o") { ++ intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) ++ if err == nil { ++ if true || intv == int64(int(intv)) { ++ return intTag, int(intv) ++ } else { ++ return intTag, intv ++ } ++ } ++ } ++ default: ++ panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") ++ } ++ } ++ return strTag, in ++} ++ ++// encodeBase64 encodes s as base64 that is broken up into multiple lines ++// as appropriate for the resulting length. ++func encodeBase64(s string) string { ++ const lineLen = 70 ++ encLen := base64.StdEncoding.EncodedLen(len(s)) ++ lines := encLen/lineLen + 1 ++ buf := make([]byte, encLen*2+lines) ++ in := buf[0:encLen] ++ out := buf[encLen:] ++ base64.StdEncoding.Encode(in, []byte(s)) ++ k := 0 ++ for i := 0; i < len(in); i += lineLen { ++ j := i + lineLen ++ if j > len(in) { ++ j = len(in) ++ } ++ k += copy(out[k:], in[i:j]) ++ if lines > 1 { ++ out[k] = '\n' ++ k++ ++ } ++ } ++ return string(out[:k]) ++} ++ ++// This is a subset of the formats allowed by the regular expression ++// defined at http://yaml.org/type/timestamp.html. ++var allowedTimestampFormats = []string{ ++ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. ++ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". ++ "2006-1-2 15:4:5.999999999", // space separated with no time zone ++ "2006-1-2", // date only ++ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" ++ // from the set of examples. ++} ++ ++// parseTimestamp parses s as a timestamp string and ++// returns the timestamp and reports whether it succeeded. ++// Timestamp formats are defined at http://yaml.org/type/timestamp.html ++func parseTimestamp(s string) (time.Time, bool) { ++ // TODO write code to check all the formats supported by ++ // http://yaml.org/type/timestamp.html instead of using time.Parse. ++ ++ // Quick check: all date formats start with YYYY-. ++ i := 0 ++ for ; i < len(s); i++ { ++ if c := s[i]; c < '0' || c > '9' { ++ break ++ } ++ } ++ if i != 4 || i == len(s) || s[i] != '-' { ++ return time.Time{}, false ++ } ++ for _, format := range allowedTimestampFormats { ++ if t, err := time.Parse(format, s); err == nil { ++ return t, true ++ } ++ } ++ return time.Time{}, false ++} +diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go +new file mode 100644 +index 000000000000..ca0070108f4e +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/scannerc.go +@@ -0,0 +1,3038 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++import ( ++ "bytes" ++ "fmt" ++) ++ ++// Introduction ++// ************ ++// ++// The following notes assume that you are familiar with the YAML specification ++// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in ++// some cases we are less restrictive that it requires. ++// ++// The process of transforming a YAML stream into a sequence of events is ++// divided on two steps: Scanning and Parsing. ++// ++// The Scanner transforms the input stream into a sequence of tokens, while the ++// parser transform the sequence of tokens produced by the Scanner into a ++// sequence of parsing events. ++// ++// The Scanner is rather clever and complicated. The Parser, on the contrary, ++// is a straightforward implementation of a recursive-descendant parser (or, ++// LL(1) parser, as it is usually called). ++// ++// Actually there are two issues of Scanning that might be called "clever", the ++// rest is quite straightforward. The issues are "block collection start" and ++// "simple keys". Both issues are explained below in details. ++// ++// Here the Scanning step is explained and implemented. We start with the list ++// of all the tokens produced by the Scanner together with short descriptions. ++// ++// Now, tokens: ++// ++// STREAM-START(encoding) # The stream start. ++// STREAM-END # The stream end. ++// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. ++// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. ++// DOCUMENT-START # '---' ++// DOCUMENT-END # '...' ++// BLOCK-SEQUENCE-START # Indentation increase denoting a block ++// BLOCK-MAPPING-START # sequence or a block mapping. ++// BLOCK-END # Indentation decrease. ++// FLOW-SEQUENCE-START # '[' ++// FLOW-SEQUENCE-END # ']' ++// BLOCK-SEQUENCE-START # '{' ++// BLOCK-SEQUENCE-END # '}' ++// BLOCK-ENTRY # '-' ++// FLOW-ENTRY # ',' ++// KEY # '?' or nothing (simple keys). ++// VALUE # ':' ++// ALIAS(anchor) # '*anchor' ++// ANCHOR(anchor) # '&anchor' ++// TAG(handle,suffix) # '!handle!suffix' ++// SCALAR(value,style) # A scalar. ++// ++// The following two tokens are "virtual" tokens denoting the beginning and the ++// end of the stream: ++// ++// STREAM-START(encoding) ++// STREAM-END ++// ++// We pass the information about the input stream encoding with the ++// STREAM-START token. ++// ++// The next two tokens are responsible for tags: ++// ++// VERSION-DIRECTIVE(major,minor) ++// TAG-DIRECTIVE(handle,prefix) ++// ++// Example: ++// ++// %YAML 1.1 ++// %TAG ! !foo ++// %TAG !yaml! tag:yaml.org,2002: ++// --- ++// ++// The correspoding sequence of tokens: ++// ++// STREAM-START(utf-8) ++// VERSION-DIRECTIVE(1,1) ++// TAG-DIRECTIVE("!","!foo") ++// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") ++// DOCUMENT-START ++// STREAM-END ++// ++// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole ++// line. ++// ++// The document start and end indicators are represented by: ++// ++// DOCUMENT-START ++// DOCUMENT-END ++// ++// Note that if a YAML stream contains an implicit document (without '---' ++// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be ++// produced. ++// ++// In the following examples, we present whole documents together with the ++// produced tokens. ++// ++// 1. An implicit document: ++// ++// 'a scalar' ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// SCALAR("a scalar",single-quoted) ++// STREAM-END ++// ++// 2. An explicit document: ++// ++// --- ++// 'a scalar' ++// ... ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// DOCUMENT-START ++// SCALAR("a scalar",single-quoted) ++// DOCUMENT-END ++// STREAM-END ++// ++// 3. Several documents in a stream: ++// ++// 'a scalar' ++// --- ++// 'another scalar' ++// --- ++// 'yet another scalar' ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// SCALAR("a scalar",single-quoted) ++// DOCUMENT-START ++// SCALAR("another scalar",single-quoted) ++// DOCUMENT-START ++// SCALAR("yet another scalar",single-quoted) ++// STREAM-END ++// ++// We have already introduced the SCALAR token above. The following tokens are ++// used to describe aliases, anchors, tag, and scalars: ++// ++// ALIAS(anchor) ++// ANCHOR(anchor) ++// TAG(handle,suffix) ++// SCALAR(value,style) ++// ++// The following series of examples illustrate the usage of these tokens: ++// ++// 1. A recursive sequence: ++// ++// &A [ *A ] ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// ANCHOR("A") ++// FLOW-SEQUENCE-START ++// ALIAS("A") ++// FLOW-SEQUENCE-END ++// STREAM-END ++// ++// 2. A tagged scalar: ++// ++// !!float "3.14" # A good approximation. ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// TAG("!!","float") ++// SCALAR("3.14",double-quoted) ++// STREAM-END ++// ++// 3. Various scalar styles: ++// ++// --- # Implicit empty plain scalars do not produce tokens. ++// --- a plain scalar ++// --- 'a single-quoted scalar' ++// --- "a double-quoted scalar" ++// --- |- ++// a literal scalar ++// --- >- ++// a folded ++// scalar ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// DOCUMENT-START ++// DOCUMENT-START ++// SCALAR("a plain scalar",plain) ++// DOCUMENT-START ++// SCALAR("a single-quoted scalar",single-quoted) ++// DOCUMENT-START ++// SCALAR("a double-quoted scalar",double-quoted) ++// DOCUMENT-START ++// SCALAR("a literal scalar",literal) ++// DOCUMENT-START ++// SCALAR("a folded scalar",folded) ++// STREAM-END ++// ++// Now it's time to review collection-related tokens. We will start with ++// flow collections: ++// ++// FLOW-SEQUENCE-START ++// FLOW-SEQUENCE-END ++// FLOW-MAPPING-START ++// FLOW-MAPPING-END ++// FLOW-ENTRY ++// KEY ++// VALUE ++// ++// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and ++// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' ++// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the ++// indicators '?' and ':', which are used for denoting mapping keys and values, ++// are represented by the KEY and VALUE tokens. ++// ++// The following examples show flow collections: ++// ++// 1. A flow sequence: ++// ++// [item 1, item 2, item 3] ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// FLOW-SEQUENCE-START ++// SCALAR("item 1",plain) ++// FLOW-ENTRY ++// SCALAR("item 2",plain) ++// FLOW-ENTRY ++// SCALAR("item 3",plain) ++// FLOW-SEQUENCE-END ++// STREAM-END ++// ++// 2. A flow mapping: ++// ++// { ++// a simple key: a value, # Note that the KEY token is produced. ++// ? a complex key: another value, ++// } ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// FLOW-MAPPING-START ++// KEY ++// SCALAR("a simple key",plain) ++// VALUE ++// SCALAR("a value",plain) ++// FLOW-ENTRY ++// KEY ++// SCALAR("a complex key",plain) ++// VALUE ++// SCALAR("another value",plain) ++// FLOW-ENTRY ++// FLOW-MAPPING-END ++// STREAM-END ++// ++// A simple key is a key which is not denoted by the '?' indicator. Note that ++// the Scanner still produce the KEY token whenever it encounters a simple key. ++// ++// For scanning block collections, the following tokens are used (note that we ++// repeat KEY and VALUE here): ++// ++// BLOCK-SEQUENCE-START ++// BLOCK-MAPPING-START ++// BLOCK-END ++// BLOCK-ENTRY ++// KEY ++// VALUE ++// ++// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation ++// increase that precedes a block collection (cf. the INDENT token in Python). ++// The token BLOCK-END denote indentation decrease that ends a block collection ++// (cf. the DEDENT token in Python). However YAML has some syntax pecularities ++// that makes detections of these tokens more complex. ++// ++// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators ++// '-', '?', and ':' correspondingly. ++// ++// The following examples show how the tokens BLOCK-SEQUENCE-START, ++// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: ++// ++// 1. Block sequences: ++// ++// - item 1 ++// - item 2 ++// - ++// - item 3.1 ++// - item 3.2 ++// - ++// key 1: value 1 ++// key 2: value 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-ENTRY ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 3.1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 3.2",plain) ++// BLOCK-END ++// BLOCK-ENTRY ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// 2. Block mappings: ++// ++// a simple key: a value # The KEY token is produced here. ++// ? a complex key ++// : another value ++// a mapping: ++// key 1: value 1 ++// key 2: value 2 ++// a sequence: ++// - item 1 ++// - item 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("a simple key",plain) ++// VALUE ++// SCALAR("a value",plain) ++// KEY ++// SCALAR("a complex key",plain) ++// VALUE ++// SCALAR("another value",plain) ++// KEY ++// SCALAR("a mapping",plain) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// KEY ++// SCALAR("a sequence",plain) ++// VALUE ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// YAML does not always require to start a new block collection from a new ++// line. If the current line contains only '-', '?', and ':' indicators, a new ++// block collection may start at the current line. The following examples ++// illustrate this case: ++// ++// 1. Collections in a sequence: ++// ++// - - item 1 ++// - item 2 ++// - key 1: value 1 ++// key 2: value 2 ++// - ? complex key ++// : complex value ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// BLOCK-ENTRY ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// BLOCK-ENTRY ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("complex key") ++// VALUE ++// SCALAR("complex value") ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// 2. Collections in a mapping: ++// ++// ? a sequence ++// : - item 1 ++// - item 2 ++// ? a mapping ++// : key 1: value 1 ++// key 2: value 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("a sequence",plain) ++// VALUE ++// BLOCK-SEQUENCE-START ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// KEY ++// SCALAR("a mapping",plain) ++// VALUE ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key 1",plain) ++// VALUE ++// SCALAR("value 1",plain) ++// KEY ++// SCALAR("key 2",plain) ++// VALUE ++// SCALAR("value 2",plain) ++// BLOCK-END ++// BLOCK-END ++// STREAM-END ++// ++// YAML also permits non-indented sequences if they are included into a block ++// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: ++// ++// key: ++// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. ++// - item 2 ++// ++// Tokens: ++// ++// STREAM-START(utf-8) ++// BLOCK-MAPPING-START ++// KEY ++// SCALAR("key",plain) ++// VALUE ++// BLOCK-ENTRY ++// SCALAR("item 1",plain) ++// BLOCK-ENTRY ++// SCALAR("item 2",plain) ++// BLOCK-END ++// ++ ++// Ensure that the buffer contains the required number of characters. ++// Return true on success, false on failure (reader error or memory error). ++func cache(parser *yaml_parser_t, length int) bool { ++ // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) ++ return parser.unread >= length || yaml_parser_update_buffer(parser, length) ++} ++ ++// Advance the buffer pointer. ++func skip(parser *yaml_parser_t) { ++ if !is_blank(parser.buffer, parser.buffer_pos) { ++ parser.newlines = 0 ++ } ++ parser.mark.index++ ++ parser.mark.column++ ++ parser.unread-- ++ parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) ++} ++ ++func skip_line(parser *yaml_parser_t) { ++ if is_crlf(parser.buffer, parser.buffer_pos) { ++ parser.mark.index += 2 ++ parser.mark.column = 0 ++ parser.mark.line++ ++ parser.unread -= 2 ++ parser.buffer_pos += 2 ++ parser.newlines++ ++ } else if is_break(parser.buffer, parser.buffer_pos) { ++ parser.mark.index++ ++ parser.mark.column = 0 ++ parser.mark.line++ ++ parser.unread-- ++ parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) ++ parser.newlines++ ++ } ++} ++ ++// Copy a character to a string buffer and advance pointers. ++func read(parser *yaml_parser_t, s []byte) []byte { ++ if !is_blank(parser.buffer, parser.buffer_pos) { ++ parser.newlines = 0 ++ } ++ w := width(parser.buffer[parser.buffer_pos]) ++ if w == 0 { ++ panic("invalid character sequence") ++ } ++ if len(s) == 0 { ++ s = make([]byte, 0, 32) ++ } ++ if w == 1 && len(s)+w <= cap(s) { ++ s = s[:len(s)+1] ++ s[len(s)-1] = parser.buffer[parser.buffer_pos] ++ parser.buffer_pos++ ++ } else { ++ s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) ++ parser.buffer_pos += w ++ } ++ parser.mark.index++ ++ parser.mark.column++ ++ parser.unread-- ++ return s ++} ++ ++// Copy a line break character to a string buffer and advance pointers. ++func read_line(parser *yaml_parser_t, s []byte) []byte { ++ buf := parser.buffer ++ pos := parser.buffer_pos ++ switch { ++ case buf[pos] == '\r' && buf[pos+1] == '\n': ++ // CR LF . LF ++ s = append(s, '\n') ++ parser.buffer_pos += 2 ++ parser.mark.index++ ++ parser.unread-- ++ case buf[pos] == '\r' || buf[pos] == '\n': ++ // CR|LF . LF ++ s = append(s, '\n') ++ parser.buffer_pos += 1 ++ case buf[pos] == '\xC2' && buf[pos+1] == '\x85': ++ // NEL . LF ++ s = append(s, '\n') ++ parser.buffer_pos += 2 ++ case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): ++ // LS|PS . LS|PS ++ s = append(s, buf[parser.buffer_pos:pos+3]...) ++ parser.buffer_pos += 3 ++ default: ++ return s ++ } ++ parser.mark.index++ ++ parser.mark.column = 0 ++ parser.mark.line++ ++ parser.unread-- ++ parser.newlines++ ++ return s ++} ++ ++// Get the next token. ++func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { ++ // Erase the token object. ++ *token = yaml_token_t{} // [Go] Is this necessary? ++ ++ // No tokens after STREAM-END or error. ++ if parser.stream_end_produced || parser.error != yaml_NO_ERROR { ++ return true ++ } ++ ++ // Ensure that the tokens queue contains enough tokens. ++ if !parser.token_available { ++ if !yaml_parser_fetch_more_tokens(parser) { ++ return false ++ } ++ } ++ ++ // Fetch the next token from the queue. ++ *token = parser.tokens[parser.tokens_head] ++ parser.tokens_head++ ++ parser.tokens_parsed++ ++ parser.token_available = false ++ ++ if token.typ == yaml_STREAM_END_TOKEN { ++ parser.stream_end_produced = true ++ } ++ return true ++} ++ ++// Set the scanner error and return false. ++func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { ++ parser.error = yaml_SCANNER_ERROR ++ parser.context = context ++ parser.context_mark = context_mark ++ parser.problem = problem ++ parser.problem_mark = parser.mark ++ return false ++} ++ ++func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { ++ context := "while parsing a tag" ++ if directive { ++ context = "while parsing a %TAG directive" ++ } ++ return yaml_parser_set_scanner_error(parser, context, context_mark, problem) ++} ++ ++func trace(args ...interface{}) func() { ++ pargs := append([]interface{}{"+++"}, args...) ++ fmt.Println(pargs...) ++ pargs = append([]interface{}{"---"}, args...) ++ return func() { fmt.Println(pargs...) } ++} ++ ++// Ensure that the tokens queue contains at least one token which can be ++// returned to the Parser. ++func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { ++ // While we need more tokens to fetch, do it. ++ for { ++ // [Go] The comment parsing logic requires a lookahead of two tokens ++ // so that foot comments may be parsed in time of associating them ++ // with the tokens that are parsed before them, and also for line ++ // comments to be transformed into head comments in some edge cases. ++ if parser.tokens_head < len(parser.tokens)-2 { ++ // If a potential simple key is at the head position, we need to fetch ++ // the next token to disambiguate it. ++ head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] ++ if !ok { ++ break ++ } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { ++ return false ++ } else if !valid { ++ break ++ } ++ } ++ // Fetch the next token. ++ if !yaml_parser_fetch_next_token(parser) { ++ return false ++ } ++ } ++ ++ parser.token_available = true ++ return true ++} ++ ++// The dispatcher for token fetchers. ++func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { ++ // Ensure that the buffer is initialized. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // Check if we just started scanning. Fetch STREAM-START then. ++ if !parser.stream_start_produced { ++ return yaml_parser_fetch_stream_start(parser) ++ } ++ ++ scan_mark := parser.mark ++ ++ // Eat whitespaces and comments until we reach the next token. ++ if !yaml_parser_scan_to_next_token(parser) { ++ return false ++ } ++ ++ // [Go] While unrolling indents, transform the head comments of prior ++ // indentation levels observed after scan_start into foot comments at ++ // the respective indexes. ++ ++ // Check the indentation level against the current column. ++ if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) { ++ return false ++ } ++ ++ // Ensure that the buffer contains at least 4 characters. 4 is the length ++ // of the longest indicators ('--- ' and '... '). ++ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { ++ return false ++ } ++ ++ // Is it the end of the stream? ++ if is_z(parser.buffer, parser.buffer_pos) { ++ return yaml_parser_fetch_stream_end(parser) ++ } ++ ++ // Is it a directive? ++ if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { ++ return yaml_parser_fetch_directive(parser) ++ } ++ ++ buf := parser.buffer ++ pos := parser.buffer_pos ++ ++ // Is it the document start indicator? ++ if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { ++ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) ++ } ++ ++ // Is it the document end indicator? ++ if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { ++ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) ++ } ++ ++ comment_mark := parser.mark ++ if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { ++ // Associate any following comments with the prior token. ++ comment_mark = parser.tokens[len(parser.tokens)-1].start_mark ++ } ++ defer func() { ++ if !ok { ++ return ++ } ++ if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { ++ // Sequence indicators alone have no line comments. It becomes ++ // a head comment for whatever follows. ++ return ++ } ++ if !yaml_parser_scan_line_comment(parser, comment_mark) { ++ ok = false ++ return ++ } ++ }() ++ ++ // Is it the flow sequence start indicator? ++ if buf[pos] == '[' { ++ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) ++ } ++ ++ // Is it the flow mapping start indicator? ++ if parser.buffer[parser.buffer_pos] == '{' { ++ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) ++ } ++ ++ // Is it the flow sequence end indicator? ++ if parser.buffer[parser.buffer_pos] == ']' { ++ return yaml_parser_fetch_flow_collection_end(parser, ++ yaml_FLOW_SEQUENCE_END_TOKEN) ++ } ++ ++ // Is it the flow mapping end indicator? ++ if parser.buffer[parser.buffer_pos] == '}' { ++ return yaml_parser_fetch_flow_collection_end(parser, ++ yaml_FLOW_MAPPING_END_TOKEN) ++ } ++ ++ // Is it the flow entry indicator? ++ if parser.buffer[parser.buffer_pos] == ',' { ++ return yaml_parser_fetch_flow_entry(parser) ++ } ++ ++ // Is it the block entry indicator? ++ if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { ++ return yaml_parser_fetch_block_entry(parser) ++ } ++ ++ // Is it the key indicator? ++ if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { ++ return yaml_parser_fetch_key(parser) ++ } ++ ++ // Is it the value indicator? ++ if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { ++ return yaml_parser_fetch_value(parser) ++ } ++ ++ // Is it an alias? ++ if parser.buffer[parser.buffer_pos] == '*' { ++ return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) ++ } ++ ++ // Is it an anchor? ++ if parser.buffer[parser.buffer_pos] == '&' { ++ return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) ++ } ++ ++ // Is it a tag? ++ if parser.buffer[parser.buffer_pos] == '!' { ++ return yaml_parser_fetch_tag(parser) ++ } ++ ++ // Is it a literal scalar? ++ if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { ++ return yaml_parser_fetch_block_scalar(parser, true) ++ } ++ ++ // Is it a folded scalar? ++ if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { ++ return yaml_parser_fetch_block_scalar(parser, false) ++ } ++ ++ // Is it a single-quoted scalar? ++ if parser.buffer[parser.buffer_pos] == '\'' { ++ return yaml_parser_fetch_flow_scalar(parser, true) ++ } ++ ++ // Is it a double-quoted scalar? ++ if parser.buffer[parser.buffer_pos] == '"' { ++ return yaml_parser_fetch_flow_scalar(parser, false) ++ } ++ ++ // Is it a plain scalar? ++ // ++ // A plain scalar may start with any non-blank characters except ++ // ++ // '-', '?', ':', ',', '[', ']', '{', '}', ++ // '#', '&', '*', '!', '|', '>', '\'', '\"', ++ // '%', '@', '`'. ++ // ++ // In the block context (and, for the '-' indicator, in the flow context ++ // too), it may also start with the characters ++ // ++ // '-', '?', ':' ++ // ++ // if it is followed by a non-space character. ++ // ++ // The last rule is more restrictive than the specification requires. ++ // [Go] TODO Make this logic more reasonable. ++ //switch parser.buffer[parser.buffer_pos] { ++ //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': ++ //} ++ if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || ++ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || ++ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || ++ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || ++ parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || ++ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || ++ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || ++ parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || ++ parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || ++ parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || ++ (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || ++ (parser.flow_level == 0 && ++ (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && ++ !is_blankz(parser.buffer, parser.buffer_pos+1)) { ++ return yaml_parser_fetch_plain_scalar(parser) ++ } ++ ++ // If we don't determine the token type so far, it is an error. ++ return yaml_parser_set_scanner_error(parser, ++ "while scanning for the next token", parser.mark, ++ "found character that cannot start any token") ++} ++ ++func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { ++ if !simple_key.possible { ++ return false, true ++ } ++ ++ // The 1.2 specification says: ++ // ++ // "If the ? indicator is omitted, parsing needs to see past the ++ // implicit key to recognize it as such. To limit the amount of ++ // lookahead required, the “:” indicator must appear at most 1024 ++ // Unicode characters beyond the start of the key. In addition, the key ++ // is restricted to a single line." ++ // ++ if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { ++ // Check if the potential simple key to be removed is required. ++ if simple_key.required { ++ return false, yaml_parser_set_scanner_error(parser, ++ "while scanning a simple key", simple_key.mark, ++ "could not find expected ':'") ++ } ++ simple_key.possible = false ++ return false, true ++ } ++ return true, true ++} ++ ++// Check if a simple key may start at the current position and add it if ++// needed. ++func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { ++ // A simple key is required at the current position if the scanner is in ++ // the block context and the current column coincides with the indentation ++ // level. ++ ++ required := parser.flow_level == 0 && parser.indent == parser.mark.column ++ ++ // ++ // If the current position may start a simple key, save it. ++ // ++ if parser.simple_key_allowed { ++ simple_key := yaml_simple_key_t{ ++ possible: true, ++ required: required, ++ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), ++ mark: parser.mark, ++ } ++ ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ parser.simple_keys[len(parser.simple_keys)-1] = simple_key ++ parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 ++ } ++ return true ++} ++ ++// Remove a potential simple key at the current flow level. ++func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { ++ i := len(parser.simple_keys) - 1 ++ if parser.simple_keys[i].possible { ++ // If the key is required, it is an error. ++ if parser.simple_keys[i].required { ++ return yaml_parser_set_scanner_error(parser, ++ "while scanning a simple key", parser.simple_keys[i].mark, ++ "could not find expected ':'") ++ } ++ // Remove the key from the stack. ++ parser.simple_keys[i].possible = false ++ delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) ++ } ++ return true ++} ++ ++// max_flow_level limits the flow_level ++const max_flow_level = 10000 ++ ++// Increase the flow level and resize the simple key list if needed. ++func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { ++ // Reset the simple key on the next level. ++ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ ++ possible: false, ++ required: false, ++ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), ++ mark: parser.mark, ++ }) ++ ++ // Increase the flow level. ++ parser.flow_level++ ++ if parser.flow_level > max_flow_level { ++ return yaml_parser_set_scanner_error(parser, ++ "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, ++ fmt.Sprintf("exceeded max depth of %d", max_flow_level)) ++ } ++ return true ++} ++ ++// Decrease the flow level. ++func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { ++ if parser.flow_level > 0 { ++ parser.flow_level-- ++ last := len(parser.simple_keys) - 1 ++ delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) ++ parser.simple_keys = parser.simple_keys[:last] ++ } ++ return true ++} ++ ++// max_indents limits the indents stack size ++const max_indents = 10000 ++ ++// Push the current indentation level to the stack and set the new level ++// the current column is greater than the indentation level. In this case, ++// append or insert the specified token into the token queue. ++func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { ++ // In the flow context, do nothing. ++ if parser.flow_level > 0 { ++ return true ++ } ++ ++ if parser.indent < column { ++ // Push the current indentation level to the stack and set the new ++ // indentation level. ++ parser.indents = append(parser.indents, parser.indent) ++ parser.indent = column ++ if len(parser.indents) > max_indents { ++ return yaml_parser_set_scanner_error(parser, ++ "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, ++ fmt.Sprintf("exceeded max depth of %d", max_indents)) ++ } ++ ++ // Create a token and insert it into the queue. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: mark, ++ end_mark: mark, ++ } ++ if number > -1 { ++ number -= parser.tokens_parsed ++ } ++ yaml_insert_token(parser, number, &token) ++ } ++ return true ++} ++ ++// Pop indentation levels from the indents stack until the current level ++// becomes less or equal to the column. For each indentation level, append ++// the BLOCK-END token. ++func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool { ++ // In the flow context, do nothing. ++ if parser.flow_level > 0 { ++ return true ++ } ++ ++ block_mark := scan_mark ++ block_mark.index-- ++ ++ // Loop through the indentation levels in the stack. ++ for parser.indent > column { ++ ++ // [Go] Reposition the end token before potential following ++ // foot comments of parent blocks. For that, search ++ // backwards for recent comments that were at the same ++ // indent as the block that is ending now. ++ stop_index := block_mark.index ++ for i := len(parser.comments) - 1; i >= 0; i-- { ++ comment := &parser.comments[i] ++ ++ if comment.end_mark.index < stop_index { ++ // Don't go back beyond the start of the comment/whitespace scan, unless column < 0. ++ // If requested indent column is < 0, then the document is over and everything else ++ // is a foot anyway. ++ break ++ } ++ if comment.start_mark.column == parser.indent+1 { ++ // This is a good match. But maybe there's a former comment ++ // at that same indent level, so keep searching. ++ block_mark = comment.start_mark ++ } ++ ++ // While the end of the former comment matches with ++ // the start of the following one, we know there's ++ // nothing in between and scanning is still safe. ++ stop_index = comment.scan_mark.index ++ } ++ ++ // Create a token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_BLOCK_END_TOKEN, ++ start_mark: block_mark, ++ end_mark: block_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ ++ // Pop the indentation level. ++ parser.indent = parser.indents[len(parser.indents)-1] ++ parser.indents = parser.indents[:len(parser.indents)-1] ++ } ++ return true ++} ++ ++// Initialize the scanner and produce the STREAM-START token. ++func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { ++ ++ // Set the initial indentation. ++ parser.indent = -1 ++ ++ // Initialize the simple key stack. ++ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) ++ ++ parser.simple_keys_by_tok = make(map[int]int) ++ ++ // A simple key is allowed at the beginning of the stream. ++ parser.simple_key_allowed = true ++ ++ // We have started. ++ parser.stream_start_produced = true ++ ++ // Create the STREAM-START token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_STREAM_START_TOKEN, ++ start_mark: parser.mark, ++ end_mark: parser.mark, ++ encoding: parser.encoding, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the STREAM-END token and shut down the scanner. ++func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { ++ ++ // Force new line. ++ if parser.mark.column != 0 { ++ parser.mark.column = 0 ++ parser.mark.line++ ++ } ++ ++ // Reset the indentation level. ++ if !yaml_parser_unroll_indent(parser, -1, parser.mark) { ++ return false ++ } ++ ++ // Reset simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ parser.simple_key_allowed = false ++ ++ // Create the STREAM-END token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_STREAM_END_TOKEN, ++ start_mark: parser.mark, ++ end_mark: parser.mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. ++func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { ++ // Reset the indentation level. ++ if !yaml_parser_unroll_indent(parser, -1, parser.mark) { ++ return false ++ } ++ ++ // Reset simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ parser.simple_key_allowed = false ++ ++ // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. ++ token := yaml_token_t{} ++ if !yaml_parser_scan_directive(parser, &token) { ++ return false ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the DOCUMENT-START or DOCUMENT-END token. ++func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ // Reset the indentation level. ++ if !yaml_parser_unroll_indent(parser, -1, parser.mark) { ++ return false ++ } ++ ++ // Reset simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ parser.simple_key_allowed = false ++ ++ // Consume the token. ++ start_mark := parser.mark ++ ++ skip(parser) ++ skip(parser) ++ skip(parser) ++ ++ end_mark := parser.mark ++ ++ // Create the DOCUMENT-START or DOCUMENT-END token. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. ++func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ ++ // The indicators '[' and '{' may start a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // Increase the flow level. ++ if !yaml_parser_increase_flow_level(parser) { ++ return false ++ } ++ ++ // A simple key may follow the indicators '[' and '{'. ++ parser.simple_key_allowed = true ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. ++func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ // Reset any potential simple key on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Decrease the flow level. ++ if !yaml_parser_decrease_flow_level(parser) { ++ return false ++ } ++ ++ // No simple keys after the indicators ']' and '}'. ++ parser.simple_key_allowed = false ++ ++ // Consume the token. ++ ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. ++ token := yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ // Append the token to the queue. ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the FLOW-ENTRY token. ++func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { ++ // Reset any potential simple keys on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Simple keys are allowed after ','. ++ parser.simple_key_allowed = true ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the FLOW-ENTRY token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_FLOW_ENTRY_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the BLOCK-ENTRY token. ++func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { ++ // Check if the scanner is in the block context. ++ if parser.flow_level == 0 { ++ // Check if we are allowed to start a new entry. ++ if !parser.simple_key_allowed { ++ return yaml_parser_set_scanner_error(parser, "", parser.mark, ++ "block sequence entries are not allowed in this context") ++ } ++ // Add the BLOCK-SEQUENCE-START token if needed. ++ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { ++ return false ++ } ++ } else { ++ // It is an error for the '-' indicator to occur in the flow context, ++ // but we let the Parser detect and report about it because the Parser ++ // is able to point to the context. ++ } ++ ++ // Reset any potential simple keys on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Simple keys are allowed after '-'. ++ parser.simple_key_allowed = true ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the BLOCK-ENTRY token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_BLOCK_ENTRY_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the KEY token. ++func yaml_parser_fetch_key(parser *yaml_parser_t) bool { ++ ++ // In the block context, additional checks are required. ++ if parser.flow_level == 0 { ++ // Check if we are allowed to start a new key (not nessesary simple). ++ if !parser.simple_key_allowed { ++ return yaml_parser_set_scanner_error(parser, "", parser.mark, ++ "mapping keys are not allowed in this context") ++ } ++ // Add the BLOCK-MAPPING-START token if needed. ++ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { ++ return false ++ } ++ } ++ ++ // Reset any potential simple keys on the current flow level. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // Simple keys are allowed after '?' in the block context. ++ parser.simple_key_allowed = parser.flow_level == 0 ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the KEY token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_KEY_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the VALUE token. ++func yaml_parser_fetch_value(parser *yaml_parser_t) bool { ++ ++ simple_key := &parser.simple_keys[len(parser.simple_keys)-1] ++ ++ // Have we found a simple key? ++ if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { ++ return false ++ ++ } else if valid { ++ ++ // Create the KEY token and insert it into the queue. ++ token := yaml_token_t{ ++ typ: yaml_KEY_TOKEN, ++ start_mark: simple_key.mark, ++ end_mark: simple_key.mark, ++ } ++ yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) ++ ++ // In the block context, we may need to add the BLOCK-MAPPING-START token. ++ if !yaml_parser_roll_indent(parser, simple_key.mark.column, ++ simple_key.token_number, ++ yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { ++ return false ++ } ++ ++ // Remove the simple key. ++ simple_key.possible = false ++ delete(parser.simple_keys_by_tok, simple_key.token_number) ++ ++ // A simple key cannot follow another simple key. ++ parser.simple_key_allowed = false ++ ++ } else { ++ // The ':' indicator follows a complex key. ++ ++ // In the block context, extra checks are required. ++ if parser.flow_level == 0 { ++ ++ // Check if we are allowed to start a complex value. ++ if !parser.simple_key_allowed { ++ return yaml_parser_set_scanner_error(parser, "", parser.mark, ++ "mapping values are not allowed in this context") ++ } ++ ++ // Add the BLOCK-MAPPING-START token if needed. ++ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { ++ return false ++ } ++ } ++ ++ // Simple keys after ':' are allowed in the block context. ++ parser.simple_key_allowed = parser.flow_level == 0 ++ } ++ ++ // Consume the token. ++ start_mark := parser.mark ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create the VALUE token and append it to the queue. ++ token := yaml_token_t{ ++ typ: yaml_VALUE_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the ALIAS or ANCHOR token. ++func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { ++ // An anchor or an alias could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow an anchor or an alias. ++ parser.simple_key_allowed = false ++ ++ // Create the ALIAS or ANCHOR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_anchor(parser, &token, typ) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the TAG token. ++func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { ++ // A tag could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow a tag. ++ parser.simple_key_allowed = false ++ ++ // Create the TAG token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_tag(parser, &token) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. ++func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { ++ // Remove any potential simple keys. ++ if !yaml_parser_remove_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key may follow a block scalar. ++ parser.simple_key_allowed = true ++ ++ // Create the SCALAR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_block_scalar(parser, &token, literal) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. ++func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { ++ // A plain scalar could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow a flow scalar. ++ parser.simple_key_allowed = false ++ ++ // Create the SCALAR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_flow_scalar(parser, &token, single) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Produce the SCALAR(...,plain) token. ++func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { ++ // A plain scalar could be a simple key. ++ if !yaml_parser_save_simple_key(parser) { ++ return false ++ } ++ ++ // A simple key cannot follow a flow scalar. ++ parser.simple_key_allowed = false ++ ++ // Create the SCALAR token and append it to the queue. ++ var token yaml_token_t ++ if !yaml_parser_scan_plain_scalar(parser, &token) { ++ return false ++ } ++ yaml_insert_token(parser, -1, &token) ++ return true ++} ++ ++// Eat whitespaces and comments until the next token is found. ++func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { ++ ++ scan_mark := parser.mark ++ ++ // Until the next token is not found. ++ for { ++ // Allow the BOM mark to start a line. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ } ++ ++ // Eat whitespaces. ++ // Tabs are allowed: ++ // - in the flow context ++ // - in the block context, but not at the beginning of the line or ++ // after '-', '?', or ':' (complex value). ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if we just had a line comment under a sequence entry that ++ // looks more like a header to the following content. Similar to this: ++ // ++ // - # The comment ++ // - Some data ++ // ++ // If so, transform the line comment to a head comment and reposition. ++ if len(parser.comments) > 0 && len(parser.tokens) > 1 { ++ tokenA := parser.tokens[len(parser.tokens)-2] ++ tokenB := parser.tokens[len(parser.tokens)-1] ++ comment := &parser.comments[len(parser.comments)-1] ++ if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) { ++ // If it was in the prior line, reposition so it becomes a ++ // header of the follow up token. Otherwise, keep it in place ++ // so it becomes a header of the former. ++ comment.head = comment.line ++ comment.line = nil ++ if comment.start_mark.line == parser.mark.line-1 { ++ comment.token_mark = parser.mark ++ } ++ } ++ } ++ ++ // Eat a comment until a line break. ++ if parser.buffer[parser.buffer_pos] == '#' { ++ if !yaml_parser_scan_comments(parser, scan_mark) { ++ return false ++ } ++ } ++ ++ // If it is a line break, eat it. ++ if is_break(parser.buffer, parser.buffer_pos) { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ ++ // In the block context, a new line may start a simple key. ++ if parser.flow_level == 0 { ++ parser.simple_key_allowed = true ++ } ++ } else { ++ break // We have found a token. ++ } ++ } ++ ++ return true ++} ++ ++// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++// %TAG !yaml! tag:yaml.org,2002: \n ++// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++// ++func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { ++ // Eat '%'. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Scan the directive name. ++ var name []byte ++ if !yaml_parser_scan_directive_name(parser, start_mark, &name) { ++ return false ++ } ++ ++ // Is it a YAML directive? ++ if bytes.Equal(name, []byte("YAML")) { ++ // Scan the VERSION directive value. ++ var major, minor int8 ++ if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { ++ return false ++ } ++ end_mark := parser.mark ++ ++ // Create a VERSION-DIRECTIVE token. ++ *token = yaml_token_t{ ++ typ: yaml_VERSION_DIRECTIVE_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ major: major, ++ minor: minor, ++ } ++ ++ // Is it a TAG directive? ++ } else if bytes.Equal(name, []byte("TAG")) { ++ // Scan the TAG directive value. ++ var handle, prefix []byte ++ if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { ++ return false ++ } ++ end_mark := parser.mark ++ ++ // Create a TAG-DIRECTIVE token. ++ *token = yaml_token_t{ ++ typ: yaml_TAG_DIRECTIVE_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: handle, ++ prefix: prefix, ++ } ++ ++ // Unknown directive. ++ } else { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "found unknown directive name") ++ return false ++ } ++ ++ // Eat the rest of the line including any comments. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ if parser.buffer[parser.buffer_pos] == '#' { ++ // [Go] Discard this inline comment for the time being. ++ //if !yaml_parser_scan_line_comment(parser, start_mark) { ++ // return false ++ //} ++ for !is_breakz(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ } ++ ++ // Check if we are at the end of the line. ++ if !is_breakz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "did not find expected comment or line break") ++ return false ++ } ++ ++ // Eat a line break. ++ if is_break(parser.buffer, parser.buffer_pos) { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } ++ ++ return true ++} ++ ++// Scan the directive name. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^^^^ ++// %TAG !yaml! tag:yaml.org,2002: \n ++// ^^^ ++// ++func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { ++ // Consume the directive name. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ var s []byte ++ for is_alpha(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if the name is empty. ++ if len(s) == 0 { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "could not find expected directive name") ++ return false ++ } ++ ++ // Check for an blank character after the name. ++ if !is_blankz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a directive", ++ start_mark, "found unexpected non-alphabetical character") ++ return false ++ } ++ *name = s ++ return true ++} ++ ++// Scan the value of VERSION-DIRECTIVE. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^^^^^^ ++func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { ++ // Eat whitespaces. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Consume the major version number. ++ if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { ++ return false ++ } ++ ++ // Eat '.'. ++ if parser.buffer[parser.buffer_pos] != '.' { ++ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", ++ start_mark, "did not find expected digit or '.' character") ++ } ++ ++ skip(parser) ++ ++ // Consume the minor version number. ++ if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { ++ return false ++ } ++ return true ++} ++ ++const max_number_length = 2 ++ ++// Scan the version number of VERSION-DIRECTIVE. ++// ++// Scope: ++// %YAML 1.1 # a comment \n ++// ^ ++// %YAML 1.1 # a comment \n ++// ^ ++func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { ++ ++ // Repeat while the next character is digit. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ var value, length int8 ++ for is_digit(parser.buffer, parser.buffer_pos) { ++ // Check if the number is too long. ++ length++ ++ if length > max_number_length { ++ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", ++ start_mark, "found extremely long version number") ++ } ++ value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if the number was present. ++ if length == 0 { ++ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", ++ start_mark, "did not find expected version number") ++ } ++ *number = value ++ return true ++} ++ ++// Scan the value of a TAG-DIRECTIVE token. ++// ++// Scope: ++// %TAG !yaml! tag:yaml.org,2002: \n ++// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++// ++func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { ++ var handle_value, prefix_value []byte ++ ++ // Eat whitespaces. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Scan a handle. ++ if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { ++ return false ++ } ++ ++ // Expect a whitespace. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if !is_blank(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", ++ start_mark, "did not find expected whitespace") ++ return false ++ } ++ ++ // Eat whitespaces. ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Scan a prefix. ++ if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { ++ return false ++ } ++ ++ // Expect a whitespace or line break. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if !is_blankz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", ++ start_mark, "did not find expected whitespace or line break") ++ return false ++ } ++ ++ *handle = handle_value ++ *prefix = prefix_value ++ return true ++} ++ ++func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { ++ var s []byte ++ ++ // Eat the indicator character. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Consume the value. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_alpha(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ end_mark := parser.mark ++ ++ /* ++ * Check if length of the anchor is greater than 0 and it is followed by ++ * a whitespace character or one of the indicators: ++ * ++ * '?', ':', ',', ']', '}', '%', '@', '`'. ++ */ ++ ++ if len(s) == 0 || ++ !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || ++ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || ++ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || ++ parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || ++ parser.buffer[parser.buffer_pos] == '`') { ++ context := "while scanning an alias" ++ if typ == yaml_ANCHOR_TOKEN { ++ context = "while scanning an anchor" ++ } ++ yaml_parser_set_scanner_error(parser, context, start_mark, ++ "did not find expected alphabetic or numeric character") ++ return false ++ } ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: typ, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ } ++ ++ return true ++} ++ ++/* ++ * Scan a TAG token. ++ */ ++ ++func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { ++ var handle, suffix []byte ++ ++ start_mark := parser.mark ++ ++ // Check if the tag is in the canonical form. ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ if parser.buffer[parser.buffer_pos+1] == '<' { ++ // Keep the handle as '' ++ ++ // Eat '!<' ++ skip(parser) ++ skip(parser) ++ ++ // Consume the tag value. ++ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { ++ return false ++ } ++ ++ // Check for '>' and eat it. ++ if parser.buffer[parser.buffer_pos] != '>' { ++ yaml_parser_set_scanner_error(parser, "while scanning a tag", ++ start_mark, "did not find the expected '>'") ++ return false ++ } ++ ++ skip(parser) ++ } else { ++ // The tag has either the '!suffix' or the '!handle!suffix' form. ++ ++ // First, try to scan a handle. ++ if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { ++ return false ++ } ++ ++ // Check if it is, indeed, handle. ++ if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { ++ // Scan the suffix now. ++ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { ++ return false ++ } ++ } else { ++ // It wasn't a handle after all. Scan the rest of the tag. ++ if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { ++ return false ++ } ++ ++ // Set the handle to '!'. ++ handle = []byte{'!'} ++ ++ // A special case: the '!' tag. Set the handle to '' and the ++ // suffix to '!'. ++ if len(suffix) == 0 { ++ handle, suffix = suffix, handle ++ } ++ } ++ } ++ ++ // Check the character which ends the tag. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if !is_blankz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a tag", ++ start_mark, "did not find expected whitespace or line break") ++ return false ++ } ++ ++ end_mark := parser.mark ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_TAG_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: handle, ++ suffix: suffix, ++ } ++ return true ++} ++ ++// Scan a tag handle. ++func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { ++ // Check the initial '!' character. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if parser.buffer[parser.buffer_pos] != '!' { ++ yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find expected '!'") ++ return false ++ } ++ ++ var s []byte ++ ++ // Copy the '!' character. ++ s = read(parser, s) ++ ++ // Copy all subsequent alphabetical and numerical characters. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for is_alpha(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check if the trailing character is '!' and copy it. ++ if parser.buffer[parser.buffer_pos] == '!' { ++ s = read(parser, s) ++ } else { ++ // It's either the '!' tag or not really a tag handle. If it's a %TAG ++ // directive, it's an error. If it's a tag token, it must be a part of URI. ++ if directive && string(s) != "!" { ++ yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find expected '!'") ++ return false ++ } ++ } ++ ++ *handle = s ++ return true ++} ++ ++// Scan a tag. ++func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { ++ //size_t length = head ? strlen((char *)head) : 0 ++ var s []byte ++ hasTag := len(head) > 0 ++ ++ // Copy the head if needed. ++ // ++ // Note that we don't copy the leading '!' character. ++ if len(head) > 1 { ++ s = append(s, head[1:]...) ++ } ++ ++ // Scan the tag. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // The set of characters that may appear in URI is as follows: ++ // ++ // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', ++ // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', ++ // '%'. ++ // [Go] TODO Convert this into more reasonable logic. ++ for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || ++ parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || ++ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || ++ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || ++ parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || ++ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || ++ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || ++ parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || ++ parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || ++ parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || ++ parser.buffer[parser.buffer_pos] == '%' { ++ // Check if it is a URI-escape sequence. ++ if parser.buffer[parser.buffer_pos] == '%' { ++ if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { ++ return false ++ } ++ } else { ++ s = read(parser, s) ++ } ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ hasTag = true ++ } ++ ++ if !hasTag { ++ yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find expected tag URI") ++ return false ++ } ++ *uri = s ++ return true ++} ++ ++// Decode an URI-escape sequence corresponding to a single UTF-8 character. ++func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { ++ ++ // Decode the required number of characters. ++ w := 1024 ++ for w > 0 { ++ // Check for a URI-escaped octet. ++ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { ++ return false ++ } ++ ++ if !(parser.buffer[parser.buffer_pos] == '%' && ++ is_hex(parser.buffer, parser.buffer_pos+1) && ++ is_hex(parser.buffer, parser.buffer_pos+2)) { ++ return yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "did not find URI escaped octet") ++ } ++ ++ // Get the octet. ++ octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) ++ ++ // If it is the leading octet, determine the length of the UTF-8 sequence. ++ if w == 1024 { ++ w = width(octet) ++ if w == 0 { ++ return yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "found an incorrect leading UTF-8 octet") ++ } ++ } else { ++ // Check if the trailing octet is correct. ++ if octet&0xC0 != 0x80 { ++ return yaml_parser_set_scanner_tag_error(parser, directive, ++ start_mark, "found an incorrect trailing UTF-8 octet") ++ } ++ } ++ ++ // Copy the octet and move the pointers. ++ *s = append(*s, octet) ++ skip(parser) ++ skip(parser) ++ skip(parser) ++ w-- ++ } ++ return true ++} ++ ++// Scan a block scalar. ++func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { ++ // Eat the indicator '|' or '>'. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Scan the additional block scalar indicators. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // Check for a chomping indicator. ++ var chomping, increment int ++ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { ++ // Set the chomping method and eat the indicator. ++ if parser.buffer[parser.buffer_pos] == '+' { ++ chomping = +1 ++ } else { ++ chomping = -1 ++ } ++ skip(parser) ++ ++ // Check for an indentation indicator. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if is_digit(parser.buffer, parser.buffer_pos) { ++ // Check that the indentation is greater than 0. ++ if parser.buffer[parser.buffer_pos] == '0' { ++ yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "found an indentation indicator equal to 0") ++ return false ++ } ++ ++ // Get the indentation level and eat the indicator. ++ increment = as_digit(parser.buffer, parser.buffer_pos) ++ skip(parser) ++ } ++ ++ } else if is_digit(parser.buffer, parser.buffer_pos) { ++ // Do the same as above, but in the opposite order. ++ ++ if parser.buffer[parser.buffer_pos] == '0' { ++ yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "found an indentation indicator equal to 0") ++ return false ++ } ++ increment = as_digit(parser.buffer, parser.buffer_pos) ++ skip(parser) ++ ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { ++ if parser.buffer[parser.buffer_pos] == '+' { ++ chomping = +1 ++ } else { ++ chomping = -1 ++ } ++ skip(parser) ++ } ++ } ++ ++ // Eat whitespaces and comments to the end of the line. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for is_blank(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ if parser.buffer[parser.buffer_pos] == '#' { ++ if !yaml_parser_scan_line_comment(parser, start_mark) { ++ return false ++ } ++ for !is_breakz(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ } ++ ++ // Check if we are at the end of the line. ++ if !is_breakz(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "did not find expected comment or line break") ++ return false ++ } ++ ++ // Eat a line break. ++ if is_break(parser.buffer, parser.buffer_pos) { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } ++ ++ end_mark := parser.mark ++ ++ // Set the indentation level if it was specified. ++ var indent int ++ if increment > 0 { ++ if parser.indent >= 0 { ++ indent = parser.indent + increment ++ } else { ++ indent = increment ++ } ++ } ++ ++ // Scan the leading line breaks and determine the indentation level if needed. ++ var s, leading_break, trailing_breaks []byte ++ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { ++ return false ++ } ++ ++ // Scan the block scalar content. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ var leading_blank, trailing_blank bool ++ for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { ++ // We are at the beginning of a non-empty line. ++ ++ // Is it a trailing whitespace? ++ trailing_blank = is_blank(parser.buffer, parser.buffer_pos) ++ ++ // Check if we need to fold the leading line break. ++ if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { ++ // Do we need to join the lines by space? ++ if len(trailing_breaks) == 0 { ++ s = append(s, ' ') ++ } ++ } else { ++ s = append(s, leading_break...) ++ } ++ leading_break = leading_break[:0] ++ ++ // Append the remaining line breaks. ++ s = append(s, trailing_breaks...) ++ trailing_breaks = trailing_breaks[:0] ++ ++ // Is it a leading whitespace? ++ leading_blank = is_blank(parser.buffer, parser.buffer_pos) ++ ++ // Consume the current line. ++ for !is_breakz(parser.buffer, parser.buffer_pos) { ++ s = read(parser, s) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Consume the line break. ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ leading_break = read_line(parser, leading_break) ++ ++ // Eat the following indentation spaces and line breaks. ++ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { ++ return false ++ } ++ } ++ ++ // Chomp the tail. ++ if chomping != -1 { ++ s = append(s, leading_break...) ++ } ++ if chomping == 1 { ++ s = append(s, trailing_breaks...) ++ } ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_SCALAR_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ style: yaml_LITERAL_SCALAR_STYLE, ++ } ++ if !literal { ++ token.style = yaml_FOLDED_SCALAR_STYLE ++ } ++ return true ++} ++ ++// Scan indentation spaces and line breaks for a block scalar. Determine the ++// indentation level if needed. ++func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { ++ *end_mark = parser.mark ++ ++ // Eat the indentation spaces and line breaks. ++ max_indent := 0 ++ for { ++ // Eat the indentation spaces. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { ++ skip(parser) ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ if parser.mark.column > max_indent { ++ max_indent = parser.mark.column ++ } ++ ++ // Check for a tab character messing the indentation. ++ if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { ++ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", ++ start_mark, "found a tab character where an indentation space is expected") ++ } ++ ++ // Have we found a non-empty line? ++ if !is_break(parser.buffer, parser.buffer_pos) { ++ break ++ } ++ ++ // Consume the line break. ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ // [Go] Should really be returning breaks instead. ++ *breaks = read_line(parser, *breaks) ++ *end_mark = parser.mark ++ } ++ ++ // Determine the indentation level if needed. ++ if *indent == 0 { ++ *indent = max_indent ++ if *indent < parser.indent+1 { ++ *indent = parser.indent + 1 ++ } ++ if *indent < 1 { ++ *indent = 1 ++ } ++ } ++ return true ++} ++ ++// Scan a quoted scalar. ++func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { ++ // Eat the left quote. ++ start_mark := parser.mark ++ skip(parser) ++ ++ // Consume the content of the quoted scalar. ++ var s, leading_break, trailing_breaks, whitespaces []byte ++ for { ++ // Check that there are no document indicators at the beginning of the line. ++ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { ++ return false ++ } ++ ++ if parser.mark.column == 0 && ++ ((parser.buffer[parser.buffer_pos+0] == '-' && ++ parser.buffer[parser.buffer_pos+1] == '-' && ++ parser.buffer[parser.buffer_pos+2] == '-') || ++ (parser.buffer[parser.buffer_pos+0] == '.' && ++ parser.buffer[parser.buffer_pos+1] == '.' && ++ parser.buffer[parser.buffer_pos+2] == '.')) && ++ is_blankz(parser.buffer, parser.buffer_pos+3) { ++ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", ++ start_mark, "found unexpected document indicator") ++ return false ++ } ++ ++ // Check for EOF. ++ if is_z(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", ++ start_mark, "found unexpected end of stream") ++ return false ++ } ++ ++ // Consume non-blank characters. ++ leading_blanks := false ++ for !is_blankz(parser.buffer, parser.buffer_pos) { ++ if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { ++ // Is is an escaped single quote. ++ s = append(s, '\'') ++ skip(parser) ++ skip(parser) ++ ++ } else if single && parser.buffer[parser.buffer_pos] == '\'' { ++ // It is a right single quote. ++ break ++ } else if !single && parser.buffer[parser.buffer_pos] == '"' { ++ // It is a right double quote. ++ break ++ ++ } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { ++ // It is an escaped line break. ++ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { ++ return false ++ } ++ skip(parser) ++ skip_line(parser) ++ leading_blanks = true ++ break ++ ++ } else if !single && parser.buffer[parser.buffer_pos] == '\\' { ++ // It is an escape sequence. ++ code_length := 0 ++ ++ // Check the escape character. ++ switch parser.buffer[parser.buffer_pos+1] { ++ case '0': ++ s = append(s, 0) ++ case 'a': ++ s = append(s, '\x07') ++ case 'b': ++ s = append(s, '\x08') ++ case 't', '\t': ++ s = append(s, '\x09') ++ case 'n': ++ s = append(s, '\x0A') ++ case 'v': ++ s = append(s, '\x0B') ++ case 'f': ++ s = append(s, '\x0C') ++ case 'r': ++ s = append(s, '\x0D') ++ case 'e': ++ s = append(s, '\x1B') ++ case ' ': ++ s = append(s, '\x20') ++ case '"': ++ s = append(s, '"') ++ case '\'': ++ s = append(s, '\'') ++ case '\\': ++ s = append(s, '\\') ++ case 'N': // NEL (#x85) ++ s = append(s, '\xC2') ++ s = append(s, '\x85') ++ case '_': // #xA0 ++ s = append(s, '\xC2') ++ s = append(s, '\xA0') ++ case 'L': // LS (#x2028) ++ s = append(s, '\xE2') ++ s = append(s, '\x80') ++ s = append(s, '\xA8') ++ case 'P': // PS (#x2029) ++ s = append(s, '\xE2') ++ s = append(s, '\x80') ++ s = append(s, '\xA9') ++ case 'x': ++ code_length = 2 ++ case 'u': ++ code_length = 4 ++ case 'U': ++ code_length = 8 ++ default: ++ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", ++ start_mark, "found unknown escape character") ++ return false ++ } ++ ++ skip(parser) ++ skip(parser) ++ ++ // Consume an arbitrary escape code. ++ if code_length > 0 { ++ var value int ++ ++ // Scan the character value. ++ if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { ++ return false ++ } ++ for k := 0; k < code_length; k++ { ++ if !is_hex(parser.buffer, parser.buffer_pos+k) { ++ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", ++ start_mark, "did not find expected hexdecimal number") ++ return false ++ } ++ value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) ++ } ++ ++ // Check the value and write the character. ++ if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { ++ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", ++ start_mark, "found invalid Unicode character escape code") ++ return false ++ } ++ if value <= 0x7F { ++ s = append(s, byte(value)) ++ } else if value <= 0x7FF { ++ s = append(s, byte(0xC0+(value>>6))) ++ s = append(s, byte(0x80+(value&0x3F))) ++ } else if value <= 0xFFFF { ++ s = append(s, byte(0xE0+(value>>12))) ++ s = append(s, byte(0x80+((value>>6)&0x3F))) ++ s = append(s, byte(0x80+(value&0x3F))) ++ } else { ++ s = append(s, byte(0xF0+(value>>18))) ++ s = append(s, byte(0x80+((value>>12)&0x3F))) ++ s = append(s, byte(0x80+((value>>6)&0x3F))) ++ s = append(s, byte(0x80+(value&0x3F))) ++ } ++ ++ // Advance the pointer. ++ for k := 0; k < code_length; k++ { ++ skip(parser) ++ } ++ } ++ } else { ++ // It is a non-escaped non-blank character. ++ s = read(parser, s) ++ } ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ } ++ ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ // Check if we are at the end of the scalar. ++ if single { ++ if parser.buffer[parser.buffer_pos] == '\'' { ++ break ++ } ++ } else { ++ if parser.buffer[parser.buffer_pos] == '"' { ++ break ++ } ++ } ++ ++ // Consume blank characters. ++ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { ++ if is_blank(parser.buffer, parser.buffer_pos) { ++ // Consume a space or a tab character. ++ if !leading_blanks { ++ whitespaces = read(parser, whitespaces) ++ } else { ++ skip(parser) ++ } ++ } else { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ // Check if it is a first line break. ++ if !leading_blanks { ++ whitespaces = whitespaces[:0] ++ leading_break = read_line(parser, leading_break) ++ leading_blanks = true ++ } else { ++ trailing_breaks = read_line(parser, trailing_breaks) ++ } ++ } ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Join the whitespaces or fold line breaks. ++ if leading_blanks { ++ // Do we need to fold line breaks? ++ if len(leading_break) > 0 && leading_break[0] == '\n' { ++ if len(trailing_breaks) == 0 { ++ s = append(s, ' ') ++ } else { ++ s = append(s, trailing_breaks...) ++ } ++ } else { ++ s = append(s, leading_break...) ++ s = append(s, trailing_breaks...) ++ } ++ trailing_breaks = trailing_breaks[:0] ++ leading_break = leading_break[:0] ++ } else { ++ s = append(s, whitespaces...) ++ whitespaces = whitespaces[:0] ++ } ++ } ++ ++ // Eat the right quote. ++ skip(parser) ++ end_mark := parser.mark ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_SCALAR_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ style: yaml_SINGLE_QUOTED_SCALAR_STYLE, ++ } ++ if !single { ++ token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE ++ } ++ return true ++} ++ ++// Scan a plain scalar. ++func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { ++ ++ var s, leading_break, trailing_breaks, whitespaces []byte ++ var leading_blanks bool ++ var indent = parser.indent + 1 ++ ++ start_mark := parser.mark ++ end_mark := parser.mark ++ ++ // Consume the content of the plain scalar. ++ for { ++ // Check for a document indicator. ++ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { ++ return false ++ } ++ if parser.mark.column == 0 && ++ ((parser.buffer[parser.buffer_pos+0] == '-' && ++ parser.buffer[parser.buffer_pos+1] == '-' && ++ parser.buffer[parser.buffer_pos+2] == '-') || ++ (parser.buffer[parser.buffer_pos+0] == '.' && ++ parser.buffer[parser.buffer_pos+1] == '.' && ++ parser.buffer[parser.buffer_pos+2] == '.')) && ++ is_blankz(parser.buffer, parser.buffer_pos+3) { ++ break ++ } ++ ++ // Check for a comment. ++ if parser.buffer[parser.buffer_pos] == '#' { ++ break ++ } ++ ++ // Consume non-blank characters. ++ for !is_blankz(parser.buffer, parser.buffer_pos) { ++ ++ // Check for indicators that may end a plain scalar. ++ if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || ++ (parser.flow_level > 0 && ++ (parser.buffer[parser.buffer_pos] == ',' || ++ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || ++ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || ++ parser.buffer[parser.buffer_pos] == '}')) { ++ break ++ } ++ ++ // Check if we need to join whitespaces and breaks. ++ if leading_blanks || len(whitespaces) > 0 { ++ if leading_blanks { ++ // Do we need to fold line breaks? ++ if leading_break[0] == '\n' { ++ if len(trailing_breaks) == 0 { ++ s = append(s, ' ') ++ } else { ++ s = append(s, trailing_breaks...) ++ } ++ } else { ++ s = append(s, leading_break...) ++ s = append(s, trailing_breaks...) ++ } ++ trailing_breaks = trailing_breaks[:0] ++ leading_break = leading_break[:0] ++ leading_blanks = false ++ } else { ++ s = append(s, whitespaces...) ++ whitespaces = whitespaces[:0] ++ } ++ } ++ ++ // Copy the character. ++ s = read(parser, s) ++ ++ end_mark = parser.mark ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ } ++ ++ // Is it the end? ++ if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { ++ break ++ } ++ ++ // Consume blank characters. ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ ++ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { ++ if is_blank(parser.buffer, parser.buffer_pos) { ++ ++ // Check for tab characters that abuse indentation. ++ if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { ++ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", ++ start_mark, "found a tab character that violates indentation") ++ return false ++ } ++ ++ // Consume a space or a tab character. ++ if !leading_blanks { ++ whitespaces = read(parser, whitespaces) ++ } else { ++ skip(parser) ++ } ++ } else { ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ ++ // Check if it is a first line break. ++ if !leading_blanks { ++ whitespaces = whitespaces[:0] ++ leading_break = read_line(parser, leading_break) ++ leading_blanks = true ++ } else { ++ trailing_breaks = read_line(parser, trailing_breaks) ++ } ++ } ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ } ++ ++ // Check indentation level. ++ if parser.flow_level == 0 && parser.mark.column < indent { ++ break ++ } ++ } ++ ++ // Create a token. ++ *token = yaml_token_t{ ++ typ: yaml_SCALAR_TOKEN, ++ start_mark: start_mark, ++ end_mark: end_mark, ++ value: s, ++ style: yaml_PLAIN_SCALAR_STYLE, ++ } ++ ++ // Note that we change the 'simple_key_allowed' flag. ++ if leading_blanks { ++ parser.simple_key_allowed = true ++ } ++ return true ++} ++ ++func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { ++ if parser.newlines > 0 { ++ return true ++ } ++ ++ var start_mark yaml_mark_t ++ var text []byte ++ ++ for peek := 0; peek < 512; peek++ { ++ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { ++ break ++ } ++ if is_blank(parser.buffer, parser.buffer_pos+peek) { ++ continue ++ } ++ if parser.buffer[parser.buffer_pos+peek] == '#' { ++ seen := parser.mark.index+peek ++ for { ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if is_breakz(parser.buffer, parser.buffer_pos) { ++ if parser.mark.index >= seen { ++ break ++ } ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } else if parser.mark.index >= seen { ++ if len(text) == 0 { ++ start_mark = parser.mark ++ } ++ text = read(parser, text) ++ } else { ++ skip(parser) ++ } ++ } ++ } ++ break ++ } ++ if len(text) > 0 { ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ token_mark: token_mark, ++ start_mark: start_mark, ++ line: text, ++ }) ++ } ++ return true ++} ++ ++func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool { ++ token := parser.tokens[len(parser.tokens)-1] ++ ++ if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 { ++ token = parser.tokens[len(parser.tokens)-2] ++ } ++ ++ var token_mark = token.start_mark ++ var start_mark yaml_mark_t ++ var next_indent = parser.indent ++ if next_indent < 0 { ++ next_indent = 0 ++ } ++ ++ var recent_empty = false ++ var first_empty = parser.newlines <= 1 ++ ++ var line = parser.mark.line ++ var column = parser.mark.column ++ ++ var text []byte ++ ++ // The foot line is the place where a comment must start to ++ // still be considered as a foot of the prior content. ++ // If there's some content in the currently parsed line, then ++ // the foot is the line below it. ++ var foot_line = -1 ++ if scan_mark.line > 0 { ++ foot_line = parser.mark.line-parser.newlines+1 ++ if parser.newlines == 0 && parser.mark.column > 1 { ++ foot_line++ ++ } ++ } ++ ++ var peek = 0 ++ for ; peek < 512; peek++ { ++ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { ++ break ++ } ++ column++ ++ if is_blank(parser.buffer, parser.buffer_pos+peek) { ++ continue ++ } ++ c := parser.buffer[parser.buffer_pos+peek] ++ var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') ++ if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { ++ // Got line break or terminator. ++ if close_flow || !recent_empty { ++ if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { ++ // This is the first empty line and there were no empty lines before, ++ // so this initial part of the comment is a foot of the prior token ++ // instead of being a head for the following one. Split it up. ++ // Alternatively, this might also be the last comment inside a flow ++ // scope, so it must be a footer. ++ if len(text) > 0 { ++ if start_mark.column-1 < next_indent { ++ // If dedented it's unrelated to the prior token. ++ token_mark = start_mark ++ } ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ scan_mark: scan_mark, ++ token_mark: token_mark, ++ start_mark: start_mark, ++ end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, ++ foot: text, ++ }) ++ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} ++ token_mark = scan_mark ++ text = nil ++ } ++ } else { ++ if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 { ++ text = append(text, '\n') ++ } ++ } ++ } ++ if !is_break(parser.buffer, parser.buffer_pos+peek) { ++ break ++ } ++ first_empty = false ++ recent_empty = true ++ column = 0 ++ line++ ++ continue ++ } ++ ++ if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { ++ // The comment at the different indentation is a foot of the ++ // preceding data rather than a head of the upcoming one. ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ scan_mark: scan_mark, ++ token_mark: token_mark, ++ start_mark: start_mark, ++ end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, ++ foot: text, ++ }) ++ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} ++ token_mark = scan_mark ++ text = nil ++ } ++ ++ if parser.buffer[parser.buffer_pos+peek] != '#' { ++ break ++ } ++ ++ if len(text) == 0 { ++ start_mark = yaml_mark_t{parser.mark.index + peek, line, column} ++ } else { ++ text = append(text, '\n') ++ } ++ ++ recent_empty = false ++ ++ // Consume until after the consumed comment line. ++ seen := parser.mark.index+peek ++ for { ++ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { ++ return false ++ } ++ if is_breakz(parser.buffer, parser.buffer_pos) { ++ if parser.mark.index >= seen { ++ break ++ } ++ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { ++ return false ++ } ++ skip_line(parser) ++ } else if parser.mark.index >= seen { ++ text = read(parser, text) ++ } else { ++ skip(parser) ++ } ++ } ++ ++ peek = 0 ++ column = 0 ++ line = parser.mark.line ++ next_indent = parser.indent ++ if next_indent < 0 { ++ next_indent = 0 ++ } ++ } ++ ++ if len(text) > 0 { ++ parser.comments = append(parser.comments, yaml_comment_t{ ++ scan_mark: scan_mark, ++ token_mark: start_mark, ++ start_mark: start_mark, ++ end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column}, ++ head: text, ++ }) ++ } ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/sorter.go b/vendor/gopkg.in/yaml.v3/sorter.go +new file mode 100644 +index 000000000000..9210ece7e972 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/sorter.go +@@ -0,0 +1,134 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package yaml ++ ++import ( ++ "reflect" ++ "unicode" ++) ++ ++type keyList []reflect.Value ++ ++func (l keyList) Len() int { return len(l) } ++func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } ++func (l keyList) Less(i, j int) bool { ++ a := l[i] ++ b := l[j] ++ ak := a.Kind() ++ bk := b.Kind() ++ for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { ++ a = a.Elem() ++ ak = a.Kind() ++ } ++ for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { ++ b = b.Elem() ++ bk = b.Kind() ++ } ++ af, aok := keyFloat(a) ++ bf, bok := keyFloat(b) ++ if aok && bok { ++ if af != bf { ++ return af < bf ++ } ++ if ak != bk { ++ return ak < bk ++ } ++ return numLess(a, b) ++ } ++ if ak != reflect.String || bk != reflect.String { ++ return ak < bk ++ } ++ ar, br := []rune(a.String()), []rune(b.String()) ++ digits := false ++ for i := 0; i < len(ar) && i < len(br); i++ { ++ if ar[i] == br[i] { ++ digits = unicode.IsDigit(ar[i]) ++ continue ++ } ++ al := unicode.IsLetter(ar[i]) ++ bl := unicode.IsLetter(br[i]) ++ if al && bl { ++ return ar[i] < br[i] ++ } ++ if al || bl { ++ if digits { ++ return al ++ } else { ++ return bl ++ } ++ } ++ var ai, bi int ++ var an, bn int64 ++ if ar[i] == '0' || br[i] == '0' { ++ for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { ++ if ar[j] != '0' { ++ an = 1 ++ bn = 1 ++ break ++ } ++ } ++ } ++ for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { ++ an = an*10 + int64(ar[ai]-'0') ++ } ++ for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { ++ bn = bn*10 + int64(br[bi]-'0') ++ } ++ if an != bn { ++ return an < bn ++ } ++ if ai != bi { ++ return ai < bi ++ } ++ return ar[i] < br[i] ++ } ++ return len(ar) < len(br) ++} ++ ++// keyFloat returns a float value for v if it is a number/bool ++// and whether it is a number/bool or not. ++func keyFloat(v reflect.Value) (f float64, ok bool) { ++ switch v.Kind() { ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ return float64(v.Int()), true ++ case reflect.Float32, reflect.Float64: ++ return v.Float(), true ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ return float64(v.Uint()), true ++ case reflect.Bool: ++ if v.Bool() { ++ return 1, true ++ } ++ return 0, true ++ } ++ return 0, false ++} ++ ++// numLess returns whether a < b. ++// a and b must necessarily have the same kind. ++func numLess(a, b reflect.Value) bool { ++ switch a.Kind() { ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ return a.Int() < b.Int() ++ case reflect.Float32, reflect.Float64: ++ return a.Float() < b.Float() ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ return a.Uint() < b.Uint() ++ case reflect.Bool: ++ return !a.Bool() && b.Bool() ++ } ++ panic("not a number") ++} +diff --git a/vendor/gopkg.in/yaml.v3/writerc.go b/vendor/gopkg.in/yaml.v3/writerc.go +new file mode 100644 +index 000000000000..b8a116bf9a22 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/writerc.go +@@ -0,0 +1,48 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++// Set the writer error and return false. ++func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { ++ emitter.error = yaml_WRITER_ERROR ++ emitter.problem = problem ++ return false ++} ++ ++// Flush the output buffer. ++func yaml_emitter_flush(emitter *yaml_emitter_t) bool { ++ if emitter.write_handler == nil { ++ panic("write handler not set") ++ } ++ ++ // Check if the buffer is empty. ++ if emitter.buffer_pos == 0 { ++ return true ++ } ++ ++ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { ++ return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) ++ } ++ emitter.buffer_pos = 0 ++ return true ++} +diff --git a/vendor/gopkg.in/yaml.v3/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go +new file mode 100644 +index 000000000000..8cec6da48d3e +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/yaml.go +@@ -0,0 +1,698 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++// Package yaml implements YAML support for the Go language. ++// ++// Source code and other details for the project are available at GitHub: ++// ++// https://github.com/go-yaml/yaml ++// ++package yaml ++ ++import ( ++ "errors" ++ "fmt" ++ "io" ++ "reflect" ++ "strings" ++ "sync" ++ "unicode/utf8" ++) ++ ++// The Unmarshaler interface may be implemented by types to customize their ++// behavior when being unmarshaled from a YAML document. ++type Unmarshaler interface { ++ UnmarshalYAML(value *Node) error ++} ++ ++type obsoleteUnmarshaler interface { ++ UnmarshalYAML(unmarshal func(interface{}) error) error ++} ++ ++// The Marshaler interface may be implemented by types to customize their ++// behavior when being marshaled into a YAML document. The returned value ++// is marshaled in place of the original value implementing Marshaler. ++// ++// If an error is returned by MarshalYAML, the marshaling procedure stops ++// and returns with the provided error. ++type Marshaler interface { ++ MarshalYAML() (interface{}, error) ++} ++ ++// Unmarshal decodes the first document found within the in byte slice ++// and assigns decoded values into the out value. ++// ++// Maps and pointers (to a struct, string, int, etc) are accepted as out ++// values. If an internal pointer within a struct is not initialized, ++// the yaml package will initialize it if necessary for unmarshalling ++// the provided data. The out parameter must not be nil. ++// ++// The type of the decoded values should be compatible with the respective ++// values in out. If one or more values cannot be decoded due to a type ++// mismatches, decoding continues partially until the end of the YAML ++// content, and a *yaml.TypeError is returned with details for all ++// missed values. ++// ++// Struct fields are only unmarshalled if they are exported (have an ++// upper case first letter), and are unmarshalled using the field name ++// lowercased as the default key. Custom keys may be defined via the ++// "yaml" name in the field tag: the content preceding the first comma ++// is used as the key, and the following comma-separated options are ++// used to tweak the marshalling process (see Marshal). ++// Conflicting names result in a runtime error. ++// ++// For example: ++// ++// type T struct { ++// F int `yaml:"a,omitempty"` ++// B int ++// } ++// var t T ++// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) ++// ++// See the documentation of Marshal for the format of tags and a list of ++// supported tag options. ++// ++func Unmarshal(in []byte, out interface{}) (err error) { ++ return unmarshal(in, out, false) ++} ++ ++// A Decoder reads and decodes YAML values from an input stream. ++type Decoder struct { ++ parser *parser ++ knownFields bool ++} ++ ++// NewDecoder returns a new decoder that reads from r. ++// ++// The decoder introduces its own buffering and may read ++// data from r beyond the YAML values requested. ++func NewDecoder(r io.Reader) *Decoder { ++ return &Decoder{ ++ parser: newParserFromReader(r), ++ } ++} ++ ++// KnownFields ensures that the keys in decoded mappings to ++// exist as fields in the struct being decoded into. ++func (dec *Decoder) KnownFields(enable bool) { ++ dec.knownFields = enable ++} ++ ++// Decode reads the next YAML-encoded value from its input ++// and stores it in the value pointed to by v. ++// ++// See the documentation for Unmarshal for details about the ++// conversion of YAML into a Go value. ++func (dec *Decoder) Decode(v interface{}) (err error) { ++ d := newDecoder() ++ d.knownFields = dec.knownFields ++ defer handleErr(&err) ++ node := dec.parser.parse() ++ if node == nil { ++ return io.EOF ++ } ++ out := reflect.ValueOf(v) ++ if out.Kind() == reflect.Ptr && !out.IsNil() { ++ out = out.Elem() ++ } ++ d.unmarshal(node, out) ++ if len(d.terrors) > 0 { ++ return &TypeError{d.terrors} ++ } ++ return nil ++} ++ ++// Decode decodes the node and stores its data into the value pointed to by v. ++// ++// See the documentation for Unmarshal for details about the ++// conversion of YAML into a Go value. ++func (n *Node) Decode(v interface{}) (err error) { ++ d := newDecoder() ++ defer handleErr(&err) ++ out := reflect.ValueOf(v) ++ if out.Kind() == reflect.Ptr && !out.IsNil() { ++ out = out.Elem() ++ } ++ d.unmarshal(n, out) ++ if len(d.terrors) > 0 { ++ return &TypeError{d.terrors} ++ } ++ return nil ++} ++ ++func unmarshal(in []byte, out interface{}, strict bool) (err error) { ++ defer handleErr(&err) ++ d := newDecoder() ++ p := newParser(in) ++ defer p.destroy() ++ node := p.parse() ++ if node != nil { ++ v := reflect.ValueOf(out) ++ if v.Kind() == reflect.Ptr && !v.IsNil() { ++ v = v.Elem() ++ } ++ d.unmarshal(node, v) ++ } ++ if len(d.terrors) > 0 { ++ return &TypeError{d.terrors} ++ } ++ return nil ++} ++ ++// Marshal serializes the value provided into a YAML document. The structure ++// of the generated document will reflect the structure of the value itself. ++// Maps and pointers (to struct, string, int, etc) are accepted as the in value. ++// ++// Struct fields are only marshalled if they are exported (have an upper case ++// first letter), and are marshalled using the field name lowercased as the ++// default key. Custom keys may be defined via the "yaml" name in the field ++// tag: the content preceding the first comma is used as the key, and the ++// following comma-separated options are used to tweak the marshalling process. ++// Conflicting names result in a runtime error. ++// ++// The field tag format accepted is: ++// ++// `(...) yaml:"[][,[,]]" (...)` ++// ++// The following flags are currently supported: ++// ++// omitempty Only include the field if it's not set to the zero ++// value for the type or to empty slices or maps. ++// Zero valued structs will be omitted if all their public ++// fields are zero, unless they implement an IsZero ++// method (see the IsZeroer interface type), in which ++// case the field will be excluded if IsZero returns true. ++// ++// flow Marshal using a flow style (useful for structs, ++// sequences and maps). ++// ++// inline Inline the field, which must be a struct or a map, ++// causing all of its fields or keys to be processed as if ++// they were part of the outer struct. For maps, keys must ++// not conflict with the yaml keys of other struct fields. ++// ++// In addition, if the key is "-", the field is ignored. ++// ++// For example: ++// ++// type T struct { ++// F int `yaml:"a,omitempty"` ++// B int ++// } ++// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" ++// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" ++// ++func Marshal(in interface{}) (out []byte, err error) { ++ defer handleErr(&err) ++ e := newEncoder() ++ defer e.destroy() ++ e.marshalDoc("", reflect.ValueOf(in)) ++ e.finish() ++ out = e.out ++ return ++} ++ ++// An Encoder writes YAML values to an output stream. ++type Encoder struct { ++ encoder *encoder ++} ++ ++// NewEncoder returns a new encoder that writes to w. ++// The Encoder should be closed after use to flush all data ++// to w. ++func NewEncoder(w io.Writer) *Encoder { ++ return &Encoder{ ++ encoder: newEncoderWithWriter(w), ++ } ++} ++ ++// Encode writes the YAML encoding of v to the stream. ++// If multiple items are encoded to the stream, the ++// second and subsequent document will be preceded ++// with a "---" document separator, but the first will not. ++// ++// See the documentation for Marshal for details about the conversion of Go ++// values to YAML. ++func (e *Encoder) Encode(v interface{}) (err error) { ++ defer handleErr(&err) ++ e.encoder.marshalDoc("", reflect.ValueOf(v)) ++ return nil ++} ++ ++// Encode encodes value v and stores its representation in n. ++// ++// See the documentation for Marshal for details about the ++// conversion of Go values into YAML. ++func (n *Node) Encode(v interface{}) (err error) { ++ defer handleErr(&err) ++ e := newEncoder() ++ defer e.destroy() ++ e.marshalDoc("", reflect.ValueOf(v)) ++ e.finish() ++ p := newParser(e.out) ++ p.textless = true ++ defer p.destroy() ++ doc := p.parse() ++ *n = *doc.Content[0] ++ return nil ++} ++ ++// SetIndent changes the used indentation used when encoding. ++func (e *Encoder) SetIndent(spaces int) { ++ if spaces < 0 { ++ panic("yaml: cannot indent to a negative number of spaces") ++ } ++ e.encoder.indent = spaces ++} ++ ++// Close closes the encoder by writing any remaining data. ++// It does not write a stream terminating string "...". ++func (e *Encoder) Close() (err error) { ++ defer handleErr(&err) ++ e.encoder.finish() ++ return nil ++} ++ ++func handleErr(err *error) { ++ if v := recover(); v != nil { ++ if e, ok := v.(yamlError); ok { ++ *err = e.err ++ } else { ++ panic(v) ++ } ++ } ++} ++ ++type yamlError struct { ++ err error ++} ++ ++func fail(err error) { ++ panic(yamlError{err}) ++} ++ ++func failf(format string, args ...interface{}) { ++ panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) ++} ++ ++// A TypeError is returned by Unmarshal when one or more fields in ++// the YAML document cannot be properly decoded into the requested ++// types. When this error is returned, the value is still ++// unmarshaled partially. ++type TypeError struct { ++ Errors []string ++} ++ ++func (e *TypeError) Error() string { ++ return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) ++} ++ ++type Kind uint32 ++ ++const ( ++ DocumentNode Kind = 1 << iota ++ SequenceNode ++ MappingNode ++ ScalarNode ++ AliasNode ++) ++ ++type Style uint32 ++ ++const ( ++ TaggedStyle Style = 1 << iota ++ DoubleQuotedStyle ++ SingleQuotedStyle ++ LiteralStyle ++ FoldedStyle ++ FlowStyle ++) ++ ++// Node represents an element in the YAML document hierarchy. While documents ++// are typically encoded and decoded into higher level types, such as structs ++// and maps, Node is an intermediate representation that allows detailed ++// control over the content being decoded or encoded. ++// ++// It's worth noting that although Node offers access into details such as ++// line numbers, colums, and comments, the content when re-encoded will not ++// have its original textual representation preserved. An effort is made to ++// render the data plesantly, and to preserve comments near the data they ++// describe, though. ++// ++// Values that make use of the Node type interact with the yaml package in the ++// same way any other type would do, by encoding and decoding yaml data ++// directly or indirectly into them. ++// ++// For example: ++// ++// var person struct { ++// Name string ++// Address yaml.Node ++// } ++// err := yaml.Unmarshal(data, &person) ++// ++// Or by itself: ++// ++// var person Node ++// err := yaml.Unmarshal(data, &person) ++// ++type Node struct { ++ // Kind defines whether the node is a document, a mapping, a sequence, ++ // a scalar value, or an alias to another node. The specific data type of ++ // scalar nodes may be obtained via the ShortTag and LongTag methods. ++ Kind Kind ++ ++ // Style allows customizing the apperance of the node in the tree. ++ Style Style ++ ++ // Tag holds the YAML tag defining the data type for the value. ++ // When decoding, this field will always be set to the resolved tag, ++ // even when it wasn't explicitly provided in the YAML content. ++ // When encoding, if this field is unset the value type will be ++ // implied from the node properties, and if it is set, it will only ++ // be serialized into the representation if TaggedStyle is used or ++ // the implicit tag diverges from the provided one. ++ Tag string ++ ++ // Value holds the unescaped and unquoted represenation of the value. ++ Value string ++ ++ // Anchor holds the anchor name for this node, which allows aliases to point to it. ++ Anchor string ++ ++ // Alias holds the node that this alias points to. Only valid when Kind is AliasNode. ++ Alias *Node ++ ++ // Content holds contained nodes for documents, mappings, and sequences. ++ Content []*Node ++ ++ // HeadComment holds any comments in the lines preceding the node and ++ // not separated by an empty line. ++ HeadComment string ++ ++ // LineComment holds any comments at the end of the line where the node is in. ++ LineComment string ++ ++ // FootComment holds any comments following the node and before empty lines. ++ FootComment string ++ ++ // Line and Column hold the node position in the decoded YAML text. ++ // These fields are not respected when encoding the node. ++ Line int ++ Column int ++} ++ ++// IsZero returns whether the node has all of its fields unset. ++func (n *Node) IsZero() bool { ++ return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && ++ n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 ++} ++ ++ ++// LongTag returns the long form of the tag that indicates the data type for ++// the node. If the Tag field isn't explicitly defined, one will be computed ++// based on the node properties. ++func (n *Node) LongTag() string { ++ return longTag(n.ShortTag()) ++} ++ ++// ShortTag returns the short form of the YAML tag that indicates data type for ++// the node. If the Tag field isn't explicitly defined, one will be computed ++// based on the node properties. ++func (n *Node) ShortTag() string { ++ if n.indicatedString() { ++ return strTag ++ } ++ if n.Tag == "" || n.Tag == "!" { ++ switch n.Kind { ++ case MappingNode: ++ return mapTag ++ case SequenceNode: ++ return seqTag ++ case AliasNode: ++ if n.Alias != nil { ++ return n.Alias.ShortTag() ++ } ++ case ScalarNode: ++ tag, _ := resolve("", n.Value) ++ return tag ++ case 0: ++ // Special case to make the zero value convenient. ++ if n.IsZero() { ++ return nullTag ++ } ++ } ++ return "" ++ } ++ return shortTag(n.Tag) ++} ++ ++func (n *Node) indicatedString() bool { ++ return n.Kind == ScalarNode && ++ (shortTag(n.Tag) == strTag || ++ (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0) ++} ++ ++// SetString is a convenience function that sets the node to a string value ++// and defines its style in a pleasant way depending on its content. ++func (n *Node) SetString(s string) { ++ n.Kind = ScalarNode ++ if utf8.ValidString(s) { ++ n.Value = s ++ n.Tag = strTag ++ } else { ++ n.Value = encodeBase64(s) ++ n.Tag = binaryTag ++ } ++ if strings.Contains(n.Value, "\n") { ++ n.Style = LiteralStyle ++ } ++} ++ ++// -------------------------------------------------------------------------- ++// Maintain a mapping of keys to structure field indexes ++ ++// The code in this section was copied from mgo/bson. ++ ++// structInfo holds details for the serialization of fields of ++// a given struct. ++type structInfo struct { ++ FieldsMap map[string]fieldInfo ++ FieldsList []fieldInfo ++ ++ // InlineMap is the number of the field in the struct that ++ // contains an ,inline map, or -1 if there's none. ++ InlineMap int ++ ++ // InlineUnmarshalers holds indexes to inlined fields that ++ // contain unmarshaler values. ++ InlineUnmarshalers [][]int ++} ++ ++type fieldInfo struct { ++ Key string ++ Num int ++ OmitEmpty bool ++ Flow bool ++ // Id holds the unique field identifier, so we can cheaply ++ // check for field duplicates without maintaining an extra map. ++ Id int ++ ++ // Inline holds the field index if the field is part of an inlined struct. ++ Inline []int ++} ++ ++var structMap = make(map[reflect.Type]*structInfo) ++var fieldMapMutex sync.RWMutex ++var unmarshalerType reflect.Type ++ ++func init() { ++ var v Unmarshaler ++ unmarshalerType = reflect.ValueOf(&v).Elem().Type() ++} ++ ++func getStructInfo(st reflect.Type) (*structInfo, error) { ++ fieldMapMutex.RLock() ++ sinfo, found := structMap[st] ++ fieldMapMutex.RUnlock() ++ if found { ++ return sinfo, nil ++ } ++ ++ n := st.NumField() ++ fieldsMap := make(map[string]fieldInfo) ++ fieldsList := make([]fieldInfo, 0, n) ++ inlineMap := -1 ++ inlineUnmarshalers := [][]int(nil) ++ for i := 0; i != n; i++ { ++ field := st.Field(i) ++ if field.PkgPath != "" && !field.Anonymous { ++ continue // Private field ++ } ++ ++ info := fieldInfo{Num: i} ++ ++ tag := field.Tag.Get("yaml") ++ if tag == "" && strings.Index(string(field.Tag), ":") < 0 { ++ tag = string(field.Tag) ++ } ++ if tag == "-" { ++ continue ++ } ++ ++ inline := false ++ fields := strings.Split(tag, ",") ++ if len(fields) > 1 { ++ for _, flag := range fields[1:] { ++ switch flag { ++ case "omitempty": ++ info.OmitEmpty = true ++ case "flow": ++ info.Flow = true ++ case "inline": ++ inline = true ++ default: ++ return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st)) ++ } ++ } ++ tag = fields[0] ++ } ++ ++ if inline { ++ switch field.Type.Kind() { ++ case reflect.Map: ++ if inlineMap >= 0 { ++ return nil, errors.New("multiple ,inline maps in struct " + st.String()) ++ } ++ if field.Type.Key() != reflect.TypeOf("") { ++ return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String()) ++ } ++ inlineMap = info.Num ++ case reflect.Struct, reflect.Ptr: ++ ftype := field.Type ++ for ftype.Kind() == reflect.Ptr { ++ ftype = ftype.Elem() ++ } ++ if ftype.Kind() != reflect.Struct { ++ return nil, errors.New("option ,inline may only be used on a struct or map field") ++ } ++ if reflect.PtrTo(ftype).Implements(unmarshalerType) { ++ inlineUnmarshalers = append(inlineUnmarshalers, []int{i}) ++ } else { ++ sinfo, err := getStructInfo(ftype) ++ if err != nil { ++ return nil, err ++ } ++ for _, index := range sinfo.InlineUnmarshalers { ++ inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...)) ++ } ++ for _, finfo := range sinfo.FieldsList { ++ if _, found := fieldsMap[finfo.Key]; found { ++ msg := "duplicated key '" + finfo.Key + "' in struct " + st.String() ++ return nil, errors.New(msg) ++ } ++ if finfo.Inline == nil { ++ finfo.Inline = []int{i, finfo.Num} ++ } else { ++ finfo.Inline = append([]int{i}, finfo.Inline...) ++ } ++ finfo.Id = len(fieldsList) ++ fieldsMap[finfo.Key] = finfo ++ fieldsList = append(fieldsList, finfo) ++ } ++ } ++ default: ++ return nil, errors.New("option ,inline may only be used on a struct or map field") ++ } ++ continue ++ } ++ ++ if tag != "" { ++ info.Key = tag ++ } else { ++ info.Key = strings.ToLower(field.Name) ++ } ++ ++ if _, found = fieldsMap[info.Key]; found { ++ msg := "duplicated key '" + info.Key + "' in struct " + st.String() ++ return nil, errors.New(msg) ++ } ++ ++ info.Id = len(fieldsList) ++ fieldsList = append(fieldsList, info) ++ fieldsMap[info.Key] = info ++ } ++ ++ sinfo = &structInfo{ ++ FieldsMap: fieldsMap, ++ FieldsList: fieldsList, ++ InlineMap: inlineMap, ++ InlineUnmarshalers: inlineUnmarshalers, ++ } ++ ++ fieldMapMutex.Lock() ++ structMap[st] = sinfo ++ fieldMapMutex.Unlock() ++ return sinfo, nil ++} ++ ++// IsZeroer is used to check whether an object is zero to ++// determine whether it should be omitted when marshaling ++// with the omitempty flag. One notable implementation ++// is time.Time. ++type IsZeroer interface { ++ IsZero() bool ++} ++ ++func isZero(v reflect.Value) bool { ++ kind := v.Kind() ++ if z, ok := v.Interface().(IsZeroer); ok { ++ if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { ++ return true ++ } ++ return z.IsZero() ++ } ++ switch kind { ++ case reflect.String: ++ return len(v.String()) == 0 ++ case reflect.Interface, reflect.Ptr: ++ return v.IsNil() ++ case reflect.Slice: ++ return v.Len() == 0 ++ case reflect.Map: ++ return v.Len() == 0 ++ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ++ return v.Int() == 0 ++ case reflect.Float32, reflect.Float64: ++ return v.Float() == 0 ++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: ++ return v.Uint() == 0 ++ case reflect.Bool: ++ return !v.Bool() ++ case reflect.Struct: ++ vt := v.Type() ++ for i := v.NumField() - 1; i >= 0; i-- { ++ if vt.Field(i).PkgPath != "" { ++ continue // Private field ++ } ++ if !isZero(v.Field(i)) { ++ return false ++ } ++ } ++ return true ++ } ++ return false ++} +diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go +new file mode 100644 +index 000000000000..7c6d00770619 +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/yamlh.go +@@ -0,0 +1,807 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++import ( ++ "fmt" ++ "io" ++) ++ ++// The version directive data. ++type yaml_version_directive_t struct { ++ major int8 // The major version number. ++ minor int8 // The minor version number. ++} ++ ++// The tag directive data. ++type yaml_tag_directive_t struct { ++ handle []byte // The tag handle. ++ prefix []byte // The tag prefix. ++} ++ ++type yaml_encoding_t int ++ ++// The stream encoding. ++const ( ++ // Let the parser choose the encoding. ++ yaml_ANY_ENCODING yaml_encoding_t = iota ++ ++ yaml_UTF8_ENCODING // The default UTF-8 encoding. ++ yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. ++ yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. ++) ++ ++type yaml_break_t int ++ ++// Line break types. ++const ( ++ // Let the parser choose the break type. ++ yaml_ANY_BREAK yaml_break_t = iota ++ ++ yaml_CR_BREAK // Use CR for line breaks (Mac style). ++ yaml_LN_BREAK // Use LN for line breaks (Unix style). ++ yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). ++) ++ ++type yaml_error_type_t int ++ ++// Many bad things could happen with the parser and emitter. ++const ( ++ // No error is produced. ++ yaml_NO_ERROR yaml_error_type_t = iota ++ ++ yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. ++ yaml_READER_ERROR // Cannot read or decode the input stream. ++ yaml_SCANNER_ERROR // Cannot scan the input stream. ++ yaml_PARSER_ERROR // Cannot parse the input stream. ++ yaml_COMPOSER_ERROR // Cannot compose a YAML document. ++ yaml_WRITER_ERROR // Cannot write to the output stream. ++ yaml_EMITTER_ERROR // Cannot emit a YAML stream. ++) ++ ++// The pointer position. ++type yaml_mark_t struct { ++ index int // The position index. ++ line int // The position line. ++ column int // The position column. ++} ++ ++// Node Styles ++ ++type yaml_style_t int8 ++ ++type yaml_scalar_style_t yaml_style_t ++ ++// Scalar styles. ++const ( ++ // Let the emitter choose the style. ++ yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0 ++ ++ yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style. ++ yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. ++ yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. ++ yaml_LITERAL_SCALAR_STYLE // The literal scalar style. ++ yaml_FOLDED_SCALAR_STYLE // The folded scalar style. ++) ++ ++type yaml_sequence_style_t yaml_style_t ++ ++// Sequence styles. ++const ( ++ // Let the emitter choose the style. ++ yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota ++ ++ yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. ++ yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. ++) ++ ++type yaml_mapping_style_t yaml_style_t ++ ++// Mapping styles. ++const ( ++ // Let the emitter choose the style. ++ yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota ++ ++ yaml_BLOCK_MAPPING_STYLE // The block mapping style. ++ yaml_FLOW_MAPPING_STYLE // The flow mapping style. ++) ++ ++// Tokens ++ ++type yaml_token_type_t int ++ ++// Token types. ++const ( ++ // An empty token. ++ yaml_NO_TOKEN yaml_token_type_t = iota ++ ++ yaml_STREAM_START_TOKEN // A STREAM-START token. ++ yaml_STREAM_END_TOKEN // A STREAM-END token. ++ ++ yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. ++ yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. ++ yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. ++ yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. ++ ++ yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. ++ yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. ++ yaml_BLOCK_END_TOKEN // A BLOCK-END token. ++ ++ yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. ++ yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. ++ yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. ++ yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. ++ ++ yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. ++ yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. ++ yaml_KEY_TOKEN // A KEY token. ++ yaml_VALUE_TOKEN // A VALUE token. ++ ++ yaml_ALIAS_TOKEN // An ALIAS token. ++ yaml_ANCHOR_TOKEN // An ANCHOR token. ++ yaml_TAG_TOKEN // A TAG token. ++ yaml_SCALAR_TOKEN // A SCALAR token. ++) ++ ++func (tt yaml_token_type_t) String() string { ++ switch tt { ++ case yaml_NO_TOKEN: ++ return "yaml_NO_TOKEN" ++ case yaml_STREAM_START_TOKEN: ++ return "yaml_STREAM_START_TOKEN" ++ case yaml_STREAM_END_TOKEN: ++ return "yaml_STREAM_END_TOKEN" ++ case yaml_VERSION_DIRECTIVE_TOKEN: ++ return "yaml_VERSION_DIRECTIVE_TOKEN" ++ case yaml_TAG_DIRECTIVE_TOKEN: ++ return "yaml_TAG_DIRECTIVE_TOKEN" ++ case yaml_DOCUMENT_START_TOKEN: ++ return "yaml_DOCUMENT_START_TOKEN" ++ case yaml_DOCUMENT_END_TOKEN: ++ return "yaml_DOCUMENT_END_TOKEN" ++ case yaml_BLOCK_SEQUENCE_START_TOKEN: ++ return "yaml_BLOCK_SEQUENCE_START_TOKEN" ++ case yaml_BLOCK_MAPPING_START_TOKEN: ++ return "yaml_BLOCK_MAPPING_START_TOKEN" ++ case yaml_BLOCK_END_TOKEN: ++ return "yaml_BLOCK_END_TOKEN" ++ case yaml_FLOW_SEQUENCE_START_TOKEN: ++ return "yaml_FLOW_SEQUENCE_START_TOKEN" ++ case yaml_FLOW_SEQUENCE_END_TOKEN: ++ return "yaml_FLOW_SEQUENCE_END_TOKEN" ++ case yaml_FLOW_MAPPING_START_TOKEN: ++ return "yaml_FLOW_MAPPING_START_TOKEN" ++ case yaml_FLOW_MAPPING_END_TOKEN: ++ return "yaml_FLOW_MAPPING_END_TOKEN" ++ case yaml_BLOCK_ENTRY_TOKEN: ++ return "yaml_BLOCK_ENTRY_TOKEN" ++ case yaml_FLOW_ENTRY_TOKEN: ++ return "yaml_FLOW_ENTRY_TOKEN" ++ case yaml_KEY_TOKEN: ++ return "yaml_KEY_TOKEN" ++ case yaml_VALUE_TOKEN: ++ return "yaml_VALUE_TOKEN" ++ case yaml_ALIAS_TOKEN: ++ return "yaml_ALIAS_TOKEN" ++ case yaml_ANCHOR_TOKEN: ++ return "yaml_ANCHOR_TOKEN" ++ case yaml_TAG_TOKEN: ++ return "yaml_TAG_TOKEN" ++ case yaml_SCALAR_TOKEN: ++ return "yaml_SCALAR_TOKEN" ++ } ++ return "" ++} ++ ++// The token structure. ++type yaml_token_t struct { ++ // The token type. ++ typ yaml_token_type_t ++ ++ // The start/end of the token. ++ start_mark, end_mark yaml_mark_t ++ ++ // The stream encoding (for yaml_STREAM_START_TOKEN). ++ encoding yaml_encoding_t ++ ++ // The alias/anchor/scalar value or tag/tag directive handle ++ // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). ++ value []byte ++ ++ // The tag suffix (for yaml_TAG_TOKEN). ++ suffix []byte ++ ++ // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). ++ prefix []byte ++ ++ // The scalar style (for yaml_SCALAR_TOKEN). ++ style yaml_scalar_style_t ++ ++ // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). ++ major, minor int8 ++} ++ ++// Events ++ ++type yaml_event_type_t int8 ++ ++// Event types. ++const ( ++ // An empty event. ++ yaml_NO_EVENT yaml_event_type_t = iota ++ ++ yaml_STREAM_START_EVENT // A STREAM-START event. ++ yaml_STREAM_END_EVENT // A STREAM-END event. ++ yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. ++ yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. ++ yaml_ALIAS_EVENT // An ALIAS event. ++ yaml_SCALAR_EVENT // A SCALAR event. ++ yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. ++ yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. ++ yaml_MAPPING_START_EVENT // A MAPPING-START event. ++ yaml_MAPPING_END_EVENT // A MAPPING-END event. ++ yaml_TAIL_COMMENT_EVENT ++) ++ ++var eventStrings = []string{ ++ yaml_NO_EVENT: "none", ++ yaml_STREAM_START_EVENT: "stream start", ++ yaml_STREAM_END_EVENT: "stream end", ++ yaml_DOCUMENT_START_EVENT: "document start", ++ yaml_DOCUMENT_END_EVENT: "document end", ++ yaml_ALIAS_EVENT: "alias", ++ yaml_SCALAR_EVENT: "scalar", ++ yaml_SEQUENCE_START_EVENT: "sequence start", ++ yaml_SEQUENCE_END_EVENT: "sequence end", ++ yaml_MAPPING_START_EVENT: "mapping start", ++ yaml_MAPPING_END_EVENT: "mapping end", ++ yaml_TAIL_COMMENT_EVENT: "tail comment", ++} ++ ++func (e yaml_event_type_t) String() string { ++ if e < 0 || int(e) >= len(eventStrings) { ++ return fmt.Sprintf("unknown event %d", e) ++ } ++ return eventStrings[e] ++} ++ ++// The event structure. ++type yaml_event_t struct { ++ ++ // The event type. ++ typ yaml_event_type_t ++ ++ // The start and end of the event. ++ start_mark, end_mark yaml_mark_t ++ ++ // The document encoding (for yaml_STREAM_START_EVENT). ++ encoding yaml_encoding_t ++ ++ // The version directive (for yaml_DOCUMENT_START_EVENT). ++ version_directive *yaml_version_directive_t ++ ++ // The list of tag directives (for yaml_DOCUMENT_START_EVENT). ++ tag_directives []yaml_tag_directive_t ++ ++ // The comments ++ head_comment []byte ++ line_comment []byte ++ foot_comment []byte ++ tail_comment []byte ++ ++ // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). ++ anchor []byte ++ ++ // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). ++ tag []byte ++ ++ // The scalar value (for yaml_SCALAR_EVENT). ++ value []byte ++ ++ // Is the document start/end indicator implicit, or the tag optional? ++ // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). ++ implicit bool ++ ++ // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). ++ quoted_implicit bool ++ ++ // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). ++ style yaml_style_t ++} ++ ++func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } ++func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } ++func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } ++ ++// Nodes ++ ++const ( ++ yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. ++ yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. ++ yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. ++ yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. ++ yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. ++ yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. ++ ++ yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. ++ yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. ++ ++ // Not in original libyaml. ++ yaml_BINARY_TAG = "tag:yaml.org,2002:binary" ++ yaml_MERGE_TAG = "tag:yaml.org,2002:merge" ++ ++ yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. ++ yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. ++ yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. ++) ++ ++type yaml_node_type_t int ++ ++// Node types. ++const ( ++ // An empty node. ++ yaml_NO_NODE yaml_node_type_t = iota ++ ++ yaml_SCALAR_NODE // A scalar node. ++ yaml_SEQUENCE_NODE // A sequence node. ++ yaml_MAPPING_NODE // A mapping node. ++) ++ ++// An element of a sequence node. ++type yaml_node_item_t int ++ ++// An element of a mapping node. ++type yaml_node_pair_t struct { ++ key int // The key of the element. ++ value int // The value of the element. ++} ++ ++// The node structure. ++type yaml_node_t struct { ++ typ yaml_node_type_t // The node type. ++ tag []byte // The node tag. ++ ++ // The node data. ++ ++ // The scalar parameters (for yaml_SCALAR_NODE). ++ scalar struct { ++ value []byte // The scalar value. ++ length int // The length of the scalar value. ++ style yaml_scalar_style_t // The scalar style. ++ } ++ ++ // The sequence parameters (for YAML_SEQUENCE_NODE). ++ sequence struct { ++ items_data []yaml_node_item_t // The stack of sequence items. ++ style yaml_sequence_style_t // The sequence style. ++ } ++ ++ // The mapping parameters (for yaml_MAPPING_NODE). ++ mapping struct { ++ pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). ++ pairs_start *yaml_node_pair_t // The beginning of the stack. ++ pairs_end *yaml_node_pair_t // The end of the stack. ++ pairs_top *yaml_node_pair_t // The top of the stack. ++ style yaml_mapping_style_t // The mapping style. ++ } ++ ++ start_mark yaml_mark_t // The beginning of the node. ++ end_mark yaml_mark_t // The end of the node. ++ ++} ++ ++// The document structure. ++type yaml_document_t struct { ++ ++ // The document nodes. ++ nodes []yaml_node_t ++ ++ // The version directive. ++ version_directive *yaml_version_directive_t ++ ++ // The list of tag directives. ++ tag_directives_data []yaml_tag_directive_t ++ tag_directives_start int // The beginning of the tag directives list. ++ tag_directives_end int // The end of the tag directives list. ++ ++ start_implicit int // Is the document start indicator implicit? ++ end_implicit int // Is the document end indicator implicit? ++ ++ // The start/end of the document. ++ start_mark, end_mark yaml_mark_t ++} ++ ++// The prototype of a read handler. ++// ++// The read handler is called when the parser needs to read more bytes from the ++// source. The handler should write not more than size bytes to the buffer. ++// The number of written bytes should be set to the size_read variable. ++// ++// [in,out] data A pointer to an application data specified by ++// yaml_parser_set_input(). ++// [out] buffer The buffer to write the data from the source. ++// [in] size The size of the buffer. ++// [out] size_read The actual number of bytes read from the source. ++// ++// On success, the handler should return 1. If the handler failed, ++// the returned value should be 0. On EOF, the handler should set the ++// size_read to 0 and return 1. ++type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) ++ ++// This structure holds information about a potential simple key. ++type yaml_simple_key_t struct { ++ possible bool // Is a simple key possible? ++ required bool // Is a simple key required? ++ token_number int // The number of the token. ++ mark yaml_mark_t // The position mark. ++} ++ ++// The states of the parser. ++type yaml_parser_state_t int ++ ++const ( ++ yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota ++ ++ yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. ++ yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. ++ yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. ++ yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. ++ yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. ++ yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. ++ yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. ++ yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. ++ yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. ++ yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. ++ yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. ++ yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. ++ yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. ++ yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. ++ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. ++ yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. ++ yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. ++ yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. ++ yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. ++ yaml_PARSE_END_STATE // Expect nothing. ++) ++ ++func (ps yaml_parser_state_t) String() string { ++ switch ps { ++ case yaml_PARSE_STREAM_START_STATE: ++ return "yaml_PARSE_STREAM_START_STATE" ++ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: ++ return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" ++ case yaml_PARSE_DOCUMENT_START_STATE: ++ return "yaml_PARSE_DOCUMENT_START_STATE" ++ case yaml_PARSE_DOCUMENT_CONTENT_STATE: ++ return "yaml_PARSE_DOCUMENT_CONTENT_STATE" ++ case yaml_PARSE_DOCUMENT_END_STATE: ++ return "yaml_PARSE_DOCUMENT_END_STATE" ++ case yaml_PARSE_BLOCK_NODE_STATE: ++ return "yaml_PARSE_BLOCK_NODE_STATE" ++ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: ++ return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" ++ case yaml_PARSE_FLOW_NODE_STATE: ++ return "yaml_PARSE_FLOW_NODE_STATE" ++ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: ++ return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" ++ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: ++ return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" ++ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: ++ return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" ++ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: ++ return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" ++ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: ++ return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" ++ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: ++ return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" ++ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: ++ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" ++ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" ++ case yaml_PARSE_FLOW_MAPPING_KEY_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" ++ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" ++ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: ++ return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" ++ case yaml_PARSE_END_STATE: ++ return "yaml_PARSE_END_STATE" ++ } ++ return "" ++} ++ ++// This structure holds aliases data. ++type yaml_alias_data_t struct { ++ anchor []byte // The anchor. ++ index int // The node id. ++ mark yaml_mark_t // The anchor mark. ++} ++ ++// The parser structure. ++// ++// All members are internal. Manage the structure using the ++// yaml_parser_ family of functions. ++type yaml_parser_t struct { ++ ++ // Error handling ++ ++ error yaml_error_type_t // Error type. ++ ++ problem string // Error description. ++ ++ // The byte about which the problem occurred. ++ problem_offset int ++ problem_value int ++ problem_mark yaml_mark_t ++ ++ // The error context. ++ context string ++ context_mark yaml_mark_t ++ ++ // Reader stuff ++ ++ read_handler yaml_read_handler_t // Read handler. ++ ++ input_reader io.Reader // File input data. ++ input []byte // String input data. ++ input_pos int ++ ++ eof bool // EOF flag ++ ++ buffer []byte // The working buffer. ++ buffer_pos int // The current position of the buffer. ++ ++ unread int // The number of unread characters in the buffer. ++ ++ newlines int // The number of line breaks since last non-break/non-blank character ++ ++ raw_buffer []byte // The raw buffer. ++ raw_buffer_pos int // The current position of the buffer. ++ ++ encoding yaml_encoding_t // The input encoding. ++ ++ offset int // The offset of the current position (in bytes). ++ mark yaml_mark_t // The mark of the current position. ++ ++ // Comments ++ ++ head_comment []byte // The current head comments ++ line_comment []byte // The current line comments ++ foot_comment []byte // The current foot comments ++ tail_comment []byte // Foot comment that happens at the end of a block. ++ stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc) ++ ++ comments []yaml_comment_t // The folded comments for all parsed tokens ++ comments_head int ++ ++ // Scanner stuff ++ ++ stream_start_produced bool // Have we started to scan the input stream? ++ stream_end_produced bool // Have we reached the end of the input stream? ++ ++ flow_level int // The number of unclosed '[' and '{' indicators. ++ ++ tokens []yaml_token_t // The tokens queue. ++ tokens_head int // The head of the tokens queue. ++ tokens_parsed int // The number of tokens fetched from the queue. ++ token_available bool // Does the tokens queue contain a token ready for dequeueing. ++ ++ indent int // The current indentation level. ++ indents []int // The indentation levels stack. ++ ++ simple_key_allowed bool // May a simple key occur at the current position? ++ simple_keys []yaml_simple_key_t // The stack of simple keys. ++ simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number ++ ++ // Parser stuff ++ ++ state yaml_parser_state_t // The current parser state. ++ states []yaml_parser_state_t // The parser states stack. ++ marks []yaml_mark_t // The stack of marks. ++ tag_directives []yaml_tag_directive_t // The list of TAG directives. ++ ++ // Dumper stuff ++ ++ aliases []yaml_alias_data_t // The alias data. ++ ++ document *yaml_document_t // The currently parsed document. ++} ++ ++type yaml_comment_t struct { ++ ++ scan_mark yaml_mark_t // Position where scanning for comments started ++ token_mark yaml_mark_t // Position after which tokens will be associated with this comment ++ start_mark yaml_mark_t // Position of '#' comment mark ++ end_mark yaml_mark_t // Position where comment terminated ++ ++ head []byte ++ line []byte ++ foot []byte ++} ++ ++// Emitter Definitions ++ ++// The prototype of a write handler. ++// ++// The write handler is called when the emitter needs to flush the accumulated ++// characters to the output. The handler should write @a size bytes of the ++// @a buffer to the output. ++// ++// @param[in,out] data A pointer to an application data specified by ++// yaml_emitter_set_output(). ++// @param[in] buffer The buffer with bytes to be written. ++// @param[in] size The size of the buffer. ++// ++// @returns On success, the handler should return @c 1. If the handler failed, ++// the returned value should be @c 0. ++// ++type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error ++ ++type yaml_emitter_state_t int ++ ++// The emitter states. ++const ( ++ // Expect STREAM-START. ++ yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota ++ ++ yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. ++ yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. ++ yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. ++ yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. ++ yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. ++ yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out ++ yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. ++ yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. ++ yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out ++ yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. ++ yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. ++ yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. ++ yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. ++ yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. ++ yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. ++ yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. ++ yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. ++ yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. ++ yaml_EMIT_END_STATE // Expect nothing. ++) ++ ++// The emitter structure. ++// ++// All members are internal. Manage the structure using the @c yaml_emitter_ ++// family of functions. ++type yaml_emitter_t struct { ++ ++ // Error handling ++ ++ error yaml_error_type_t // Error type. ++ problem string // Error description. ++ ++ // Writer stuff ++ ++ write_handler yaml_write_handler_t // Write handler. ++ ++ output_buffer *[]byte // String output data. ++ output_writer io.Writer // File output data. ++ ++ buffer []byte // The working buffer. ++ buffer_pos int // The current position of the buffer. ++ ++ raw_buffer []byte // The raw buffer. ++ raw_buffer_pos int // The current position of the buffer. ++ ++ encoding yaml_encoding_t // The stream encoding. ++ ++ // Emitter stuff ++ ++ canonical bool // If the output is in the canonical style? ++ best_indent int // The number of indentation spaces. ++ best_width int // The preferred width of the output lines. ++ unicode bool // Allow unescaped non-ASCII characters? ++ line_break yaml_break_t // The preferred line break. ++ ++ state yaml_emitter_state_t // The current emitter state. ++ states []yaml_emitter_state_t // The stack of states. ++ ++ events []yaml_event_t // The event queue. ++ events_head int // The head of the event queue. ++ ++ indents []int // The stack of indentation levels. ++ ++ tag_directives []yaml_tag_directive_t // The list of tag directives. ++ ++ indent int // The current indentation level. ++ ++ flow_level int // The current flow level. ++ ++ root_context bool // Is it the document root context? ++ sequence_context bool // Is it a sequence context? ++ mapping_context bool // Is it a mapping context? ++ simple_key_context bool // Is it a simple mapping key context? ++ ++ line int // The current line. ++ column int // The current column. ++ whitespace bool // If the last character was a whitespace? ++ indention bool // If the last character was an indentation character (' ', '-', '?', ':')? ++ open_ended bool // If an explicit document end is required? ++ ++ space_above bool // Is there's an empty line above? ++ foot_indent int // The indent used to write the foot comment above, or -1 if none. ++ ++ // Anchor analysis. ++ anchor_data struct { ++ anchor []byte // The anchor value. ++ alias bool // Is it an alias? ++ } ++ ++ // Tag analysis. ++ tag_data struct { ++ handle []byte // The tag handle. ++ suffix []byte // The tag suffix. ++ } ++ ++ // Scalar analysis. ++ scalar_data struct { ++ value []byte // The scalar value. ++ multiline bool // Does the scalar contain line breaks? ++ flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? ++ block_plain_allowed bool // Can the scalar be expressed in the block plain style? ++ single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? ++ block_allowed bool // Can the scalar be expressed in the literal or folded styles? ++ style yaml_scalar_style_t // The output style. ++ } ++ ++ // Comments ++ head_comment []byte ++ line_comment []byte ++ foot_comment []byte ++ tail_comment []byte ++ ++ key_line_comment []byte ++ ++ // Dumper stuff ++ ++ opened bool // If the stream was already opened? ++ closed bool // If the stream was already closed? ++ ++ // The information associated with the document nodes. ++ anchors *struct { ++ references int // The number of references. ++ anchor int // The anchor id. ++ serialized bool // If the node has been emitted? ++ } ++ ++ last_anchor_id int // The last assigned anchor id. ++ ++ document *yaml_document_t // The currently emitted document. ++} +diff --git a/vendor/gopkg.in/yaml.v3/yamlprivateh.go b/vendor/gopkg.in/yaml.v3/yamlprivateh.go +new file mode 100644 +index 000000000000..e88f9c54aecb +--- /dev/null ++++ b/vendor/gopkg.in/yaml.v3/yamlprivateh.go +@@ -0,0 +1,198 @@ ++// ++// Copyright (c) 2011-2019 Canonical Ltd ++// Copyright (c) 2006-2010 Kirill Simonov ++// ++// Permission is hereby granted, free of charge, to any person obtaining a copy of ++// this software and associated documentation files (the "Software"), to deal in ++// the Software without restriction, including without limitation the rights to ++// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies ++// of the Software, and to permit persons to whom the Software is furnished to do ++// so, subject to the following conditions: ++// ++// The above copyright notice and this permission notice shall be included in all ++// copies or substantial portions of the Software. ++// ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++package yaml ++ ++const ( ++ // The size of the input raw buffer. ++ input_raw_buffer_size = 512 ++ ++ // The size of the input buffer. ++ // It should be possible to decode the whole raw buffer. ++ input_buffer_size = input_raw_buffer_size * 3 ++ ++ // The size of the output buffer. ++ output_buffer_size = 128 ++ ++ // The size of the output raw buffer. ++ // It should be possible to encode the whole output buffer. ++ output_raw_buffer_size = (output_buffer_size*2 + 2) ++ ++ // The size of other stacks and queues. ++ initial_stack_size = 16 ++ initial_queue_size = 16 ++ initial_string_size = 16 ++) ++ ++// Check if the character at the specified position is an alphabetical ++// character, a digit, '_', or '-'. ++func is_alpha(b []byte, i int) bool { ++ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' ++} ++ ++// Check if the character at the specified position is a digit. ++func is_digit(b []byte, i int) bool { ++ return b[i] >= '0' && b[i] <= '9' ++} ++ ++// Get the value of a digit. ++func as_digit(b []byte, i int) int { ++ return int(b[i]) - '0' ++} ++ ++// Check if the character at the specified position is a hex-digit. ++func is_hex(b []byte, i int) bool { ++ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' ++} ++ ++// Get the value of a hex-digit. ++func as_hex(b []byte, i int) int { ++ bi := b[i] ++ if bi >= 'A' && bi <= 'F' { ++ return int(bi) - 'A' + 10 ++ } ++ if bi >= 'a' && bi <= 'f' { ++ return int(bi) - 'a' + 10 ++ } ++ return int(bi) - '0' ++} ++ ++// Check if the character is ASCII. ++func is_ascii(b []byte, i int) bool { ++ return b[i] <= 0x7F ++} ++ ++// Check if the character at the start of the buffer can be printed unescaped. ++func is_printable(b []byte, i int) bool { ++ return ((b[i] == 0x0A) || // . == #x0A ++ (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E ++ (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF ++ (b[i] > 0xC2 && b[i] < 0xED) || ++ (b[i] == 0xED && b[i+1] < 0xA0) || ++ (b[i] == 0xEE) || ++ (b[i] == 0xEF && // #xE000 <= . <= #xFFFD ++ !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF ++ !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) ++} ++ ++// Check if the character at the specified position is NUL. ++func is_z(b []byte, i int) bool { ++ return b[i] == 0x00 ++} ++ ++// Check if the beginning of the buffer is a BOM. ++func is_bom(b []byte, i int) bool { ++ return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF ++} ++ ++// Check if the character at the specified position is space. ++func is_space(b []byte, i int) bool { ++ return b[i] == ' ' ++} ++ ++// Check if the character at the specified position is tab. ++func is_tab(b []byte, i int) bool { ++ return b[i] == '\t' ++} ++ ++// Check if the character at the specified position is blank (space or tab). ++func is_blank(b []byte, i int) bool { ++ //return is_space(b, i) || is_tab(b, i) ++ return b[i] == ' ' || b[i] == '\t' ++} ++ ++// Check if the character at the specified position is a line break. ++func is_break(b []byte, i int) bool { ++ return (b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) ++} ++ ++func is_crlf(b []byte, i int) bool { ++ return b[i] == '\r' && b[i+1] == '\n' ++} ++ ++// Check if the character is a line break or NUL. ++func is_breakz(b []byte, i int) bool { ++ //return is_break(b, i) || is_z(b, i) ++ return ( ++ // is_break: ++ b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) ++ // is_z: ++ b[i] == 0) ++} ++ ++// Check if the character is a line break, space, or NUL. ++func is_spacez(b []byte, i int) bool { ++ //return is_space(b, i) || is_breakz(b, i) ++ return ( ++ // is_space: ++ b[i] == ' ' || ++ // is_breakz: ++ b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) ++ b[i] == 0) ++} ++ ++// Check if the character is a line break, space, tab, or NUL. ++func is_blankz(b []byte, i int) bool { ++ //return is_blank(b, i) || is_breakz(b, i) ++ return ( ++ // is_blank: ++ b[i] == ' ' || b[i] == '\t' || ++ // is_breakz: ++ b[i] == '\r' || // CR (#xD) ++ b[i] == '\n' || // LF (#xA) ++ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) ++ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) ++ b[i] == 0) ++} ++ ++// Determine the width of the character. ++func width(b byte) int { ++ // Don't replace these by a switch without first ++ // confirming that it is being inlined. ++ if b&0x80 == 0x00 { ++ return 1 ++ } ++ if b&0xE0 == 0xC0 { ++ return 2 ++ } ++ if b&0xF0 == 0xE0 { ++ return 3 ++ } ++ if b&0xF8 == 0xF0 { ++ return 4 ++ } ++ return 0 ++ ++} +diff --git a/vendor/modules.txt b/vendor/modules.txt +index 520bc4ca95e0..e744937180df 100644 +--- a/vendor/modules.txt ++++ b/vendor/modules.txt +@@ -18,9 +18,17 @@ github.com/containerd/containerd/errdefs + github.com/containerd/containerd/log + github.com/containerd/containerd/pkg/userns + github.com/containerd/containerd/platforms ++# github.com/cpuguy83/go-md2man/v2 v2.0.2 ++## explicit; go 1.11 ++github.com/cpuguy83/go-md2man/v2 ++github.com/cpuguy83/go-md2man/v2/md2man + # github.com/creack/pty v1.1.11 + ## explicit; go 1.13 + github.com/creack/pty ++# github.com/docker/cli-docs-tool v0.5.1 ++## explicit; go 1.18 ++github.com/docker/cli-docs-tool ++github.com/docker/cli-docs-tool/annotation + # github.com/docker/distribution v2.8.1+incompatible + ## explicit + github.com/docker/distribution +@@ -222,12 +230,16 @@ github.com/prometheus/procfs/internal/util + # github.com/rivo/uniseg v0.2.0 + ## explicit; go 1.12 + github.com/rivo/uniseg ++# github.com/russross/blackfriday/v2 v2.1.0 ++## explicit ++github.com/russross/blackfriday/v2 + # github.com/sirupsen/logrus v1.9.0 + ## explicit; go 1.13 + github.com/sirupsen/logrus + # github.com/spf13/cobra v1.6.1 + ## explicit; go 1.15 + github.com/spf13/cobra ++github.com/spf13/cobra/doc + # github.com/spf13/pflag v1.0.5 + ## explicit; go 1.12 + github.com/spf13/pflag +@@ -389,6 +401,9 @@ google.golang.org/protobuf/types/known/timestamppb + # gopkg.in/yaml.v2 v2.4.0 + ## explicit; go 1.15 + gopkg.in/yaml.v2 ++# gopkg.in/yaml.v3 v3.0.1 ++## explicit ++gopkg.in/yaml.v3 + # gotest.tools/v3 v3.4.0 + ## explicit; go 1.13 + gotest.tools/v3/assert +-- +2.40.0 + diff --git a/docker-20.10.23_ce_6051f1429.tar.xz b/docker-20.10.23_ce_6051f1429.tar.xz deleted file mode 100644 index 823ee94..0000000 --- a/docker-20.10.23_ce_6051f1429.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0d6b832806f3144a4b917657f615d9388081e7c7b3f77db3b4b7c6c01b931686 -size 6589992 diff --git a/docker-23.0.5_ce_94d3ad69cc59.tar.xz b/docker-23.0.5_ce_94d3ad69cc59.tar.xz new file mode 100644 index 0000000..d5ef907 --- /dev/null +++ b/docker-23.0.5_ce_94d3ad69cc59.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84d3a48cfbeeece15ad367eb03834a97b0c57d195d889e5191c138cd6e06579a +size 8262024 diff --git a/docker-cli-20.10.23_ce.tar.xz b/docker-cli-20.10.23_ce.tar.xz deleted file mode 100644 index be55404..0000000 --- a/docker-cli-20.10.23_ce.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c2a96dd55814fc22ccfe054b78438963fc139b292696bc3ba7667abd399d7c70 -size 4320480 diff --git a/docker-cli-23.0.5_ce.tar.xz b/docker-cli-23.0.5_ce.tar.xz new file mode 100644 index 0000000..8ab54dd --- /dev/null +++ b/docker-cli-23.0.5_ce.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b93219b6b5c781031c1ed35fb3174c59e3572e3437218ca3646361259acb77e8 +size 3498104 diff --git a/docker-libnetwork-05b93e0d3a95952f70c113b0bc5bdb538d7afdd7.tar.xz b/docker-libnetwork-05b93e0d3a95952f70c113b0bc5bdb538d7afdd7.tar.xz deleted file mode 100644 index 91a8dd5..0000000 --- a/docker-libnetwork-05b93e0d3a95952f70c113b0bc5bdb538d7afdd7.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:44fa1530b22f18434174b03895c8933b356f254b718855fd7487888afbb10e91 -size 1983112 diff --git a/docker.changes b/docker.changes index 01ee29d..1327910 100644 --- a/docker.changes +++ b/docker.changes @@ -1,3 +1,30 @@ +------------------------------------------------------------------- +Thu Apr 27 14:09:05 UTC 2023 - Aleksa Sarai + +- Update to Docker 23.0.5-ce. See upstream changelog online at + . +- Rebase patches: + * cli-0001-docs-include-required-tools-in-source-tree.patch + +------------------------------------------------------------------- +Wed Apr 26 00:31:54 UTC 2023 - Aleksa Sarai + +- Update to Docker 23.0.4-ce. See upstream changelog online at + . bsc#1208074 +- Rebase patches: + * 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch + * 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch + * 0003-bsc1073877-apparmor-clobber-docker-default-profile-o.patch +- Renumbered patches: + - 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch +- Remove upstreamed patches: + - 0005-bsc1183855-btrfs-Do-not-disable-quota-on-cleanup.patch + - 0006-bsc1193930-vendor-update-golang.org-x-crypto.patch + - 0007-bsc1200022-fifo.Close-prevent-possible-panic-if-fifo.patch +- Backport to allow man pages to be + built without internet access in OBS. + + cli-0001-docs-include-required-tools-in-source-tree.patch + ------------------------------------------------------------------- Wed Feb 1 14:33:19 UTC 2023 - Dirk Müller diff --git a/docker.spec b/docker.spec index 20ed0bc..7ba190e 100644 --- a/docker.spec +++ b/docker.spec @@ -1,7 +1,7 @@ # # spec file for package docker # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -26,37 +26,16 @@ %define _fillupdir /var/adm/fillup-templates %endif -# Handle _multibuild magic. -%define flavour @BUILD_FLAVOR@%{nil} - -# We split the Name: into "realname" and "name_suffix". -%define realname docker -%if "%flavour" == "" -%define name_suffix %{nil} -%else -%define name_suffix -%{flavour} -%endif - # Used when generating the "build" information for Docker version. The value of # git_commit_epoch is unused here (we use SOURCE_DATE_EPOCH, which rpm # helpfully injects into our build environment from the changelog). If you want # to generate a new git_commit_epoch, use this: # $ date --date="$(git show --format=fuller --date=iso $COMMIT_ID | grep -oP '(?<=^CommitDate: ).*')" '+%s' -%define real_version 20.10.23 -%define git_version 6051f1429 -%define git_commit_epoch 1674059068 +%define real_version 23.0.5 +%define git_version 94d3ad69cc59 +%define git_commit_epoch 1682522945 -# We require a specific pin of libnetwork because it doesn't really do -# versioning and minor version mismatches in libnetwork can break Docker -# networking. All other key runtime dependencies (containerd, runc) are stable -# enough that this isn't necessary. -%define libnetwork_version 05b93e0d3a95952f70c113b0bc5bdb538d7afdd7 - -%define dist_builddir %{_builddir}/dist-suse -%define cli_builddir %{dist_builddir}/src/github.com/docker/cli -%define proxy_builddir %{dist_builddir}/src/github.com/docker/libnetwork - -Name: %{realname}%{name_suffix} +Name: docker Version: %{real_version}_ce # This "nice version" is so that docker --version gives a result that can be # parsed by other people. boo#1182476 @@ -66,9 +45,8 @@ Summary: The Moby-project Linux container runtime License: Apache-2.0 Group: System/Management URL: http://www.docker.io -Source: %{realname}-%{version}_%{git_version}.tar.xz -Source1: %{realname}-cli-%{version}.tar.xz -Source2: %{realname}-libnetwork-%{libnetwork_version}.tar.xz +Source: %{name}-%{version}_%{git_version}.tar.xz +Source1: %{name}-cli-%{version}.tar.xz Source3: docker-rpmlintrc # TODO: Move these source files to somewhere nicer. Source100: docker.service @@ -87,14 +65,9 @@ Patch100: 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch Patch101: 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch # SUSE-FEATURE: Add support to mirror unofficial/private registries # . -Patch300: 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch -# SUSE-BACKPORT: Backport of https://github.com/moby/moby/pull/42273. bsc#1183855 bsc#1175081 -Patch301: 0005-bsc1183855-btrfs-Do-not-disable-quota-on-cleanup.patch -# SUSE-BACKPORT: Backport of several golang.org/x/crypto updates. -# bsc#1193930 CVE-2021-43565 bsc#1197284 CVE-2022-27191 -Patch302: 0006-bsc1193930-vendor-update-golang.org-x-crypto.patch -# SUSE-BACKPORT: Backport of . bsc#1200022 -Patch303: 0007-bsc1200022-fifo.Close-prevent-possible-panic-if-fifo.patch +Patch300: 0003-bsc1073877-apparmor-clobber-docker-default-profile-o.patch +# UPSTREAM: Backport of . +Patch900: cli-0001-docs-include-required-tools-in-source-tree.patch BuildRequires: audit BuildRequires: bash-completion BuildRequires: ca-certificates @@ -111,17 +84,17 @@ BuildRequires: fish BuildRequires: go-go-md2man BuildRequires: pkgconfig(libsystemd) BuildRequires: sysuser-tools -BuildRequires: golang(API) = 1.18 +BuildRequires: golang(API) = 1.19 Requires: (apparmor-parser or container-selinux) Requires: ca-certificates-mozilla # The docker-proxy binary used to be in a separate package. We obsolete it, # since now docker-proxy is maintained as part of this package. -Obsoletes: docker-libnetwork%{name_suffix} < 0.7.0.2 -Provides: docker-libnetwork%{name_suffix} = 0.7.0.2.%{version} +Obsoletes: docker-libnetwork < 0.7.0.2 +Provides: docker-libnetwork = 0.7.0.2.%{version} # Required to actually run containers. We require the minimum version that is # pinned by Docker, but in order to avoid headaches we allow for updates. -Requires: runc >= 1.1.2 -Requires: containerd >= 1.6.9 +Requires: runc >= 1.1.5 +Requires: containerd >= 1.6.20 # Needed for --init support. We don't use "tini", we use our own implementation # which handles edge-cases better. Requires: catatonit @@ -149,7 +122,6 @@ Recommends: lvm2 >= 2.2.89 Recommends: git-core >= 1.7 ExcludeArch: s390 ppc - %description Docker complements LXC with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and @@ -193,38 +165,27 @@ BuildArch: noarch Fish command line completion support for %{name}. %prep -%setup -q -n %{realname}-%{version}_%{git_version} +# docker-cli +%define cli_builddir %{_builddir}/%{name}-cli-%{version} +%setup -q -T -b 1 -n %{name}-cli-%{version} +[ "%{cli_builddir}" = "$PWD" ] +# offline manpages +%patch900 -p1 -%if 0%{?is_opensuse} -# nothing -%else +# docker +%define docker_builddir %{_builddir}/%{name}-%{version}_%{git_version} +%setup -q -n %{name}-%{version}_%{git_version} +[ "%{docker_builddir}" = "$PWD" ] +# README_SUSE.md for documentation. +cp %{SOURCE103} . + +%if 0%{?is_opensuse} == 0 # PATCH-SUSE: Secrets patches. %patch100 -p1 %patch101 -p1 %endif # bsc#1099277 %patch300 -p1 -# bsc#1183855 bsc#1175081 -%patch301 -p1 -# bsc#1193930 CVE-2021-43565 bsc#1197284 CVE-2022-27191 -%patch302 -p1 -# bsc#1200022 -%patch303 -p1 - -# README_SUSE.md for documentation. -cp %{SOURCE103} . - -# Extract the docker-cli source in a subdir. -mkdir -p %{cli_builddir} -pushd %{cli_builddir} -xz -dc %{SOURCE1} | tar -xof - --strip-components=1 -popd - -# Extract the docker-libnetwork source in a subdir. -mkdir -p %{proxy_builddir} -pushd %{proxy_builddir} -xz -dc %{SOURCE2} | tar -xof - --strip-components=1 -popd %build %sysusers_generate_pre %{SOURCE106} %{name} %{name}.conf @@ -239,12 +200,7 @@ BUILDTAGS="exclude_graphdriver_aufs apparmor selinux seccomp pkcs11" BUILDTAGS="libdm_dlsym_deferred_remove $BUILDTAGS" %endif -(cat </dev/null | sed -e 's/ /T/')" -# NOTE: This will have to be removed with the next major Docker bump. -export GO111MODULE=off -EOF -) > docker_build_env -. ./docker_build_env - -# Preparing GOPATH so that the client is visible to the compiler -mkdir -p src/github.com/docker/ -ln -s "%{cli_builddir}" "$PWD/src/github.com/docker/cli" -export GOPATH="$GOPATH:$PWD" ################### ## DOCKER ENGINE ## ################### -# Ignore the warning that we compile outside a Docker container. +pushd "%{docker_builddir}" +# use go module for build +ln -s {vendor,go}.mod +ln -s {vendor,go}.sum ./hack/make.sh dynbinary +popd ################### ## DOCKER CLIENT ## ################### -pushd %{cli_builddir} -make dynbinary - -mkdir -p ./man/man1 -go build -buildmode=pie -o gen-manpages github.com/docker/cli/man -./gen-manpages --root "$PWD" --target "$PWD/man/man1" -./man/md2man-all.sh +pushd "%{cli_builddir}" +# use go module for build +ln -s {vendor,go}.mod +ln -s {vendor,go}.sum +make DISABLE_WARN_OUTSIDE_CONTAINER=1 dynbinary manpages popd -################## -## DOCKER PROXY ## -################## - -pushd %{proxy_builddir} -GOPATH="%{dist_builddir}" \ - go build -buildmode=pie -o docker-proxy github.com/docker/libnetwork/cmd/proxy -popd - -# We verify that our libnetwork source is the correct version. This is done -# on-build to make sure that someone doing an update didn't miss anything. -grep 'LIBNETWORK_COMMIT:=%{libnetwork_version}' hack/dockerfile/install/proxy.installer - %install install -Dd -m0755 \ %{buildroot}%{_sysconfdir}/init.d \ @@ -306,30 +241,31 @@ install -Dd -m0755 \ %{buildroot}%{_sbindir} # docker daemon -install -D -m0755 bundles/dynbinary-daemon/dockerd %{buildroot}/%{_bindir}/dockerd +install -D -m0755 %{docker_builddir}/bundles/dynbinary-daemon/dockerd %{buildroot}/%{_bindir}/dockerd +# docker proxy +install -D -m0755 %{docker_builddir}/bundles/dynbinary-daemon/docker-proxy %{buildroot}/%{_bindir}/docker-proxy + +# /var/lib/docker install -d %{buildroot}/%{_localstatedir}/lib/docker # daemon.json config file install -D -m0644 %{SOURCE105} %{buildroot}%{_sysconfdir}/docker/daemon.json # docker cli install -D -m0755 %{cli_builddir}/build/docker %{buildroot}/%{_bindir}/docker -install -D -m0644 %{cli_builddir}/contrib/completion/bash/docker "%{buildroot}%{_datarootdir}/bash-completion/completions/%{realname}" -install -D -m0644 %{cli_builddir}/contrib/completion/zsh/_docker "%{buildroot}%{_sysconfdir}/zsh_completion.d/_%{realname}" -install -D -m0644 %{cli_builddir}/contrib/completion/fish/docker.fish "%{buildroot}/%{_datadir}/fish/vendor_completions.d/%{realname}.fish" - -# docker proxy -install -D -m0755 %{proxy_builddir}/docker-proxy %{buildroot}/%{_bindir}/docker-proxy +install -D -m0644 %{cli_builddir}/contrib/completion/bash/docker "%{buildroot}%{_datarootdir}/bash-completion/completions/%{name}" +install -D -m0644 %{cli_builddir}/contrib/completion/zsh/_docker "%{buildroot}%{_sysconfdir}/zsh_completion.d/_%{name}" +install -D -m0644 %{cli_builddir}/contrib/completion/fish/docker.fish "%{buildroot}/%{_datadir}/fish/vendor_completions.d/%{name}.fish" # systemd service -install -D -m0644 %{SOURCE100} %{buildroot}%{_unitdir}/%{realname}.service +install -D -m0644 %{SOURCE100} %{buildroot}%{_unitdir}/%{name}.service ln -sf service %{buildroot}%{_sbindir}/rcdocker # udev rules that prevents dolphin to show all docker devices and slows down # upstream report https://bugs.kde.org/show_bug.cgi?id=329930 -install -D -m0644 %{SOURCE101} %{buildroot}%{_udevrulesdir}/80-%{realname}.rules +install -D -m0644 %{SOURCE101} %{buildroot}%{_udevrulesdir}/80-%{name}.rules # audit rules -install -D -m0640 %{SOURCE104} %{buildroot}%{_sysconfdir}/audit/rules.d/%{realname}.rules +install -D -m0640 %{SOURCE104} %{buildroot}%{_sysconfdir}/audit/rules.d/%{name}.rules # sysconfig file install -D -m0644 %{SOURCE102} %{buildroot}%{_fillupdir}/sysconfig.docker @@ -363,17 +299,17 @@ grep -q '^dockremap:' /etc/subgid || \ usermod -w 100000000-200000000 dockremap &>/dev/null || \ echo "dockremap:100000000:100000001" >>/etc/subgid ||: -%service_add_pre %{realname}.service +%service_add_pre %{name}.service %post -%service_add_post %{realname}.service +%service_add_post %{name}.service %{fillup_only -n docker} %preun -%service_del_preun %{realname}.service +%service_del_preun %{name}.service %postun -%service_del_postun %{realname}.service +%service_del_postun %{name}.service %files %defattr(-,root,root) @@ -385,15 +321,15 @@ grep -q '^dockremap:' /etc/subgid || \ %{_sbindir}/rcdocker %dir %{_localstatedir}/lib/docker/ -%{_unitdir}/%{realname}.service +%{_unitdir}/%{name}.service %{_sysusersdir}/%{name}.conf %dir %{_sysconfdir}/docker %config(noreplace) %{_sysconfdir}/docker/daemon.json %{_fillupdir}/sysconfig.docker -%config %{_sysconfdir}/audit/rules.d/%{realname}.rules -%{_udevrulesdir}/80-%{realname}.rules +%config %{_sysconfdir}/audit/rules.d/%{name}.rules +%{_udevrulesdir}/80-%{name}.rules %{_mandir}/man1/docker-*.1%{ext_man} %{_mandir}/man1/docker.1%{ext_man} @@ -402,14 +338,14 @@ grep -q '^dockremap:' /etc/subgid || \ %files bash-completion %defattr(-,root,root) -%{_datarootdir}/bash-completion/completions/%{realname} +%{_datarootdir}/bash-completion/completions/%{name} %files zsh-completion %defattr(-,root,root) -%{_sysconfdir}/zsh_completion.d/_%{realname} +%{_sysconfdir}/zsh_completion.d/_%{name} %files fish-completion %defattr(-,root,root) -%{_datadir}/fish/vendor_completions.d/%{realname}.fish +%{_datadir}/fish/vendor_completions.d/%{name}.fish %changelog