diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index ba13efec..27043dfc 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -1,3 +1,5 @@
+version: 2
+
before:
hooks:
- go mod tidy
@@ -38,14 +40,14 @@ archives:
blobs:
- provider: gs
bucket: bitrise-cli-releases-prod
- folder: /{{ .Tag }}
+ directory: /{{ .Tag }}
ids:
- default
- provider: s3
bucket: bitrise-cli-releases-prod
region: us-east-1
endpoint: "{{ .Env.AWS_ENDPOINT_URL }}"
- folder: /
+ directory: /
ids:
- s3
diff --git a/bitrise.yml b/bitrise.yml
index 939a182f..a4522ed8 100644
--- a/bitrise.yml
+++ b/bitrise.yml
@@ -326,7 +326,7 @@ step_bundles:
#!/usr/bin/env bash
set -ex
- goreleaser release --snapshot --rm-dist
+ goreleaser release --snapshot --clean
- deploy-to-bitrise-io@2: { }
setup_repo:
@@ -362,14 +362,8 @@ step_bundles:
- content: |-
#!/bin/bash
set -ex
-
- if [ "$(uname)" = "Linux" ]; then
- wget -O /tmp/goreleaser.deb https://github.com/goreleaser/goreleaser/releases/download/v1.19.2/goreleaser_1.19.2_amd64.deb
- sudo dpkg -i /tmp/goreleaser.deb
- else
- go install github.com/goreleaser/goreleaser@latest
- asdf reshim golang
- fi
+ go install github.com/goreleaser/goreleaser/v2@latest
+ asdf reshim golang
meta:
bitrise.io:
diff --git a/bitrise/util_test.go b/bitrise/util_test.go
index ae46e872..3905e73d 100644
--- a/bitrise/util_test.go
+++ b/bitrise/util_test.go
@@ -305,3 +305,199 @@ workflows:
require.Error(t, err)
require.Equal(t, 0, len(warnings))
}
+
+func TestConfigModelFromYAMLFileContent_StepListValidation(t *testing.T) {
+ tests := []struct {
+ name string
+ config string
+ wantErr string
+ }{
+ {
+ name: "Invalid bitrise.yml: step bundle in a step bundle's steps list",
+ config: `
+format_version: '11'
+default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
+step_bundles:
+ build: {}
+ test:
+ steps:
+ - bundle::build: {}`,
+ wantErr: "step bundle (test) has config issue: step bundle is not allowed in a step bundle's step list",
+ },
+ {
+ name: "Invalid bitrise.yml: with group in a step bundle's steps list",
+ config: `
+format_version: '11'
+default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
+step_bundles:
+ test:
+ steps:
+ - with: {}`,
+ wantErr: "step bundle (test) has config issue: 'with' group is not allowed in a step bundle's step list",
+ },
+ {
+ name: "Invalid bitrise.yml: step bundle in a 'with' group's steps list",
+ config: `
+format_version: '11'
+default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
+services:
+ postgres:
+ image: postgres:13
+workflows:
+ primary:
+ steps:
+ - with:
+ services:
+ - postgres
+ steps:
+ - bundle::test: {}`,
+ wantErr: "invalid 'with' group in workflow (primary): step bundle is not allowed in a 'with' group's step list",
+ },
+ {
+ name: "Invalid bitrise.yml: with group in a 'with' group's steps list",
+ config: `
+format_version: '11'
+default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
+services:
+ postgres:
+ image: postgres:13
+workflows:
+ primary:
+ steps:
+ - with:
+ services:
+ - postgres
+ steps:
+ - with: {}`,
+ wantErr: "invalid 'with' group in workflow (primary): 'with' group is not allowed in a 'with' group's step list",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ _, warns, err := ConfigModelFromFileContent([]byte(tt.config), false)
+ require.Equal(t, []string(nil), warns)
+ if tt.wantErr != "" {
+ require.EqualError(t, err, tt.wantErr)
+ } else {
+ require.NoError(t, err)
+ }
+ })
+ }
+}
+
+func TestConfigModelFromJSONFileContent_StepListValidation(t *testing.T) {
+ tests := []struct {
+ name string
+ config string
+ wantErr string
+ }{
+ {
+ name: "Invalid bitrise.yml: step bundle in a step bundle's steps list",
+ config: `{
+ "format_version": "11",
+ "default_step_lib_source": "https://github.com/bitrise-io/bitrise-steplib.git",
+ "step_bundles": {
+ "build": {},
+ "test": {
+ "steps": [
+ {
+ "bundle::build": {}
+ }
+ ]
+ }
+ }
+}`,
+ wantErr: "step bundle (test) has config issue: step bundle is not allowed in a step bundle's step list",
+ },
+ {
+ name: "Invalid bitrise.yml: with group in a step bundle's steps list",
+ config: `{
+ "format_version": "11",
+ "default_step_lib_source": "https://github.com/bitrise-io/bitrise-steplib.git",
+ "step_bundles": {
+ "test": {
+ "steps": [
+ {
+ "with": {}
+ }
+ ]
+ }
+ }
+}`,
+ wantErr: "step bundle (test) has config issue: 'with' group is not allowed in a step bundle's step list",
+ },
+ {
+ name: "Invalid bitrise.yml: step bundle in a 'with' group's steps list",
+ config: `{
+ "format_version": "11",
+ "default_step_lib_source": "https://github.com/bitrise-io/bitrise-steplib.git",
+ "services": {
+ "postgres": {
+ "image": "postgres:13"
+ }
+ },
+ "workflows": {
+ "primary": {
+ "steps": [
+ {
+ "with": {
+ "services": [
+ "postgres"
+ ],
+ "steps": [
+ {
+ "bundle::test": {}
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+}`,
+ wantErr: "invalid 'with' group in workflow (primary): step bundle is not allowed in a 'with' group's step list",
+ },
+ {
+ name: "Invalid bitrise.yml: with group in a 'with' group's steps list",
+ config: `{
+ "format_version": "11",
+ "default_step_lib_source": "https://github.com/bitrise-io/bitrise-steplib.git",
+ "services": {
+ "postgres": {
+ "image": "postgres:13"
+ }
+ },
+ "workflows": {
+ "primary": {
+ "steps": [
+ {
+ "with": {
+ "services": [
+ "postgres"
+ ],
+ "steps": [
+ {
+ "with": {}
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+}`,
+ wantErr: "invalid 'with' group in workflow (primary): 'with' group is not allowed in a 'with' group's step list",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ _, warns, err := ConfigModelFromFileContent([]byte(tt.config), true)
+ require.Equal(t, []string(nil), warns)
+ if tt.wantErr != "" {
+ require.EqualError(t, err, tt.wantErr)
+ } else {
+ require.NoError(t, err)
+ }
+ })
+ }
+}
diff --git a/go.mod b/go.mod
index 30b40687..fee2768a 100644
--- a/go.mod
+++ b/go.mod
@@ -12,31 +12,31 @@ require (
github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.22
github.com/bitrise-io/goinp v0.0.0-20240103152431-054ed78518ef
github.com/bitrise-io/stepman v0.0.0-20240828074035-6ae1a5f5efde
- github.com/go-git/go-git/v5 v5.12.0
+ github.com/go-git/go-git/v5 v5.13.0
github.com/gofrs/uuid v4.3.1+incompatible
github.com/hashicorp/go-retryablehttp v0.7.7
github.com/hashicorp/go-version v1.4.0
github.com/heimdalr/dag v1.4.0
github.com/ryanuber/go-glob v1.0.0
- github.com/stretchr/testify v1.9.0
+ github.com/stretchr/testify v1.10.0
github.com/urfave/cli v1.22.15
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
- golang.org/x/sys v0.25.0
+ golang.org/x/sys v0.28.0
gopkg.in/yaml.v2 v2.4.0
)
require (
dario.cat/mergo v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
- github.com/ProtonMail/go-crypto v1.0.0 // indirect
+ github.com/ProtonMail/go-crypto v1.1.3 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
- github.com/cyphar/filepath-securejoin v0.2.4 // indirect
+ github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
- github.com/go-git/go-billy/v5 v5.5.0 // indirect
+ github.com/go-git/go-billy/v5 v5.6.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
@@ -50,13 +50,13 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
- github.com/skeema/knownhosts v1.2.2 // indirect
+ github.com/skeema/knownhosts v1.3.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
- golang.org/x/crypto v0.27.0 // indirect
+ golang.org/x/crypto v0.31.0 // indirect
golang.org/x/mod v0.21.0 // indirect
- golang.org/x/net v0.29.0 // indirect
- golang.org/x/sync v0.8.0 // indirect
- golang.org/x/term v0.24.0 // indirect
+ golang.org/x/net v0.33.0 // indirect
+ golang.org/x/sync v0.10.0 // indirect
+ golang.org/x/term v0.27.0 // indirect
golang.org/x/tools v0.25.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index 8f0aaebc..ecf6a855 100644
--- a/go.sum
+++ b/go.sum
@@ -8,6 +8,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
+github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
+github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -34,6 +36,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lV
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
+github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
+github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@@ -59,10 +63,14 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
+github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
+github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
+github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E=
+github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw=
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI=
@@ -136,6 +144,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
+github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
+github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -151,6 +161,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
@@ -168,6 +180,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -188,6 +202,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -195,6 +211,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -213,6 +231,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -220,6 +240,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
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/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
diff --git a/models/models_methods.go b/models/models_methods.go
index 13b323be..e46d6486 100644
--- a/models/models_methods.go
+++ b/models/models_methods.go
@@ -312,6 +312,12 @@ func (bundle *StepBundleModel) Validate() ([]string, error) {
return warnings, err
}
+ if stepID == StepListItemWithKey {
+ return warnings, errors.New("'with' group is not allowed in a step bundle's step list")
+ } else if strings.HasPrefix(stepID, StepListItemStepBundleKeyPrefix) {
+ return warnings, errors.New("step bundle is not allowed in a step bundle's step list")
+ }
+
warns, err := validateStep(stepID, step)
warnings = append(warnings, warns...)
if err != nil {
@@ -357,6 +363,12 @@ func (with *WithModel) Validate(workflowID string, containers, services map[stri
return warnings, err
}
+ if stepID == StepListItemWithKey {
+ return warnings, fmt.Errorf("invalid 'with' group in workflow (%s): 'with' group is not allowed in a 'with' group's step list", workflowID)
+ } else if strings.HasPrefix(stepID, StepListItemStepBundleKeyPrefix) {
+ return warnings, fmt.Errorf("invalid 'with' group in workflow (%s): step bundle is not allowed in a 'with' group's step list", workflowID)
+ }
+
warns, err := validateStep(stepID, step)
warnings = append(warnings, warns...)
if err != nil {
diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go b/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
index 1a6f7350..5022285b 100644
--- a/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
+++ b/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
@@ -18,8 +18,9 @@ import (
"crypto/cipher"
"crypto/subtle"
"errors"
- "github.com/ProtonMail/go-crypto/internal/byteutil"
"math/bits"
+
+ "github.com/ProtonMail/go-crypto/internal/byteutil"
)
type ocb struct {
@@ -153,7 +154,7 @@ func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
truncatedNonce := make([]byte, len(nonce))
copy(truncatedNonce, nonce)
truncatedNonce[len(truncatedNonce)-1] &= 192
- Ktop := make([]byte, blockSize)
+ var Ktop []byte
if bytes.Equal(truncatedNonce, o.reusableKtop.noncePrefix) {
Ktop = o.reusableKtop.Ktop
} else {
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
index d7af9141..e0a677f2 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
@@ -23,7 +23,7 @@ import (
// Headers
//
// base64-encoded Bytes
-// '=' base64 encoded checksum
+// '=' base64 encoded checksum (optional) not checked anymore
// -----END Type-----
//
// where Headers is a possibly empty sequence of Key: Value lines.
@@ -40,36 +40,15 @@ type Block struct {
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.
+// lineReader wraps a line based reader. It watches for the end of an armor block
type lineReader struct {
- in *bufio.Reader
- buf []byte
- eof bool
- crc uint32
- crcSet bool
+ in *bufio.Reader
+ buf []byte
+ eof bool
}
func (l *lineReader) Read(p []byte) (n int, err error) {
@@ -98,26 +77,9 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
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
- }
+ // Don't check the checksum
l.eof = true
- l.crcSet = true
return 0, io.EOF
}
@@ -138,23 +100,14 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
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.
+// openpgpReader passes Read calls to the underlying base64 decoder.
type openpgpReader struct {
- lReader *lineReader
- b64Reader io.Reader
- currentCRC uint32
+ lReader *lineReader
+ b64Reader io.Reader
}
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
}
@@ -222,7 +175,6 @@ TryNextBlock:
}
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
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
index 5b6e16c1..112f98b8 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
@@ -14,6 +14,23 @@ var blockEnd = []byte("\n=")
var newline = []byte("\n")
var armorEndOfLineOut = []byte("-----\n")
+const crc24Init = 0xb704ce
+const crc24Poly = 0x1864cfb
+
+// 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
+}
+
// writeSlices writes its arguments to the given Writer.
func writeSlices(out io.Writer, slices ...[]byte) (err error) {
for _, s := range slices {
@@ -99,15 +116,18 @@ func (l *lineBreaker) Close() (err error) {
//
// encoding -> base64 encoder -> lineBreaker -> out
type encoding struct {
- out io.Writer
- breaker *lineBreaker
- b64 io.WriteCloser
- crc uint32
- blockType []byte
+ out io.Writer
+ breaker *lineBreaker
+ b64 io.WriteCloser
+ crc uint32
+ crcEnabled bool
+ blockType []byte
}
func (e *encoding) Write(data []byte) (n int, err error) {
- e.crc = crc24(e.crc, data)
+ if e.crcEnabled {
+ e.crc = crc24(e.crc, data)
+ }
return e.b64.Write(data)
}
@@ -118,20 +138,21 @@ func (e *encoding) Close() (err error) {
}
e.breaker.Close()
- var checksumBytes [3]byte
- checksumBytes[0] = byte(e.crc >> 16)
- checksumBytes[1] = byte(e.crc >> 8)
- checksumBytes[2] = byte(e.crc)
+ if e.crcEnabled {
+ 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[:])
+ var b64ChecksumBytes [4]byte
+ base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
- return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
+ return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
+ }
+ return writeSlices(e.out, 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) {
+func encode(out io.Writer, blockType string, headers map[string]string, checksum bool) (w io.WriteCloser, err error) {
bType := []byte(blockType)
err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
if err != nil {
@@ -151,11 +172,27 @@ func Encode(out io.Writer, blockType string, headers map[string]string) (w io.Wr
}
e := &encoding{
- out: out,
- breaker: newLineBreaker(out, 64),
- crc: crc24Init,
- blockType: bType,
+ out: out,
+ breaker: newLineBreaker(out, 64),
+ blockType: bType,
+ crc: crc24Init,
+ crcEnabled: checksum,
}
e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
return e, nil
}
+
+// 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) {
+ return encode(out, blockType, headers, true)
+}
+
+// EncodeWithChecksumOption returns a WriteCloser which will encode the data written to it in
+// OpenPGP armor and provides the option to include a checksum.
+// When forming ASCII Armor, the CRC24 footer SHOULD NOT be generated,
+// unless interoperability with implementations that require the CRC24 footer
+// to be present is a concern.
+func EncodeWithChecksumOption(out io.Writer, blockType string, headers map[string]string, doChecksum bool) (w io.WriteCloser, err error) {
+ return encode(out, blockType, headers, doChecksum)
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go
index a94f6150..5b40e137 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go
@@ -30,8 +30,12 @@ func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
if c == '\r' {
*s = 1
} else if c == '\n' {
- cw.Write(buf[start:i])
- cw.Write(newline)
+ if _, err := cw.Write(buf[start:i]); err != nil {
+ return 0, err
+ }
+ if _, err := cw.Write(newline); err != nil {
+ return 0, err
+ }
start = i + 1
}
case 1:
@@ -39,7 +43,9 @@ func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
}
}
- cw.Write(buf[start:])
+ if _, err := cw.Write(buf[start:]); err != nil {
+ return 0, err
+ }
return len(buf), nil
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
index c895bad6..db8fb163 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
@@ -163,13 +163,9 @@ func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLead
if _, err := param.Write([]byte("Anonymous Sender ")); err != nil {
return nil, err
}
- // For v5 keys, the 20 leftmost octets of the fingerprint are used.
- if _, err := param.Write(fingerprint[:20]); err != nil {
+ if _, err := param.Write(fingerprint[:]); err != nil {
return nil, err
}
- if param.Len()-len(curveOID) != 45 {
- return nil, errors.New("ecdh: malformed KDF Param")
- }
// MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
h := pub.KDF.Hash.New()
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go
new file mode 100644
index 00000000..6abdf7c4
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go
@@ -0,0 +1,115 @@
+// Package ed25519 implements the ed25519 signature algorithm for OpenPGP
+// as defined in the Open PGP crypto refresh.
+package ed25519
+
+import (
+ "crypto/subtle"
+ "io"
+
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+ ed25519lib "github.com/cloudflare/circl/sign/ed25519"
+)
+
+const (
+ // PublicKeySize is the size, in bytes, of public keys in this package.
+ PublicKeySize = ed25519lib.PublicKeySize
+ // SeedSize is the size, in bytes, of private key seeds.
+ // The private key representation used by RFC 8032.
+ SeedSize = ed25519lib.SeedSize
+ // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
+ SignatureSize = ed25519lib.SignatureSize
+)
+
+type PublicKey struct {
+ // Point represents the elliptic curve point of the public key.
+ Point []byte
+}
+
+type PrivateKey struct {
+ PublicKey
+ // Key the private key representation by RFC 8032,
+ // encoded as seed | pub key point.
+ Key []byte
+}
+
+// NewPublicKey creates a new empty ed25519 public key.
+func NewPublicKey() *PublicKey {
+ return &PublicKey{}
+}
+
+// NewPrivateKey creates a new empty private key referencing the public key.
+func NewPrivateKey(key PublicKey) *PrivateKey {
+ return &PrivateKey{
+ PublicKey: key,
+ }
+}
+
+// Seed returns the ed25519 private key secret seed.
+// The private key representation by RFC 8032.
+func (pk *PrivateKey) Seed() []byte {
+ return pk.Key[:SeedSize]
+}
+
+// MarshalByteSecret returns the underlying 32 byte seed of the private key.
+func (pk *PrivateKey) MarshalByteSecret() []byte {
+ return pk.Seed()
+}
+
+// UnmarshalByteSecret computes the private key from the secret seed
+// and stores it in the private key object.
+func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error {
+ sk.Key = ed25519lib.NewKeyFromSeed(seed)
+ return nil
+}
+
+// GenerateKey generates a fresh private key with the provided randomness source.
+func GenerateKey(rand io.Reader) (*PrivateKey, error) {
+ publicKey, privateKey, err := ed25519lib.GenerateKey(rand)
+ if err != nil {
+ return nil, err
+ }
+ privateKeyOut := new(PrivateKey)
+ privateKeyOut.PublicKey.Point = publicKey[:]
+ privateKeyOut.Key = privateKey[:]
+ return privateKeyOut, nil
+}
+
+// Sign signs a message with the ed25519 algorithm.
+// priv MUST be a valid key! Check this with Validate() before use.
+func Sign(priv *PrivateKey, message []byte) ([]byte, error) {
+ return ed25519lib.Sign(priv.Key, message), nil
+}
+
+// Verify verifies an ed25519 signature.
+func Verify(pub *PublicKey, message []byte, signature []byte) bool {
+ return ed25519lib.Verify(pub.Point, message, signature)
+}
+
+// Validate checks if the ed25519 private key is valid.
+func Validate(priv *PrivateKey) error {
+ expectedPrivateKey := ed25519lib.NewKeyFromSeed(priv.Seed())
+ if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 {
+ return errors.KeyInvalidError("ed25519: invalid ed25519 secret")
+ }
+ if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 {
+ return errors.KeyInvalidError("ed25519: invalid ed25519 public key")
+ }
+ return nil
+}
+
+// ENCODING/DECODING signature:
+
+// WriteSignature encodes and writes an ed25519 signature to writer.
+func WriteSignature(writer io.Writer, signature []byte) error {
+ _, err := writer.Write(signature)
+ return err
+}
+
+// ReadSignature decodes an ed25519 signature from a reader.
+func ReadSignature(reader io.Reader) ([]byte, error) {
+ signature := make([]byte, SignatureSize)
+ if _, err := io.ReadFull(reader, signature); err != nil {
+ return nil, err
+ }
+ return signature, nil
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go
new file mode 100644
index 00000000..b11fb4fb
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go
@@ -0,0 +1,119 @@
+// Package ed448 implements the ed448 signature algorithm for OpenPGP
+// as defined in the Open PGP crypto refresh.
+package ed448
+
+import (
+ "crypto/subtle"
+ "io"
+
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+ ed448lib "github.com/cloudflare/circl/sign/ed448"
+)
+
+const (
+ // PublicKeySize is the size, in bytes, of public keys in this package.
+ PublicKeySize = ed448lib.PublicKeySize
+ // SeedSize is the size, in bytes, of private key seeds.
+ // The private key representation used by RFC 8032.
+ SeedSize = ed448lib.SeedSize
+ // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
+ SignatureSize = ed448lib.SignatureSize
+)
+
+type PublicKey struct {
+ // Point represents the elliptic curve point of the public key.
+ Point []byte
+}
+
+type PrivateKey struct {
+ PublicKey
+ // Key the private key representation by RFC 8032,
+ // encoded as seed | public key point.
+ Key []byte
+}
+
+// NewPublicKey creates a new empty ed448 public key.
+func NewPublicKey() *PublicKey {
+ return &PublicKey{}
+}
+
+// NewPrivateKey creates a new empty private key referencing the public key.
+func NewPrivateKey(key PublicKey) *PrivateKey {
+ return &PrivateKey{
+ PublicKey: key,
+ }
+}
+
+// Seed returns the ed448 private key secret seed.
+// The private key representation by RFC 8032.
+func (pk *PrivateKey) Seed() []byte {
+ return pk.Key[:SeedSize]
+}
+
+// MarshalByteSecret returns the underlying seed of the private key.
+func (pk *PrivateKey) MarshalByteSecret() []byte {
+ return pk.Seed()
+}
+
+// UnmarshalByteSecret computes the private key from the secret seed
+// and stores it in the private key object.
+func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error {
+ sk.Key = ed448lib.NewKeyFromSeed(seed)
+ return nil
+}
+
+// GenerateKey generates a fresh private key with the provided randomness source.
+func GenerateKey(rand io.Reader) (*PrivateKey, error) {
+ publicKey, privateKey, err := ed448lib.GenerateKey(rand)
+ if err != nil {
+ return nil, err
+ }
+ privateKeyOut := new(PrivateKey)
+ privateKeyOut.PublicKey.Point = publicKey[:]
+ privateKeyOut.Key = privateKey[:]
+ return privateKeyOut, nil
+}
+
+// Sign signs a message with the ed448 algorithm.
+// priv MUST be a valid key! Check this with Validate() before use.
+func Sign(priv *PrivateKey, message []byte) ([]byte, error) {
+ // Ed448 is used with the empty string as a context string.
+ // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7
+ return ed448lib.Sign(priv.Key, message, ""), nil
+}
+
+// Verify verifies a ed448 signature
+func Verify(pub *PublicKey, message []byte, signature []byte) bool {
+ // Ed448 is used with the empty string as a context string.
+ // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7
+ return ed448lib.Verify(pub.Point, message, signature, "")
+}
+
+// Validate checks if the ed448 private key is valid
+func Validate(priv *PrivateKey) error {
+ expectedPrivateKey := ed448lib.NewKeyFromSeed(priv.Seed())
+ if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 {
+ return errors.KeyInvalidError("ed448: invalid ed448 secret")
+ }
+ if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 {
+ return errors.KeyInvalidError("ed448: invalid ed448 public key")
+ }
+ return nil
+}
+
+// ENCODING/DECODING signature:
+
+// WriteSignature encodes and writes an ed448 signature to writer.
+func WriteSignature(writer io.Writer, signature []byte) error {
+ _, err := writer.Write(signature)
+ return err
+}
+
+// ReadSignature decodes an ed448 signature from a reader.
+func ReadSignature(reader io.Reader) ([]byte, error) {
+ signature := make([]byte, SignatureSize)
+ if _, err := io.ReadFull(reader, signature); err != nil {
+ return nil, err
+ }
+ return signature, nil
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
index 17e2bcfe..0eb3937b 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
@@ -9,6 +9,18 @@ import (
"strconv"
)
+var (
+ // ErrDecryptSessionKeyParsing is a generic error message for parsing errors in decrypted data
+ // to reduce the risk of oracle attacks.
+ ErrDecryptSessionKeyParsing = DecryptWithSessionKeyError("parsing error")
+ // ErrAEADTagVerification is returned if one of the tag verifications in SEIPDv2 fails
+ ErrAEADTagVerification error = DecryptWithSessionKeyError("AEAD tag verification failed")
+ // ErrMDCHashMismatch
+ ErrMDCHashMismatch error = SignatureError("MDC hash mismatch")
+ // ErrMDCMissing
+ ErrMDCMissing error = SignatureError("MDC packet not found")
+)
+
// A StructuralError is returned when OpenPGP data is found to be syntactically
// invalid.
type StructuralError string
@@ -17,6 +29,34 @@ func (s StructuralError) Error() string {
return "openpgp: invalid data: " + string(s)
}
+// A DecryptWithSessionKeyError is returned when a failure occurs when reading from symmetrically decrypted data or
+// an authentication tag verification fails.
+// Such an error indicates that the supplied session key is likely wrong or the data got corrupted.
+type DecryptWithSessionKeyError string
+
+func (s DecryptWithSessionKeyError) Error() string {
+ return "openpgp: decryption with session key failed: " + string(s)
+}
+
+// HandleSensitiveParsingError handles parsing errors when reading data from potentially decrypted data.
+// The function makes parsing errors generic to reduce the risk of oracle attacks in SEIPDv1.
+func HandleSensitiveParsingError(err error, decrypted bool) error {
+ if !decrypted {
+ // Data was not encrypted so we return the inner error.
+ return err
+ }
+ // The data is read from a stream that decrypts using a session key;
+ // therefore, we need to handle parsing errors appropriately.
+ // This is essential to mitigate the risk of oracle attacks.
+ if decError, ok := err.(*DecryptWithSessionKeyError); ok {
+ return decError
+ }
+ if decError, ok := err.(DecryptWithSessionKeyError); ok {
+ return decError
+ }
+ return ErrDecryptSessionKeyParsing
+}
+
// UnsupportedError indicates that, although the OpenPGP data is valid, it
// makes use of currently unimplemented features.
type UnsupportedError string
@@ -41,9 +81,6 @@ func (b SignatureError) Error() string {
return "openpgp: invalid signature: " + string(b)
}
-var ErrMDCHashMismatch error = SignatureError("MDC hash mismatch")
-var ErrMDCMissing error = SignatureError("MDC packet not found")
-
type signatureExpiredError int
func (se signatureExpiredError) Error() string {
@@ -58,6 +95,14 @@ func (ke keyExpiredError) Error() string {
return "openpgp: key expired"
}
+var ErrSignatureOlderThanKey error = signatureOlderThanKeyError(0)
+
+type signatureOlderThanKeyError int
+
+func (ske signatureOlderThanKeyError) Error() string {
+ return "openpgp: signature is older than the key"
+}
+
var ErrKeyExpired error = keyExpiredError(0)
type keyIncorrectError int
@@ -92,12 +137,24 @@ func (keyRevokedError) Error() string {
var ErrKeyRevoked error = keyRevokedError(0)
+type WeakAlgorithmError string
+
+func (e WeakAlgorithmError) Error() string {
+ return "openpgp: weak algorithms are rejected: " + string(e)
+}
+
type UnknownPacketTypeError uint8
func (upte UnknownPacketTypeError) Error() string {
return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
}
+type CriticalUnknownPacketTypeError uint8
+
+func (upte CriticalUnknownPacketTypeError) Error() string {
+ return "openpgp: unknown critical packet type: " + strconv.Itoa(int(upte))
+}
+
// AEADError indicates that there is a problem when initializing or using a
// AEAD instance, configuration struct, nonces or index values.
type AEADError string
@@ -114,3 +171,10 @@ type ErrDummyPrivateKey string
func (dke ErrDummyPrivateKey) Error() string {
return "openpgp: s2k GNU dummy key: " + string(dke)
}
+
+// ErrMalformedMessage results when the packet sequence is incorrect
+type ErrMalformedMessage string
+
+func (dke ErrMalformedMessage) Error() string {
+ return "openpgp: malformed message " + string(dke)
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
index 5760cff8..c76a75bc 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
@@ -51,24 +51,14 @@ func (sk CipherFunction) Id() uint8 {
return uint8(sk)
}
-var keySizeByID = map[uint8]int{
- TripleDES.Id(): 24,
- CAST5.Id(): cast5.KeySize,
- AES128.Id(): 16,
- AES192.Id(): 24,
- AES256.Id(): 32,
-}
-
// KeySize returns the key size, in bytes, of cipher.
func (cipher CipherFunction) KeySize() int {
switch cipher {
- case TripleDES:
- return 24
case CAST5:
return cast5.KeySize
case AES128:
return 16
- case AES192:
+ case AES192, TripleDES:
return 24
case AES256:
return 32
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
index 35751034..0da2d0d8 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
@@ -4,11 +4,14 @@ package ecc
import (
"bytes"
"crypto/elliptic"
+
"github.com/ProtonMail/go-crypto/bitcurves"
"github.com/ProtonMail/go-crypto/brainpool"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
)
+const Curve25519GenName = "Curve25519"
+
type CurveInfo struct {
GenName string
Oid *encoding.OID
@@ -42,19 +45,19 @@ var Curves = []CurveInfo{
},
{
// Curve25519
- GenName: "Curve25519",
+ GenName: Curve25519GenName,
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
Curve: NewCurve25519(),
},
{
- // X448
+ // x448
GenName: "Curve448",
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x6F}),
Curve: NewX448(),
},
{
// Ed25519
- GenName: "Curve25519",
+ GenName: Curve25519GenName,
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
Curve: NewEd25519(),
},
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
index 54a08a8a..5a4c3a85 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
@@ -2,6 +2,7 @@
package ecc
import (
+ "bytes"
"crypto/subtle"
"io"
@@ -90,7 +91,14 @@ func (c *ed25519) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
}
func getEd25519Sk(publicKey, privateKey []byte) ed25519lib.PrivateKey {
- return append(privateKey, publicKey...)
+ privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey)
+
+ if privateKeyCap >= privateKeyLen+publicKeyLen &&
+ bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) {
+ return privateKey[:privateKeyLen+publicKeyLen]
+ }
+
+ return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...)
}
func (c *ed25519) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
index 18cd8043..b6edda74 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
@@ -2,6 +2,7 @@
package ecc
import (
+ "bytes"
"crypto/subtle"
"io"
@@ -84,7 +85,14 @@ func (c *ed448) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
}
func getEd448Sk(publicKey, privateKey []byte) ed448lib.PrivateKey {
- return append(privateKey, publicKey...)
+ privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey)
+
+ if privateKeyCap >= privateKeyLen+publicKeyLen &&
+ bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) {
+ return privateKey[:privateKeyLen+publicKeyLen]
+ }
+
+ return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...)
}
func (c *ed448) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
index 0e71934c..77213f66 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
@@ -15,11 +15,15 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
+ "github.com/ProtonMail/go-crypto/openpgp/ed25519"
+ "github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"github.com/ProtonMail/go-crypto/openpgp/packet"
+ "github.com/ProtonMail/go-crypto/openpgp/x25519"
+ "github.com/ProtonMail/go-crypto/openpgp/x448"
)
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
@@ -36,8 +40,10 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
return nil, err
}
primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw)
- if config != nil && config.V5Keys {
- primary.UpgradeToV5()
+ if config.V6() {
+ if err := primary.UpgradeToV6(); err != nil {
+ return nil, err
+ }
}
e := &Entity{
@@ -45,9 +51,25 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
PrivateKey: primary,
Identities: make(map[string]*Identity),
Subkeys: []Subkey{},
+ Signatures: []*packet.Signature{},
+ }
+
+ if config.V6() {
+ // In v6 keys algorithm preferences should be stored in direct key signatures
+ selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypeDirectSignature, config)
+ err = writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
+ if err != nil {
+ return nil, err
+ }
+ err = selfSignature.SignDirectKeyBinding(&primary.PublicKey, primary, config)
+ if err != nil {
+ return nil, err
+ }
+ e.Signatures = append(e.Signatures, selfSignature)
+ e.SelfSignature = selfSignature
}
- err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs)
+ err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
if err != nil {
return nil, err
}
@@ -65,32 +87,19 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
func (t *Entity) AddUserId(name, comment, email string, config *packet.Config) error {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
- return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs)
+ return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
}
-func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error {
- uid := packet.NewUserId(name, comment, email)
- if uid == nil {
- return errors.InvalidArgumentError("user id field contained invalid characters")
- }
-
- if _, ok := t.Identities[uid.Id]; ok {
- return errors.InvalidArgumentError("user id exist")
- }
-
- primary := t.PrivateKey
-
- isPrimaryId := len(t.Identities) == 0
+func writeKeyProperties(selfSignature *packet.Signature, creationTime time.Time, keyLifetimeSecs uint32, config *packet.Config) error {
+ advertiseAead := config.AEAD() != nil
- selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypePositiveCert, config)
selfSignature.CreationTime = creationTime
selfSignature.KeyLifetimeSecs = &keyLifetimeSecs
- selfSignature.IsPrimaryId = &isPrimaryId
selfSignature.FlagsValid = true
selfSignature.FlagSign = true
selfSignature.FlagCertify = true
selfSignature.SEIPDv1 = true // true by default, see 5.8 vs. 5.14
- selfSignature.SEIPDv2 = config.AEAD() != nil
+ selfSignature.SEIPDv2 = advertiseAead
// Set the PreferredHash for the SelfSignature from the packet.Config.
// If it is not the must-implement algorithm from rfc4880bis, append that.
@@ -119,18 +128,44 @@ func (t *Entity) addUserId(name, comment, email string, config *packet.Config, c
selfSignature.PreferredCompression = append(selfSignature.PreferredCompression, uint8(config.Compression()))
}
- // And for DefaultMode.
- modes := []uint8{uint8(config.AEAD().Mode())}
- if config.AEAD().Mode() != packet.AEADModeOCB {
- modes = append(modes, uint8(packet.AEADModeOCB))
+ if advertiseAead {
+ // Get the preferred AEAD mode from the packet.Config.
+ // If it is not the must-implement algorithm from rfc9580, append that.
+ modes := []uint8{uint8(config.AEAD().Mode())}
+ if config.AEAD().Mode() != packet.AEADModeOCB {
+ modes = append(modes, uint8(packet.AEADModeOCB))
+ }
+
+ // For preferred (AES256, GCM), we'll generate (AES256, GCM), (AES256, OCB), (AES128, GCM), (AES128, OCB)
+ for _, cipher := range selfSignature.PreferredSymmetric {
+ for _, mode := range modes {
+ selfSignature.PreferredCipherSuites = append(selfSignature.PreferredCipherSuites, [2]uint8{cipher, mode})
+ }
+ }
+ }
+ return nil
+}
+
+func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32, writeProperties bool) error {
+ uid := packet.NewUserId(name, comment, email)
+ if uid == nil {
+ return errors.InvalidArgumentError("user id field contained invalid characters")
+ }
+
+ if _, ok := t.Identities[uid.Id]; ok {
+ return errors.InvalidArgumentError("user id exist")
}
- // For preferred (AES256, GCM), we'll generate (AES256, GCM), (AES256, OCB), (AES128, GCM), (AES128, OCB)
- for _, cipher := range selfSignature.PreferredSymmetric {
- for _, mode := range modes {
- selfSignature.PreferredCipherSuites = append(selfSignature.PreferredCipherSuites, [2]uint8{cipher, mode})
+ primary := t.PrivateKey
+ isPrimaryId := len(t.Identities) == 0
+ selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypePositiveCert, config)
+ if writeProperties {
+ err := writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
+ if err != nil {
+ return err
}
}
+ selfSignature.IsPrimaryId = &isPrimaryId
// User ID binding signature
err := selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config)
@@ -158,8 +193,10 @@ func (e *Entity) AddSigningSubkey(config *packet.Config) error {
}
sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw)
sub.IsSubkey = true
- if config != nil && config.V5Keys {
- sub.UpgradeToV5()
+ if config.V6() {
+ if err := sub.UpgradeToV6(); err != nil {
+ return err
+ }
}
subkey := Subkey{
@@ -203,8 +240,10 @@ func (e *Entity) addEncryptionSubkey(config *packet.Config, creationTime time.Ti
}
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
sub.IsSubkey = true
- if config != nil && config.V5Keys {
- sub.UpgradeToV5()
+ if config.V6() {
+ if err := sub.UpgradeToV6(); err != nil {
+ return err
+ }
}
subkey := Subkey{
@@ -242,6 +281,11 @@ func newSigner(config *packet.Config) (signer interface{}, err error) {
}
return rsa.GenerateKey(config.Random(), bits)
case packet.PubKeyAlgoEdDSA:
+ if config.V6() {
+ // Implementations MUST NOT accept or generate v6 key material
+ // using the deprecated OIDs.
+ return nil, errors.InvalidArgumentError("EdDSALegacy cannot be used for v6 keys")
+ }
curve := ecc.FindEdDSAByGenName(string(config.CurveName()))
if curve == nil {
return nil, errors.InvalidArgumentError("unsupported curve")
@@ -263,6 +307,18 @@ func newSigner(config *packet.Config) (signer interface{}, err error) {
return nil, err
}
return priv, nil
+ case packet.PubKeyAlgoEd25519:
+ priv, err := ed25519.GenerateKey(config.Random())
+ if err != nil {
+ return nil, err
+ }
+ return priv, nil
+ case packet.PubKeyAlgoEd448:
+ priv, err := ed448.GenerateKey(config.Random())
+ if err != nil {
+ return nil, err
+ }
+ return priv, nil
default:
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
}
@@ -285,6 +341,13 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
case packet.PubKeyAlgoEdDSA, packet.PubKeyAlgoECDSA:
fallthrough // When passing EdDSA or ECDSA, we generate an ECDH subkey
case packet.PubKeyAlgoECDH:
+ if config.V6() &&
+ (config.CurveName() == packet.Curve25519 ||
+ config.CurveName() == packet.Curve448) {
+ // Implementations MUST NOT accept or generate v6 key material
+ // using the deprecated OIDs.
+ return nil, errors.InvalidArgumentError("ECDH with Curve25519/448 legacy cannot be used for v6 keys")
+ }
var kdf = ecdh.KDF{
Hash: algorithm.SHA512,
Cipher: algorithm.AES256,
@@ -294,6 +357,10 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
return nil, errors.InvalidArgumentError("unsupported curve")
}
return ecdh.GenerateKey(config.Random(), curve, kdf)
+ case packet.PubKeyAlgoEd25519, packet.PubKeyAlgoX25519: // When passing Ed25519, we generate an x25519 subkey
+ return x25519.GenerateKey(config.Random())
+ case packet.PubKeyAlgoEd448, packet.PubKeyAlgoX448: // When passing Ed448, we generate an x448 subkey
+ return x448.GenerateKey(config.Random())
default:
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
}
@@ -302,7 +369,7 @@ func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
var bigOne = big.NewInt(1)
// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the
-// given bit size, using the given random source and prepopulated primes.
+// given bit size, using the given random source and pre-populated primes.
func generateRSAKeyWithPrimes(random io.Reader, nprimes int, bits int, prepopulatedPrimes []*big.Int) (*rsa.PrivateKey, error) {
priv := new(rsa.PrivateKey)
priv.E = 65537
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
index 2d7b0cf3..a071353e 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
@@ -6,6 +6,7 @@ package openpgp
import (
goerrors "errors"
+ "fmt"
"io"
"time"
@@ -24,11 +25,13 @@ var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
// (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
+ PrimaryKey *packet.PublicKey
+ PrivateKey *packet.PrivateKey
+ Identities map[string]*Identity // indexed by Identity.Name
+ Revocations []*packet.Signature
+ Subkeys []Subkey
+ SelfSignature *packet.Signature // Direct-key self signature of the PrimaryKey (contains primary key properties in v6)
+ Signatures []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures
}
// An Identity represents an identity claimed by an Entity and zero or more
@@ -120,12 +123,12 @@ func shouldPreferIdentity(existingId, potentialNewId *Identity) bool {
// given Entity.
func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
// Fail to find any encryption key if the...
- i := e.PrimaryIdentity()
- if e.PrimaryKey.KeyExpired(i.SelfSignature, now) || // primary key has expired
- i.SelfSignature == nil || // user ID has no self-signature
- i.SelfSignature.SigExpired(now) || // user ID self-signature has expired
+ primarySelfSignature, primaryIdentity := e.PrimarySelfSignature()
+ if primarySelfSignature == nil || // no self-signature found
+ e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired
e.Revoked(now) || // primary key has been revoked
- i.Revoked(now) { // user ID has been revoked
+ primarySelfSignature.SigExpired(now) || // user ID or or direct self-signature has expired
+ (primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys)
return Key{}, false
}
@@ -152,9 +155,9 @@ func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
// If we don't have any subkeys for encryption and the primary key
// is marked as OK to encrypt with, then we can use it.
- if i.SelfSignature.FlagsValid && i.SelfSignature.FlagEncryptCommunications &&
+ if primarySelfSignature.FlagsValid && primarySelfSignature.FlagEncryptCommunications &&
e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
- return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
+ return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true
}
return Key{}, false
@@ -186,12 +189,12 @@ func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key, bool) {
// Fail to find any signing key if the...
- i := e.PrimaryIdentity()
- if e.PrimaryKey.KeyExpired(i.SelfSignature, now) || // primary key has expired
- i.SelfSignature == nil || // user ID has no self-signature
- i.SelfSignature.SigExpired(now) || // user ID self-signature has expired
+ primarySelfSignature, primaryIdentity := e.PrimarySelfSignature()
+ if primarySelfSignature == nil || // no self-signature found
+ e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired
e.Revoked(now) || // primary key has been revoked
- i.Revoked(now) { // user ID has been revoked
+ primarySelfSignature.SigExpired(now) || // user ID or direct self-signature has expired
+ (primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys)
return Key{}, false
}
@@ -220,12 +223,12 @@ func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key,
// If we don't have any subkeys for signing and the primary key
// is marked as OK to sign with, then we can use it.
- if i.SelfSignature.FlagsValid &&
- (flags&packet.KeyFlagCertify == 0 || i.SelfSignature.FlagCertify) &&
- (flags&packet.KeyFlagSign == 0 || i.SelfSignature.FlagSign) &&
+ if primarySelfSignature.FlagsValid &&
+ (flags&packet.KeyFlagCertify == 0 || primarySelfSignature.FlagCertify) &&
+ (flags&packet.KeyFlagSign == 0 || primarySelfSignature.FlagSign) &&
e.PrimaryKey.PubKeyAlgo.CanSign() &&
(id == 0 || e.PrimaryKey.KeyId == id) {
- return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
+ return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true
}
// No keys with a valid Signing Flag or no keys matched the id passed in
@@ -259,7 +262,7 @@ func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) er
var keysToEncrypt []*packet.PrivateKey
// Add entity private key to encrypt.
if e.PrivateKey != nil && !e.PrivateKey.Dummy() && !e.PrivateKey.Encrypted {
- keysToEncrypt = append(keysToEncrypt, e.PrivateKey)
+ keysToEncrypt = append(keysToEncrypt, e.PrivateKey)
}
// Add subkeys to encrypt.
@@ -271,7 +274,7 @@ func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) er
return packet.EncryptPrivateKeys(keysToEncrypt, passphrase, config)
}
-// DecryptPrivateKeys decrypts all encrypted keys in the entitiy with the given passphrase.
+// DecryptPrivateKeys decrypts all encrypted keys in the entity with the given passphrase.
// Avoids recomputation of similar s2k key derivations. Public keys and dummy keys are ignored,
// and don't cause an error to be returned.
func (e *Entity) DecryptPrivateKeys(passphrase []byte) error {
@@ -284,7 +287,7 @@ func (e *Entity) DecryptPrivateKeys(passphrase []byte) error {
// Add subkeys to decrypt.
for _, sub := range e.Subkeys {
if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && sub.PrivateKey.Encrypted {
- keysToDecrypt = append(keysToDecrypt, sub.PrivateKey)
+ keysToDecrypt = append(keysToDecrypt, sub.PrivateKey)
}
}
return packet.DecryptPrivateKeys(keysToDecrypt, passphrase)
@@ -318,8 +321,7 @@ type EntityList []*Entity
func (el EntityList) KeysById(id uint64) (keys []Key) {
for _, e := range el {
if e.PrimaryKey.KeyId == id {
- ident := e.PrimaryIdentity()
- selfSig := ident.SelfSignature
+ selfSig, _ := e.PrimarySelfSignature()
keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, e.Revocations})
}
@@ -441,7 +443,6 @@ func readToNextPublicKey(packets *packet.Reader) (err error) {
return
} else if err != nil {
if _, ok := err.(errors.UnsupportedError); ok {
- err = nil
continue
}
return
@@ -479,6 +480,7 @@ func ReadEntity(packets *packet.Reader) (*Entity, error) {
}
var revocations []*packet.Signature
+ var directSignatures []*packet.Signature
EachPacket:
for {
p, err := packets.Next()
@@ -497,9 +499,7 @@ EachPacket:
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).
+ directSignatures = append(directSignatures, pkt)
}
// Else, ignoring the signature as it does not follow anything
// we would know to attach it to.
@@ -522,12 +522,39 @@ EachPacket:
return nil, err
}
default:
- // we ignore unknown packets
+ // we ignore unknown packets.
}
}
- if len(e.Identities) == 0 {
- return nil, errors.StructuralError("entity without any identities")
+ if len(e.Identities) == 0 && e.PrimaryKey.Version < 6 {
+ return nil, errors.StructuralError(fmt.Sprintf("v%d entity without any identities", e.PrimaryKey.Version))
+ }
+
+ // An implementation MUST ensure that a valid direct-key signature is present before using a v6 key.
+ if e.PrimaryKey.Version == 6 {
+ if len(directSignatures) == 0 {
+ return nil, errors.StructuralError("v6 entity without a valid direct-key signature")
+ }
+ // Select main direct key signature.
+ var mainDirectKeySelfSignature *packet.Signature
+ for _, directSignature := range directSignatures {
+ if directSignature.SigType == packet.SigTypeDirectSignature &&
+ directSignature.CheckKeyIdOrFingerprint(e.PrimaryKey) &&
+ (mainDirectKeySelfSignature == nil ||
+ directSignature.CreationTime.After(mainDirectKeySelfSignature.CreationTime)) {
+ mainDirectKeySelfSignature = directSignature
+ }
+ }
+ if mainDirectKeySelfSignature == nil {
+ return nil, errors.StructuralError("no valid direct-key self-signature for v6 primary key found")
+ }
+ // Check that the main self-signature is valid.
+ err = e.PrimaryKey.VerifyDirectKeySignature(mainDirectKeySelfSignature)
+ if err != nil {
+ return nil, errors.StructuralError("invalid direct-key self-signature for v6 primary key")
+ }
+ e.SelfSignature = mainDirectKeySelfSignature
+ e.Signatures = directSignatures
}
for _, revocation := range revocations {
@@ -672,6 +699,12 @@ func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign boo
return err
}
}
+ for _, directSignature := range e.Signatures {
+ err := directSignature.Serialize(w)
+ if err != nil {
+ return err
+ }
+ }
for _, ident := range e.Identities {
err = ident.UserId.Serialize(w)
if err != nil {
@@ -738,6 +771,12 @@ func (e *Entity) Serialize(w io.Writer) error {
return err
}
}
+ for _, directSignature := range e.Signatures {
+ err := directSignature.Serialize(w)
+ if err != nil {
+ return err
+ }
+ }
for _, ident := range e.Identities {
err = ident.UserId.Serialize(w)
if err != nil {
@@ -840,3 +879,23 @@ func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, rea
sk.Revocations = append(sk.Revocations, revSig)
return nil
}
+
+func (e *Entity) primaryDirectSignature() *packet.Signature {
+ return e.SelfSignature
+}
+
+// PrimarySelfSignature searches the entity for the self-signature that stores key preferences.
+// For V4 keys, returns the self-signature of the primary identity, and the identity.
+// For V6 keys, returns the latest valid direct-key self-signature, and no identity (nil).
+// This self-signature is to be used to check the key expiration,
+// algorithm preferences, and so on.
+func (e *Entity) PrimarySelfSignature() (*packet.Signature, *Identity) {
+ if e.PrimaryKey.Version == 6 {
+ return e.primaryDirectSignature(), nil
+ }
+ primaryIdentity := e.PrimaryIdentity()
+ if primaryIdentity == nil {
+ return nil, nil
+ }
+ return primaryIdentity.SelfSignature, primaryIdentity
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
index cee83bdc..2eecd062 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
@@ -88,17 +88,20 @@ func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
if errRead != nil && errRead != io.EOF {
return 0, errRead
}
- decrypted, errChunk := ar.openChunk(cipherChunk)
- if errChunk != nil {
- return 0, errChunk
- }
- // Return decrypted bytes, buffering if necessary
- if len(dst) < len(decrypted) {
- n = copy(dst, decrypted[:len(dst)])
- ar.buffer.Write(decrypted[len(dst):])
- } else {
- n = copy(dst, decrypted)
+ if len(cipherChunk) > 0 {
+ decrypted, errChunk := ar.openChunk(cipherChunk)
+ if errChunk != nil {
+ return 0, errChunk
+ }
+
+ // Return decrypted bytes, buffering if necessary
+ if len(dst) < len(decrypted) {
+ n = copy(dst, decrypted[:len(dst)])
+ ar.buffer.Write(decrypted[len(dst):])
+ } else {
+ n = copy(dst, decrypted)
+ }
}
// Check final authentication tag
@@ -116,6 +119,12 @@ func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
// checked in the last Read call. In the future, this function could be used to
// wipe the reader and peeked, decrypted bytes, if necessary.
func (ar *aeadDecrypter) Close() (err error) {
+ if !ar.eof {
+ errChunk := ar.validateFinalTag(ar.peekedBytes)
+ if errChunk != nil {
+ return errChunk
+ }
+ }
return nil
}
@@ -138,7 +147,7 @@ func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) {
nonce := ar.computeNextNonce()
plainChunk, err := ar.aead.Open(nil, nonce, chunk, adata)
if err != nil {
- return nil, err
+ return nil, errors.ErrAEADTagVerification
}
ar.bytesProcessed += len(plainChunk)
if err = ar.aeadCrypter.incrementIndex(); err != nil {
@@ -163,9 +172,8 @@ func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
// ... and total number of encrypted octets
adata = append(adata, amountBytes...)
nonce := ar.computeNextNonce()
- _, err := ar.aead.Open(nil, nonce, tag, adata)
- if err != nil {
- return err
+ if _, err := ar.aead.Open(nil, nonce, tag, adata); err != nil {
+ return errors.ErrAEADTagVerification
}
return nil
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
index 2f5cad71..0bcb38ca 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
@@ -8,9 +8,10 @@ import (
"compress/bzip2"
"compress/flate"
"compress/zlib"
- "github.com/ProtonMail/go-crypto/openpgp/errors"
"io"
"strconv"
+
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
)
// Compressed represents a compressed OpenPGP packet. The decompressed contents
@@ -39,6 +40,37 @@ type CompressionConfig struct {
Level int
}
+// decompressionReader ensures that the whole compression packet is read.
+type decompressionReader struct {
+ compressed io.Reader
+ decompressed io.ReadCloser
+ readAll bool
+}
+
+func newDecompressionReader(r io.Reader, decompressor io.ReadCloser) *decompressionReader {
+ return &decompressionReader{
+ compressed: r,
+ decompressed: decompressor,
+ }
+}
+
+func (dr *decompressionReader) Read(data []byte) (n int, err error) {
+ if dr.readAll {
+ return 0, io.EOF
+ }
+ n, err = dr.decompressed.Read(data)
+ if err == io.EOF {
+ dr.readAll = true
+ // Close the decompressor.
+ if errDec := dr.decompressed.Close(); errDec != nil {
+ return n, errDec
+ }
+ // Consume all remaining data from the compressed packet.
+ consumeAll(dr.compressed)
+ }
+ return n, err
+}
+
func (c *Compressed) parse(r io.Reader) error {
var buf [1]byte
_, err := readFull(r, buf[:])
@@ -50,11 +82,15 @@ func (c *Compressed) parse(r io.Reader) error {
case 0:
c.Body = r
case 1:
- c.Body = flate.NewReader(r)
+ c.Body = newDecompressionReader(r, flate.NewReader(r))
case 2:
- c.Body, err = zlib.NewReader(r)
+ decompressor, err := zlib.NewReader(r)
+ if err != nil {
+ return err
+ }
+ c.Body = newDecompressionReader(r, decompressor)
case 3:
- c.Body = bzip2.NewReader(r)
+ c.Body = newDecompressionReader(r, io.NopCloser(bzip2.NewReader(r)))
default:
err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
index 04994bec..8bf8e6e5 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
@@ -14,6 +14,34 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/s2k"
)
+var (
+ defaultRejectPublicKeyAlgorithms = map[PublicKeyAlgorithm]bool{
+ PubKeyAlgoElGamal: true,
+ PubKeyAlgoDSA: true,
+ }
+ defaultRejectHashAlgorithms = map[crypto.Hash]bool{
+ crypto.MD5: true,
+ crypto.RIPEMD160: true,
+ }
+ defaultRejectMessageHashAlgorithms = map[crypto.Hash]bool{
+ crypto.SHA1: true,
+ crypto.MD5: true,
+ crypto.RIPEMD160: true,
+ }
+ defaultRejectCurves = map[Curve]bool{
+ CurveSecP256k1: true,
+ }
+)
+
+// A global feature flag to indicate v5 support.
+// Can be set via a build tag, e.g.: `go build -tags v5 ./...`
+// If the build tag is missing config_v5.go will set it to true.
+//
+// Disables parsing of v5 keys and v5 signatures.
+// These are non-standard entities, which in the crypto-refresh have been superseded
+// by v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively.
+var V5Disabled = false
+
// Config collects a number of parameters along with sensible defaults.
// A nil *Config is valid and results in all default values.
type Config struct {
@@ -73,9 +101,16 @@ type Config struct {
// **Note: using this option may break compatibility with other OpenPGP
// implementations, as well as future versions of this library.**
AEADConfig *AEADConfig
- // V5Keys configures version 5 key generation. If false, this package still
- // supports version 5 keys, but produces version 4 keys.
- V5Keys bool
+ // V6Keys configures version 6 key generation. If false, this package still
+ // supports version 6 keys, but produces version 4 keys.
+ V6Keys bool
+ // Minimum RSA key size allowed for key generation and message signing, verification and encryption.
+ MinRSABits uint16
+ // Reject insecure algorithms, only works with v2 api
+ RejectPublicKeyAlgorithms map[PublicKeyAlgorithm]bool
+ RejectHashAlgorithms map[crypto.Hash]bool
+ RejectMessageHashAlgorithms map[crypto.Hash]bool
+ RejectCurves map[Curve]bool
// "The validity period of the key. This is the number of seconds after
// the key creation time that the key expires. If this is not present
// or has a value of zero, the key never expires. This is found only on
@@ -104,12 +139,40 @@ type Config struct {
// might be no other way than to tolerate the missing MDC. Setting this flag, allows this
// mode of operation. It should be considered a measure of last resort.
InsecureAllowUnauthenticatedMessages bool
+ // InsecureAllowDecryptionWithSigningKeys allows decryption with keys marked as signing keys in the v2 API.
+ // This setting is potentially insecure, but it is needed as some libraries
+ // ignored key flags when selecting a key for encryption.
+ // Not relevant for the v1 API, as all keys were allowed in decryption.
+ InsecureAllowDecryptionWithSigningKeys bool
// KnownNotations is a map of Notation Data names to bools, which controls
// the notation names that are allowed to be present in critical Notation Data
// signature subpackets.
KnownNotations map[string]bool
// SignatureNotations is a list of Notations to be added to any signatures.
SignatureNotations []*Notation
+ // CheckIntendedRecipients controls, whether the OpenPGP Intended Recipient Fingerprint feature
+ // should be enabled for encryption and decryption.
+ // (See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr).
+ // When the flag is set, encryption produces Intended Recipient Fingerprint signature sub-packets and decryption
+ // checks whether the key it was encrypted to is one of the included fingerprints in the signature.
+ // If the flag is disabled, no Intended Recipient Fingerprint sub-packets are created or checked.
+ // The default behavior, when the config or flag is nil, is to enable the feature.
+ CheckIntendedRecipients *bool
+ // CacheSessionKey controls if decryption should return the session key used for decryption.
+ // If the flag is set, the session key is cached in the message details struct.
+ CacheSessionKey bool
+ // CheckPacketSequence is a flag that controls if the pgp message reader should strictly check
+ // that the packet sequence conforms with the grammar mandated by rfc4880.
+ // The default behavior, when the config or flag is nil, is to check the packet sequence.
+ CheckPacketSequence *bool
+ // NonDeterministicSignaturesViaNotation is a flag to enable randomization of signatures.
+ // If true, a salt notation is used to randomize signatures generated by v4 and v5 keys
+ // (v6 signatures are always non-deterministic, by design).
+ // This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
+ // during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
+ // weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
+ // The default behavior, when the config or flag is nil, is to enable the feature.
+ NonDeterministicSignaturesViaNotation *bool
}
func (c *Config) Random() io.Reader {
@@ -197,7 +260,7 @@ func (c *Config) S2K() *s2k.Config {
return nil
}
// for backwards compatibility
- if c != nil && c.S2KCount > 0 && c.S2KConfig == nil {
+ if c.S2KCount > 0 && c.S2KConfig == nil {
return &s2k.Config{
S2KCount: c.S2KCount,
}
@@ -233,6 +296,13 @@ func (c *Config) AllowUnauthenticatedMessages() bool {
return c.InsecureAllowUnauthenticatedMessages
}
+func (c *Config) AllowDecryptionWithSigningKeys() bool {
+ if c == nil {
+ return false
+ }
+ return c.InsecureAllowDecryptionWithSigningKeys
+}
+
func (c *Config) KnownNotation(notationName string) bool {
if c == nil {
return false
@@ -246,3 +316,95 @@ func (c *Config) Notations() []*Notation {
}
return c.SignatureNotations
}
+
+func (c *Config) V6() bool {
+ if c == nil {
+ return false
+ }
+ return c.V6Keys
+}
+
+func (c *Config) IntendedRecipients() bool {
+ if c == nil || c.CheckIntendedRecipients == nil {
+ return true
+ }
+ return *c.CheckIntendedRecipients
+}
+
+func (c *Config) RetrieveSessionKey() bool {
+ if c == nil {
+ return false
+ }
+ return c.CacheSessionKey
+}
+
+func (c *Config) MinimumRSABits() uint16 {
+ if c == nil || c.MinRSABits == 0 {
+ return 2047
+ }
+ return c.MinRSABits
+}
+
+func (c *Config) RejectPublicKeyAlgorithm(alg PublicKeyAlgorithm) bool {
+ var rejectedAlgorithms map[PublicKeyAlgorithm]bool
+ if c == nil || c.RejectPublicKeyAlgorithms == nil {
+ // Default
+ rejectedAlgorithms = defaultRejectPublicKeyAlgorithms
+ } else {
+ rejectedAlgorithms = c.RejectPublicKeyAlgorithms
+ }
+ return rejectedAlgorithms[alg]
+}
+
+func (c *Config) RejectHashAlgorithm(hash crypto.Hash) bool {
+ var rejectedAlgorithms map[crypto.Hash]bool
+ if c == nil || c.RejectHashAlgorithms == nil {
+ // Default
+ rejectedAlgorithms = defaultRejectHashAlgorithms
+ } else {
+ rejectedAlgorithms = c.RejectHashAlgorithms
+ }
+ return rejectedAlgorithms[hash]
+}
+
+func (c *Config) RejectMessageHashAlgorithm(hash crypto.Hash) bool {
+ var rejectedAlgorithms map[crypto.Hash]bool
+ if c == nil || c.RejectMessageHashAlgorithms == nil {
+ // Default
+ rejectedAlgorithms = defaultRejectMessageHashAlgorithms
+ } else {
+ rejectedAlgorithms = c.RejectMessageHashAlgorithms
+ }
+ return rejectedAlgorithms[hash]
+}
+
+func (c *Config) RejectCurve(curve Curve) bool {
+ var rejectedCurve map[Curve]bool
+ if c == nil || c.RejectCurves == nil {
+ // Default
+ rejectedCurve = defaultRejectCurves
+ } else {
+ rejectedCurve = c.RejectCurves
+ }
+ return rejectedCurve[curve]
+}
+
+func (c *Config) StrictPacketSequence() bool {
+ if c == nil || c.CheckPacketSequence == nil {
+ return true
+ }
+ return *c.CheckPacketSequence
+}
+
+func (c *Config) RandomizeSignaturesViaNotation() bool {
+ if c == nil || c.NonDeterministicSignaturesViaNotation == nil {
+ return true
+ }
+ return *c.NonDeterministicSignaturesViaNotation
+}
+
+// BoolPointer is a helper function to set a boolean pointer in the Config.
+// e.g., config.CheckPacketSequence = BoolPointer(true)
+func BoolPointer(value bool) *bool {
+ return &value
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go
new file mode 100644
index 00000000..f2415906
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go
@@ -0,0 +1,7 @@
+//go:build !v5
+
+package packet
+
+func init() {
+ V5Disabled = true
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
index eeff2902..b90bb289 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
@@ -5,9 +5,11 @@
package packet
import (
+ "bytes"
"crypto"
"crypto/rsa"
"encoding/binary"
+ "encoding/hex"
"io"
"math/big"
"strconv"
@@ -16,32 +18,85 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
+ "github.com/ProtonMail/go-crypto/openpgp/x25519"
+ "github.com/ProtonMail/go-crypto/openpgp/x448"
)
-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 for a v3 packet
- Key []byte // only valid after a successful Decrypt
+ Version int
+ KeyId uint64
+ KeyVersion int // v6
+ KeyFingerprint []byte // v6
+ Algo PublicKeyAlgorithm
+ CipherFunc CipherFunction // only valid after a successful Decrypt for a v3 packet
+ Key []byte // only valid after a successful Decrypt
encryptedMPI1, encryptedMPI2 encoding.Field
+ ephemeralPublicX25519 *x25519.PublicKey // used for x25519
+ ephemeralPublicX448 *x448.PublicKey // used for x448
+ encryptedSession []byte // used for x25519 and x448
}
func (e *EncryptedKey) parse(r io.Reader) (err error) {
- var buf [10]byte
- _, err = readFull(r, buf[:])
+ var buf [8]byte
+ _, err = readFull(r, buf[:versionSize])
if err != nil {
return
}
- if buf[0] != encryptedKeyVersion {
+ e.Version = int(buf[0])
+ if e.Version != 3 && e.Version != 6 {
return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
}
- e.KeyId = binary.BigEndian.Uint64(buf[1:9])
- e.Algo = PublicKeyAlgorithm(buf[9])
+ if e.Version == 6 {
+ //Read a one-octet size of the following two fields.
+ if _, err = readFull(r, buf[:1]); err != nil {
+ return
+ }
+ // The size may also be zero, and the key version and
+ // fingerprint omitted for an "anonymous recipient"
+ if buf[0] != 0 {
+ // non-anonymous case
+ _, err = readFull(r, buf[:versionSize])
+ if err != nil {
+ return
+ }
+ e.KeyVersion = int(buf[0])
+ if e.KeyVersion != 4 && e.KeyVersion != 6 {
+ return errors.UnsupportedError("unknown public key version " + strconv.Itoa(e.KeyVersion))
+ }
+ var fingerprint []byte
+ if e.KeyVersion == 6 {
+ fingerprint = make([]byte, fingerprintSizeV6)
+ } else if e.KeyVersion == 4 {
+ fingerprint = make([]byte, fingerprintSize)
+ }
+ _, err = readFull(r, fingerprint)
+ if err != nil {
+ return
+ }
+ e.KeyFingerprint = fingerprint
+ if e.KeyVersion == 6 {
+ e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[:keyIdSize])
+ } else if e.KeyVersion == 4 {
+ e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[fingerprintSize-keyIdSize : fingerprintSize])
+ }
+ }
+ } else {
+ _, err = readFull(r, buf[:8])
+ if err != nil {
+ return
+ }
+ e.KeyId = binary.BigEndian.Uint64(buf[:keyIdSize])
+ }
+
+ _, err = readFull(r, buf[:1])
+ if err != nil {
+ return
+ }
+ e.Algo = PublicKeyAlgorithm(buf[0])
+ var cipherFunction byte
switch e.Algo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
e.encryptedMPI1 = new(encoding.MPI)
@@ -68,26 +123,39 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) {
if _, err = e.encryptedMPI2.ReadFrom(r); err != nil {
return
}
+ case PubKeyAlgoX25519:
+ e.ephemeralPublicX25519, e.encryptedSession, cipherFunction, err = x25519.DecodeFields(r, e.Version == 6)
+ if err != nil {
+ return
+ }
+ case PubKeyAlgoX448:
+ e.ephemeralPublicX448, e.encryptedSession, cipherFunction, err = x448.DecodeFields(r, e.Version == 6)
+ if err != nil {
+ return
+ }
+ }
+ if e.Version < 6 {
+ switch e.Algo {
+ case PubKeyAlgoX25519, PubKeyAlgoX448:
+ e.CipherFunc = CipherFunction(cipherFunction)
+ // Check for validiy is in the Decrypt method
+ }
}
+
_, 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 {
- if e.KeyId != 0 && e.KeyId != priv.KeyId {
+ if e.Version < 6 && e.KeyId != 0 && e.KeyId != priv.KeyId {
return errors.InvalidArgumentError("cannot decrypt encrypted session key for key id " + strconv.FormatUint(e.KeyId, 16) + " with private key id " + strconv.FormatUint(priv.KeyId, 16))
}
+ if e.Version == 6 && e.KeyVersion != 0 && !bytes.Equal(e.KeyFingerprint, priv.Fingerprint) {
+ return errors.InvalidArgumentError("cannot decrypt encrypted session key for key fingerprint " + hex.EncodeToString(e.KeyFingerprint) + " with private key fingerprint " + hex.EncodeToString(priv.Fingerprint))
+ }
if e.Algo != priv.PubKeyAlgo {
return errors.InvalidArgumentError("cannot decrypt encrypted session key of type " + strconv.Itoa(int(e.Algo)) + " with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
}
@@ -113,52 +181,116 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
vsG := e.encryptedMPI1.Bytes()
m := e.encryptedMPI2.Bytes()
oid := priv.PublicKey.oid.EncodedBytes()
- b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, priv.PublicKey.Fingerprint[:])
+ fp := priv.PublicKey.Fingerprint[:]
+ if priv.PublicKey.Version == 5 {
+ // For v5 the, the fingerprint must be restricted to 20 bytes
+ fp = fp[:20]
+ }
+ b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, fp)
+ case PubKeyAlgoX25519:
+ b, err = x25519.Decrypt(priv.PrivateKey.(*x25519.PrivateKey), e.ephemeralPublicX25519, e.encryptedSession)
+ case PubKeyAlgoX448:
+ b, err = x448.Decrypt(priv.PrivateKey.(*x448.PrivateKey), e.ephemeralPublicX448, e.encryptedSession)
default:
err = errors.InvalidArgumentError("cannot decrypt encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
}
-
if err != nil {
return err
}
- e.CipherFunc = CipherFunction(b[0])
- if !e.CipherFunc.IsSupported() {
- return errors.UnsupportedError("unsupported encryption function")
- }
-
- e.Key = b[1 : len(b)-2]
- expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
- checksum := checksumKeyMaterial(e.Key)
- if checksum != expectedChecksum {
- return errors.StructuralError("EncryptedKey checksum incorrect")
+ var key []byte
+ switch priv.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
+ keyOffset := 0
+ if e.Version < 6 {
+ e.CipherFunc = CipherFunction(b[0])
+ keyOffset = 1
+ if !e.CipherFunc.IsSupported() {
+ return errors.UnsupportedError("unsupported encryption function")
+ }
+ }
+ key, err = decodeChecksumKey(b[keyOffset:])
+ if err != nil {
+ return err
+ }
+ case PubKeyAlgoX25519, PubKeyAlgoX448:
+ if e.Version < 6 {
+ switch e.CipherFunc {
+ case CipherAES128, CipherAES192, CipherAES256:
+ break
+ default:
+ return errors.StructuralError("v3 PKESK mandates AES as cipher function for x25519 and x448")
+ }
+ }
+ key = b[:]
+ default:
+ return errors.UnsupportedError("unsupported algorithm for decryption")
}
-
+ e.Key = key
return nil
}
// Serialize writes the encrypted key packet, e, to w.
func (e *EncryptedKey) Serialize(w io.Writer) error {
- var mpiLen int
+ var encodedLength int
switch e.Algo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
- mpiLen = int(e.encryptedMPI1.EncodedLength())
+ encodedLength = int(e.encryptedMPI1.EncodedLength())
case PubKeyAlgoElGamal:
- mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
+ encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
case PubKeyAlgoECDH:
- mpiLen = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
+ encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
+ case PubKeyAlgoX25519:
+ encodedLength = x25519.EncodedFieldsLength(e.encryptedSession, e.Version == 6)
+ case PubKeyAlgoX448:
+ encodedLength = x448.EncodedFieldsLength(e.encryptedSession, e.Version == 6)
default:
return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
}
- err := serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
+ packetLen := versionSize /* version */ + keyIdSize /* key id */ + algorithmSize /* algo */ + encodedLength
+ if e.Version == 6 {
+ packetLen = versionSize /* version */ + algorithmSize /* algo */ + encodedLength + keyVersionSize /* key version */
+ if e.KeyVersion == 6 {
+ packetLen += fingerprintSizeV6
+ } else if e.KeyVersion == 4 {
+ packetLen += fingerprintSize
+ }
+ }
+
+ err := serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
return err
}
- w.Write([]byte{encryptedKeyVersion})
- binary.Write(w, binary.BigEndian, e.KeyId)
- w.Write([]byte{byte(e.Algo)})
+ _, err = w.Write([]byte{byte(e.Version)})
+ if err != nil {
+ return err
+ }
+ if e.Version == 6 {
+ _, err = w.Write([]byte{byte(e.KeyVersion)})
+ if err != nil {
+ return err
+ }
+ // The key version number may also be zero,
+ // and the fingerprint omitted
+ if e.KeyVersion != 0 {
+ _, err = w.Write(e.KeyFingerprint)
+ if err != nil {
+ return err
+ }
+ }
+ } else {
+ // Write KeyID
+ err = binary.Write(w, binary.BigEndian, e.KeyId)
+ if err != nil {
+ return err
+ }
+ }
+ _, err = w.Write([]byte{byte(e.Algo)})
+ if err != nil {
+ return err
+ }
switch e.Algo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
@@ -176,34 +308,115 @@ func (e *EncryptedKey) Serialize(w io.Writer) error {
}
_, err := w.Write(e.encryptedMPI2.EncodedBytes())
return err
+ case PubKeyAlgoX25519:
+ err := x25519.EncodeFields(w, e.ephemeralPublicX25519, e.encryptedSession, byte(e.CipherFunc), e.Version == 6)
+ return err
+ case PubKeyAlgoX448:
+ err := x448.EncodeFields(w, e.ephemeralPublicX448, e.encryptedSession, byte(e.CipherFunc), e.Version == 6)
+ return err
default:
panic("internal error")
}
}
-// SerializeEncryptedKey serializes an encrypted key packet to w that contains
+// SerializeEncryptedKeyAEAD serializes an encrypted key packet to w that contains
// key, encrypted to pub.
+// If aeadSupported is set, PKESK v6 is used, otherwise v3.
+// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
// 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)
+func SerializeEncryptedKeyAEAD(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, config *Config) error {
+ return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, aeadSupported, key, false, config)
+}
+
+// SerializeEncryptedKeyAEADwithHiddenOption serializes an encrypted key packet to w that contains
+// key, encrypted to pub.
+// Offers the hidden flag option to indicated if the PKESK packet should include a wildcard KeyID.
+// If aeadSupported is set, PKESK v6 is used, otherwise v3.
+// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
+// If config is nil, sensible defaults will be used.
+func SerializeEncryptedKeyAEADwithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, hidden bool, config *Config) error {
+ var buf [36]byte // max possible header size is v6
+ lenHeaderWritten := versionSize
+ version := 3
+
+ if aeadSupported {
+ version = 6
+ }
+ // An implementation MUST NOT generate ElGamal v6 PKESKs.
+ if version == 6 && pub.PubKeyAlgo == PubKeyAlgoElGamal {
+ return errors.InvalidArgumentError("ElGamal v6 PKESK are not allowed")
+ }
+ // In v3 PKESKs, for x25519 and x448, mandate using AES
+ if version == 3 && (pub.PubKeyAlgo == PubKeyAlgoX25519 || pub.PubKeyAlgo == PubKeyAlgoX448) {
+ switch cipherFunc {
+ case CipherAES128, CipherAES192, CipherAES256:
+ break
+ default:
+ return errors.InvalidArgumentError("v3 PKESK mandates AES for x25519 and x448")
+ }
+ }
+
+ buf[0] = byte(version)
+
+ // If hidden is set, the key should be hidden
+ // An implementation MAY accept or use a Key ID of all zeros,
+ // or a key version of zero and no key fingerprint, to hide the intended decryption key.
+ // See Section 5.1.8. in the open pgp crypto refresh
+ if version == 6 {
+ if !hidden {
+ // A one-octet size of the following two fields.
+ buf[1] = byte(keyVersionSize + len(pub.Fingerprint))
+ // A one octet key version number.
+ buf[2] = byte(pub.Version)
+ lenHeaderWritten += keyVersionSize + 1
+ // The fingerprint of the public key
+ copy(buf[lenHeaderWritten:lenHeaderWritten+len(pub.Fingerprint)], pub.Fingerprint)
+ lenHeaderWritten += len(pub.Fingerprint)
+ } else {
+ // The size may also be zero, and the key version
+ // and fingerprint omitted for an "anonymous recipient"
+ buf[1] = 0
+ lenHeaderWritten += 1
+ }
+ } else {
+ if !hidden {
+ binary.BigEndian.PutUint64(buf[versionSize:(versionSize+keyIdSize)], pub.KeyId)
+ }
+ lenHeaderWritten += keyIdSize
+ }
+ buf[lenHeaderWritten] = byte(pub.PubKeyAlgo)
+ lenHeaderWritten += algorithmSize
+
+ var keyBlock []byte
+ switch pub.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
+ lenKeyBlock := len(key) + 2
+ if version < 6 {
+ lenKeyBlock += 1 // cipher type included
+ }
+ keyBlock = make([]byte, lenKeyBlock)
+ keyOffset := 0
+ if version < 6 {
+ keyBlock[0] = byte(cipherFunc)
+ keyOffset = 1
+ }
+ encodeChecksumKey(keyBlock[keyOffset:], key)
+ case PubKeyAlgoX25519, PubKeyAlgoX448:
+ // algorithm is added in plaintext below
+ keyBlock = key
+ }
switch pub.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
- return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
+ return serializeEncryptedKeyRSA(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*rsa.PublicKey), keyBlock)
case PubKeyAlgoElGamal:
- return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
+ return serializeEncryptedKeyElGamal(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*elgamal.PublicKey), keyBlock)
case PubKeyAlgoECDH:
- return serializeEncryptedKeyECDH(w, config.Random(), buf, pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint)
+ return serializeEncryptedKeyECDH(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint)
+ case PubKeyAlgoX25519:
+ return serializeEncryptedKeyX25519(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x25519.PublicKey), keyBlock, byte(cipherFunc), version)
+ case PubKeyAlgoX448:
+ return serializeEncryptedKeyX448(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x448.PublicKey), keyBlock, byte(cipherFunc), version)
case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
}
@@ -211,14 +424,32 @@ func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunctio
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 {
+// SerializeEncryptedKey serializes an encrypted key packet to w that contains
+// key, encrypted to pub.
+// PKESKv6 is used if config.AEAD() is not nil.
+// If config is nil, sensible defaults will be used.
+// Deprecated: Use SerializeEncryptedKeyAEAD instead.
+func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
+ return SerializeEncryptedKeyAEAD(w, pub, cipherFunc, config.AEAD() != nil, key, config)
+}
+
+// SerializeEncryptedKeyWithHiddenOption serializes an encrypted key packet to w that contains
+// key, encrypted to pub. PKESKv6 is used if config.AEAD() is not nil.
+// The hidden option controls if the packet should be anonymous, i.e., omit key metadata.
+// If config is nil, sensible defaults will be used.
+// Deprecated: Use SerializeEncryptedKeyAEADwithHiddenOption instead.
+func SerializeEncryptedKeyWithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, hidden bool, config *Config) error {
+ return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, config.AEAD() != nil, key, hidden, config)
+}
+
+func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header []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())
}
cipherMPI := encoding.NewMPI(cipherText)
- packetLen := 10 /* header length */ + int(cipherMPI.EncodedLength())
+ packetLen := len(header) /* header length */ + int(cipherMPI.EncodedLength())
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
@@ -232,13 +463,13 @@ func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub
return err
}
-func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
+func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header []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 := len(header) /* header length */
packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
@@ -257,7 +488,7 @@ func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte,
return err
}
-func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error {
+func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header []byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error {
vsG, c, err := ecdh.Encrypt(rand, pub, keyBlock, oid.EncodedBytes(), fingerprint)
if err != nil {
return errors.InvalidArgumentError("ECDH encryption failed: " + err.Error())
@@ -266,7 +497,7 @@ func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub
g := encoding.NewMPI(vsG)
m := encoding.NewOID(c)
- packetLen := 10 /* header length */
+ packetLen := len(header) /* header length */
packetLen += int(g.EncodedLength()) + int(m.EncodedLength())
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
@@ -284,3 +515,70 @@ func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub
_, err = w.Write(m.EncodedBytes())
return err
}
+
+func serializeEncryptedKeyX25519(w io.Writer, rand io.Reader, header []byte, pub *x25519.PublicKey, keyBlock []byte, cipherFunc byte, version int) error {
+ ephemeralPublicX25519, ciphertext, err := x25519.Encrypt(rand, pub, keyBlock)
+ if err != nil {
+ return errors.InvalidArgumentError("x25519 encryption failed: " + err.Error())
+ }
+
+ packetLen := len(header) /* header length */
+ packetLen += x25519.EncodedFieldsLength(ciphertext, version == 6)
+
+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+ if err != nil {
+ return err
+ }
+
+ _, err = w.Write(header[:])
+ if err != nil {
+ return err
+ }
+ return x25519.EncodeFields(w, ephemeralPublicX25519, ciphertext, cipherFunc, version == 6)
+}
+
+func serializeEncryptedKeyX448(w io.Writer, rand io.Reader, header []byte, pub *x448.PublicKey, keyBlock []byte, cipherFunc byte, version int) error {
+ ephemeralPublicX448, ciphertext, err := x448.Encrypt(rand, pub, keyBlock)
+ if err != nil {
+ return errors.InvalidArgumentError("x448 encryption failed: " + err.Error())
+ }
+
+ packetLen := len(header) /* header length */
+ packetLen += x448.EncodedFieldsLength(ciphertext, version == 6)
+
+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
+ if err != nil {
+ return err
+ }
+
+ _, err = w.Write(header[:])
+ if err != nil {
+ return err
+ }
+ return x448.EncodeFields(w, ephemeralPublicX448, ciphertext, cipherFunc, version == 6)
+}
+
+func checksumKeyMaterial(key []byte) uint16 {
+ var checksum uint16
+ for _, v := range key {
+ checksum += uint16(v)
+ }
+ return checksum
+}
+
+func decodeChecksumKey(msg []byte) (key []byte, err error) {
+ key = msg[:len(msg)-2]
+ expectedChecksum := uint16(msg[len(msg)-2])<<8 | uint16(msg[len(msg)-1])
+ checksum := checksumKeyMaterial(key)
+ if checksum != expectedChecksum {
+ err = errors.StructuralError("session key checksum is incorrect")
+ }
+ return
+}
+
+func encodeChecksumKey(buffer []byte, key []byte) {
+ copy(buffer, key)
+ checksum := checksumKeyMaterial(key)
+ buffer[len(key)] = byte(checksum >> 8)
+ buffer[len(key)+1] = byte(checksum)
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go
index 4be98760..8a028c8a 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go
@@ -58,9 +58,9 @@ func (l *LiteralData) parse(r io.Reader) (err error) {
// 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'
+ buf[0] = 'b'
+ if !isBinary {
+ buf[0] = 'u'
}
if len(fileName) > 255 {
fileName = fileName[:255]
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go
new file mode 100644
index 00000000..1ee378ba
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go
@@ -0,0 +1,33 @@
+package packet
+
+import (
+ "io"
+
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+)
+
+type Marker struct{}
+
+const markerString = "PGP"
+
+// parse just checks if the packet contains "PGP".
+func (m *Marker) parse(reader io.Reader) error {
+ var buffer [3]byte
+ if _, err := io.ReadFull(reader, buffer[:]); err != nil {
+ return err
+ }
+ if string(buffer[:]) != markerString {
+ return errors.StructuralError("invalid marker packet")
+ }
+ return nil
+}
+
+// SerializeMarker writes a marker packet to writer.
+func SerializeMarker(writer io.Writer) error {
+ err := serializeHeader(writer, packetTypeMarker, len(markerString))
+ if err != nil {
+ return err
+ }
+ _, err = writer.Write([]byte(markerString))
+ return err
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
index 033fb2d7..f393c406 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
@@ -7,34 +7,37 @@ package packet
import (
"crypto"
"encoding/binary"
- "github.com/ProtonMail/go-crypto/openpgp/errors"
- "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"io"
"strconv"
+
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+ "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
)
// 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
+ Version int
+ SigType SignatureType
+ Hash crypto.Hash
+ PubKeyAlgo PublicKeyAlgorithm
+ KeyId uint64
+ IsLast bool
+ Salt []byte // v6 only
+ KeyFingerprint []byte // v6 only
}
-const onePassSignatureVersion = 3
-
func (ops *OnePassSignature) parse(r io.Reader) (err error) {
- var buf [13]byte
-
- _, err = readFull(r, buf[:])
+ var buf [8]byte
+ // Read: version | signature type | hash algorithm | public-key algorithm
+ _, err = readFull(r, buf[:4])
if err != nil {
return
}
- if buf[0] != onePassSignatureVersion {
- err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
+ if buf[0] != 3 && buf[0] != 6 {
+ return errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
}
+ ops.Version = int(buf[0])
var ok bool
ops.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2])
@@ -44,15 +47,69 @@ func (ops *OnePassSignature) parse(r io.Reader) (err error) {
ops.SigType = SignatureType(buf[1])
ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
- ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
- ops.IsLast = buf[12] != 0
+
+ if ops.Version == 6 {
+ // Only for v6, a variable-length field containing the salt
+ _, err = readFull(r, buf[:1])
+ if err != nil {
+ return
+ }
+ saltLength := int(buf[0])
+ var expectedSaltLength int
+ expectedSaltLength, err = SaltLengthForHash(ops.Hash)
+ if err != nil {
+ return
+ }
+ if saltLength != expectedSaltLength {
+ err = errors.StructuralError("unexpected salt size for the given hash algorithm")
+ return
+ }
+ salt := make([]byte, expectedSaltLength)
+ _, err = readFull(r, salt)
+ if err != nil {
+ return
+ }
+ ops.Salt = salt
+
+ // Only for v6 packets, 32 octets of the fingerprint of the signing key.
+ fingerprint := make([]byte, 32)
+ _, err = readFull(r, fingerprint)
+ if err != nil {
+ return
+ }
+ ops.KeyFingerprint = fingerprint
+ ops.KeyId = binary.BigEndian.Uint64(ops.KeyFingerprint[:8])
+ } else {
+ _, err = readFull(r, buf[:8])
+ if err != nil {
+ return
+ }
+ ops.KeyId = binary.BigEndian.Uint64(buf[:8])
+ }
+
+ _, err = readFull(r, buf[:1])
+ if err != nil {
+ return
+ }
+ ops.IsLast = buf[0] != 0
return
}
// Serialize marshals the given OnePassSignature to w.
func (ops *OnePassSignature) Serialize(w io.Writer) error {
- var buf [13]byte
- buf[0] = onePassSignatureVersion
+ //v3 length 1+1+1+1+8+1 =
+ packetLength := 13
+ if ops.Version == 6 {
+ // v6 length 1+1+1+1+1+len(salt)+32+1 =
+ packetLength = 38 + len(ops.Salt)
+ }
+
+ if err := serializeHeader(w, packetTypeOnePassSignature, packetLength); err != nil {
+ return err
+ }
+
+ var buf [8]byte
+ buf[0] = byte(ops.Version)
buf[1] = uint8(ops.SigType)
var ok bool
buf[2], ok = algorithm.HashToHashIdWithSha1(ops.Hash)
@@ -60,14 +117,41 @@ func (ops *OnePassSignature) Serialize(w io.Writer) error {
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 {
+ _, err := w.Write(buf[:4])
+ if err != nil {
return err
}
- _, err := w.Write(buf[:])
+
+ if ops.Version == 6 {
+ // write salt for v6 signatures
+ _, err := w.Write([]byte{uint8(len(ops.Salt))})
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(ops.Salt)
+ if err != nil {
+ return err
+ }
+
+ // write fingerprint v6 signatures
+ _, err = w.Write(ops.KeyFingerprint)
+ if err != nil {
+ return err
+ }
+ } else {
+ binary.BigEndian.PutUint64(buf[:8], ops.KeyId)
+ _, err := w.Write(buf[:8])
+ if err != nil {
+ return err
+ }
+ }
+
+ isLast := []byte{byte(0)}
+ if ops.IsLast {
+ isLast[0] = 1
+ }
+
+ _, err = w.Write(isLast)
return err
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
index 4f820407..cef7c661 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
@@ -7,7 +7,6 @@ package packet
import (
"bytes"
"io"
- "io/ioutil"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
@@ -26,7 +25,7 @@ type OpaquePacket struct {
}
func (op *OpaquePacket) parse(r io.Reader) (err error) {
- op.Contents, err = ioutil.ReadAll(r)
+ op.Contents, err = io.ReadAll(r)
return
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
index 4d86a7da..1e92e22c 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
@@ -311,12 +311,15 @@ const (
packetTypePrivateSubkey packetType = 7
packetTypeCompressed packetType = 8
packetTypeSymmetricallyEncrypted packetType = 9
+ packetTypeMarker packetType = 10
packetTypeLiteralData packetType = 11
+ packetTypeTrust packetType = 12
packetTypeUserId packetType = 13
packetTypePublicSubkey packetType = 14
packetTypeUserAttribute packetType = 17
packetTypeSymmetricallyEncryptedIntegrityProtected packetType = 18
packetTypeAEADEncrypted packetType = 20
+ packetPadding packetType = 21
)
// EncryptedDataPacket holds encrypted data. It is currently implemented by
@@ -328,7 +331,7 @@ type EncryptedDataPacket interface {
// 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)
+ tag, len, contents, err := readHeader(r)
if err != nil {
return
}
@@ -367,8 +370,93 @@ func Read(r io.Reader) (p Packet, err error) {
p = se
case packetTypeAEADEncrypted:
p = new(AEADEncrypted)
+ case packetPadding:
+ p = Padding(len)
+ case packetTypeMarker:
+ p = new(Marker)
+ case packetTypeTrust:
+ // Not implemented, just consume
+ err = errors.UnknownPacketTypeError(tag)
default:
+ // Packet Tags from 0 to 39 are critical.
+ // Packet Tags from 40 to 63 are non-critical.
+ if tag < 40 {
+ err = errors.CriticalUnknownPacketTypeError(tag)
+ } else {
+ err = errors.UnknownPacketTypeError(tag)
+ }
+ }
+ if p != nil {
+ err = p.parse(contents)
+ }
+ if err != nil {
+ consumeAll(contents)
+ }
+ return
+}
+
+// ReadWithCheck reads a single OpenPGP message packet from the given io.Reader. If there is an
+// error parsing a packet, the whole packet is consumed from the input.
+// ReadWithCheck additionally checks if the OpenPGP message packet sequence adheres
+// to the packet composition rules in rfc4880, if not throws an error.
+func ReadWithCheck(r io.Reader, sequence *SequenceVerifier) (p Packet, msgErr error, err error) {
+ tag, len, contents, err := readHeader(r)
+ if err != nil {
+ return
+ }
+ switch tag {
+ case packetTypeEncryptedKey:
+ msgErr = sequence.Next(ESKSymbol)
+ p = new(EncryptedKey)
+ case packetTypeSignature:
+ msgErr = sequence.Next(SigSymbol)
+ p = new(Signature)
+ case packetTypeSymmetricKeyEncrypted:
+ msgErr = sequence.Next(ESKSymbol)
+ p = new(SymmetricKeyEncrypted)
+ case packetTypeOnePassSignature:
+ msgErr = sequence.Next(OPSSymbol)
+ p = new(OnePassSignature)
+ case packetTypeCompressed:
+ msgErr = sequence.Next(CompSymbol)
+ p = new(Compressed)
+ case packetTypeSymmetricallyEncrypted:
+ msgErr = sequence.Next(EncSymbol)
+ p = new(SymmetricallyEncrypted)
+ case packetTypeLiteralData:
+ msgErr = sequence.Next(LDSymbol)
+ p = new(LiteralData)
+ case packetTypeSymmetricallyEncryptedIntegrityProtected:
+ msgErr = sequence.Next(EncSymbol)
+ se := new(SymmetricallyEncrypted)
+ se.IntegrityProtected = true
+ p = se
+ case packetTypeAEADEncrypted:
+ msgErr = sequence.Next(EncSymbol)
+ p = new(AEADEncrypted)
+ case packetPadding:
+ p = Padding(len)
+ case packetTypeMarker:
+ p = new(Marker)
+ case packetTypeTrust:
+ // Not implemented, just consume
err = errors.UnknownPacketTypeError(tag)
+ case packetTypePrivateKey,
+ packetTypePrivateSubkey,
+ packetTypePublicKey,
+ packetTypePublicSubkey,
+ packetTypeUserId,
+ packetTypeUserAttribute:
+ msgErr = sequence.Next(UnknownSymbol)
+ consumeAll(contents)
+ default:
+ // Packet Tags from 0 to 39 are critical.
+ // Packet Tags from 40 to 63 are non-critical.
+ if tag < 40 {
+ err = errors.CriticalUnknownPacketTypeError(tag)
+ } else {
+ err = errors.UnknownPacketTypeError(tag)
+ }
}
if p != nil {
err = p.parse(contents)
@@ -385,17 +473,17 @@ type SignatureType uint8
const (
SigTypeBinary SignatureType = 0x00
- SigTypeText = 0x01
- SigTypeGenericCert = 0x10
- SigTypePersonaCert = 0x11
- SigTypeCasualCert = 0x12
- SigTypePositiveCert = 0x13
- SigTypeSubkeyBinding = 0x18
- SigTypePrimaryKeyBinding = 0x19
- SigTypeDirectSignature = 0x1F
- SigTypeKeyRevocation = 0x20
- SigTypeSubkeyRevocation = 0x28
- SigTypeCertificationRevocation = 0x30
+ SigTypeText SignatureType = 0x01
+ SigTypeGenericCert SignatureType = 0x10
+ SigTypePersonaCert SignatureType = 0x11
+ SigTypeCasualCert SignatureType = 0x12
+ SigTypePositiveCert SignatureType = 0x13
+ SigTypeSubkeyBinding SignatureType = 0x18
+ SigTypePrimaryKeyBinding SignatureType = 0x19
+ SigTypeDirectSignature SignatureType = 0x1F
+ SigTypeKeyRevocation SignatureType = 0x20
+ SigTypeSubkeyRevocation SignatureType = 0x28
+ SigTypeCertificationRevocation SignatureType = 0x30
)
// PublicKeyAlgorithm represents the different public key system specified for
@@ -412,6 +500,11 @@ const (
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
// https://www.ietf.org/archive/id/draft-koch-eddsa-for-openpgp-04.txt
PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
+ // https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh
+ PubKeyAlgoX25519 PublicKeyAlgorithm = 25
+ PubKeyAlgoX448 PublicKeyAlgorithm = 26
+ PubKeyAlgoEd25519 PublicKeyAlgorithm = 27
+ PubKeyAlgoEd448 PublicKeyAlgorithm = 28
// Deprecated in RFC 4880, Section 13.5. Use key flags instead.
PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
@@ -422,7 +515,7 @@ const (
// key of the given type.
func (pka PublicKeyAlgorithm) CanEncrypt() bool {
switch pka {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH, PubKeyAlgoX25519, PubKeyAlgoX448:
return true
}
return false
@@ -432,7 +525,7 @@ func (pka PublicKeyAlgorithm) CanEncrypt() bool {
// sign a message.
func (pka PublicKeyAlgorithm) CanSign() bool {
switch pka {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA:
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA, PubKeyAlgoEd25519, PubKeyAlgoEd448:
return true
}
return false
@@ -512,6 +605,11 @@ func (mode AEADMode) TagLength() int {
return algorithm.AEADMode(mode).TagLength()
}
+// IsSupported returns true if the aead mode is supported from the library
+func (mode AEADMode) IsSupported() bool {
+ return algorithm.AEADMode(mode).TagLength() > 0
+}
+
// new returns a fresh instance of the given mode.
func (mode AEADMode) new(block cipher.Block) cipher.AEAD {
return algorithm.AEADMode(mode).New(block)
@@ -526,8 +624,17 @@ const (
KeySuperseded ReasonForRevocation = 1
KeyCompromised ReasonForRevocation = 2
KeyRetired ReasonForRevocation = 3
+ UserIDNotValid ReasonForRevocation = 32
+ Unknown ReasonForRevocation = 200
)
+func NewReasonForRevocation(value byte) ReasonForRevocation {
+ if value < 4 || value == 32 {
+ return ReasonForRevocation(value)
+ }
+ return Unknown
+}
+
// Curve is a mapping to supported ECC curves for key generation.
// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-06.html#name-curve-specific-wire-formats
type Curve string
@@ -549,3 +656,20 @@ type TrustLevel uint8
// TrustAmount represents a trust amount per RFC4880 5.2.3.13
type TrustAmount uint8
+
+const (
+ // versionSize is the length in bytes of the version value.
+ versionSize = 1
+ // algorithmSize is the length in bytes of the key algorithm value.
+ algorithmSize = 1
+ // keyVersionSize is the length in bytes of the key version value
+ keyVersionSize = 1
+ // keyIdSize is the length in bytes of the key identifier value.
+ keyIdSize = 8
+ // timestampSize is the length in bytes of encoded timestamps.
+ timestampSize = 4
+ // fingerprintSizeV6 is the length in bytes of the key fingerprint in v6.
+ fingerprintSizeV6 = 32
+ // fingerprintSize is the length in bytes of the key fingerprint.
+ fingerprintSize = 20
+)
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go
new file mode 100644
index 00000000..55a8a56c
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go
@@ -0,0 +1,222 @@
+package packet
+
+// This file implements the pushdown automata (PDA) from PGPainless (Paul Schaub)
+// to verify pgp packet sequences. See Paul's blogpost for more details:
+// https://blog.jabberhead.tk/2022/10/26/implementing-packet-sequence-validation-using-pushdown-automata/
+import (
+ "fmt"
+
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+)
+
+func NewErrMalformedMessage(from State, input InputSymbol, stackSymbol StackSymbol) errors.ErrMalformedMessage {
+ return errors.ErrMalformedMessage(fmt.Sprintf("state %d, input symbol %d, stack symbol %d ", from, input, stackSymbol))
+}
+
+// InputSymbol defines the input alphabet of the PDA
+type InputSymbol uint8
+
+const (
+ LDSymbol InputSymbol = iota
+ SigSymbol
+ OPSSymbol
+ CompSymbol
+ ESKSymbol
+ EncSymbol
+ EOSSymbol
+ UnknownSymbol
+)
+
+// StackSymbol defines the stack alphabet of the PDA
+type StackSymbol int8
+
+const (
+ MsgStackSymbol StackSymbol = iota
+ OpsStackSymbol
+ KeyStackSymbol
+ EndStackSymbol
+ EmptyStackSymbol
+)
+
+// State defines the states of the PDA
+type State int8
+
+const (
+ OpenPGPMessage State = iota
+ ESKMessage
+ LiteralMessage
+ CompressedMessage
+ EncryptedMessage
+ ValidMessage
+)
+
+// transition represents a state transition in the PDA
+type transition func(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error)
+
+// SequenceVerifier is a pushdown automata to verify
+// PGP messages packet sequences according to rfc4880.
+type SequenceVerifier struct {
+ stack []StackSymbol
+ state State
+}
+
+// Next performs a state transition with the given input symbol.
+// If the transition fails a ErrMalformedMessage is returned.
+func (sv *SequenceVerifier) Next(input InputSymbol) error {
+ for {
+ stackSymbol := sv.popStack()
+ transitionFunc := getTransition(sv.state)
+ nextState, newStackSymbols, redo, err := transitionFunc(input, stackSymbol)
+ if err != nil {
+ return err
+ }
+ if redo {
+ sv.pushStack(stackSymbol)
+ }
+ for _, newStackSymbol := range newStackSymbols {
+ sv.pushStack(newStackSymbol)
+ }
+ sv.state = nextState
+ if !redo {
+ break
+ }
+ }
+ return nil
+}
+
+// Valid returns true if RDA is in a valid state.
+func (sv *SequenceVerifier) Valid() bool {
+ return sv.state == ValidMessage && len(sv.stack) == 0
+}
+
+func (sv *SequenceVerifier) AssertValid() error {
+ if !sv.Valid() {
+ return errors.ErrMalformedMessage("invalid message")
+ }
+ return nil
+}
+
+func NewSequenceVerifier() *SequenceVerifier {
+ return &SequenceVerifier{
+ stack: []StackSymbol{EndStackSymbol, MsgStackSymbol},
+ state: OpenPGPMessage,
+ }
+}
+
+func (sv *SequenceVerifier) popStack() StackSymbol {
+ if len(sv.stack) == 0 {
+ return EmptyStackSymbol
+ }
+ elemIndex := len(sv.stack) - 1
+ stackSymbol := sv.stack[elemIndex]
+ sv.stack = sv.stack[:elemIndex]
+ return stackSymbol
+}
+
+func (sv *SequenceVerifier) pushStack(stackSymbol StackSymbol) {
+ sv.stack = append(sv.stack, stackSymbol)
+}
+
+func getTransition(from State) transition {
+ switch from {
+ case OpenPGPMessage:
+ return fromOpenPGPMessage
+ case LiteralMessage:
+ return fromLiteralMessage
+ case CompressedMessage:
+ return fromCompressedMessage
+ case EncryptedMessage:
+ return fromEncryptedMessage
+ case ESKMessage:
+ return fromESKMessage
+ case ValidMessage:
+ return fromValidMessage
+ }
+ return nil
+}
+
+// fromOpenPGPMessage is the transition for the state OpenPGPMessage.
+func fromOpenPGPMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
+ if stackSymbol != MsgStackSymbol {
+ return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol)
+ }
+ switch input {
+ case LDSymbol:
+ return LiteralMessage, nil, false, nil
+ case SigSymbol:
+ return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, false, nil
+ case OPSSymbol:
+ return OpenPGPMessage, []StackSymbol{OpsStackSymbol, MsgStackSymbol}, false, nil
+ case CompSymbol:
+ return CompressedMessage, nil, false, nil
+ case ESKSymbol:
+ return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil
+ case EncSymbol:
+ return EncryptedMessage, nil, false, nil
+ }
+ return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol)
+}
+
+// fromESKMessage is the transition for the state ESKMessage.
+func fromESKMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
+ if stackSymbol != KeyStackSymbol {
+ return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol)
+ }
+ switch input {
+ case ESKSymbol:
+ return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil
+ case EncSymbol:
+ return EncryptedMessage, nil, false, nil
+ }
+ return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol)
+}
+
+// fromLiteralMessage is the transition for the state LiteralMessage.
+func fromLiteralMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
+ switch input {
+ case SigSymbol:
+ if stackSymbol == OpsStackSymbol {
+ return LiteralMessage, nil, false, nil
+ }
+ case EOSSymbol:
+ if stackSymbol == EndStackSymbol {
+ return ValidMessage, nil, false, nil
+ }
+ }
+ return 0, nil, false, NewErrMalformedMessage(LiteralMessage, input, stackSymbol)
+}
+
+// fromLiteralMessage is the transition for the state CompressedMessage.
+func fromCompressedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
+ switch input {
+ case SigSymbol:
+ if stackSymbol == OpsStackSymbol {
+ return CompressedMessage, nil, false, nil
+ }
+ case EOSSymbol:
+ if stackSymbol == EndStackSymbol {
+ return ValidMessage, nil, false, nil
+ }
+ }
+ return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil
+}
+
+// fromEncryptedMessage is the transition for the state EncryptedMessage.
+func fromEncryptedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
+ switch input {
+ case SigSymbol:
+ if stackSymbol == OpsStackSymbol {
+ return EncryptedMessage, nil, false, nil
+ }
+ case EOSSymbol:
+ if stackSymbol == EndStackSymbol {
+ return ValidMessage, nil, false, nil
+ }
+ }
+ return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil
+}
+
+// fromValidMessage is the transition for the state ValidMessage.
+func fromValidMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
+ return 0, nil, false, NewErrMalformedMessage(ValidMessage, input, stackSymbol)
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go
new file mode 100644
index 00000000..2d714723
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go
@@ -0,0 +1,24 @@
+package packet
+
+import (
+ "io"
+
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+)
+
+// UnsupportedPackage represents a OpenPGP packet with a known packet type
+// but with unsupported content.
+type UnsupportedPacket struct {
+ IncompletePacket Packet
+ Error errors.UnsupportedError
+}
+
+// Implements the Packet interface
+func (up *UnsupportedPacket) parse(read io.Reader) error {
+ err := up.IncompletePacket.parse(read)
+ if castedErr, ok := err.(errors.UnsupportedError); ok {
+ up.Error = castedErr
+ return nil
+ }
+ return err
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go
new file mode 100644
index 00000000..3b6a7045
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go
@@ -0,0 +1,26 @@
+package packet
+
+import (
+ "io"
+)
+
+// Padding type represents a Padding Packet (Tag 21).
+// The padding type is represented by the length of its padding.
+// see https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-padding-packet-tag-21
+type Padding int
+
+// parse just ignores the padding content.
+func (pad Padding) parse(reader io.Reader) error {
+ _, err := io.CopyN(io.Discard, reader, int64(pad))
+ return err
+}
+
+// SerializePadding writes the padding to writer.
+func (pad Padding) SerializePadding(writer io.Writer, rand io.Reader) error {
+ err := serializeHeader(writer, packetPadding, int(pad))
+ if err != nil {
+ return err
+ }
+ _, err = io.CopyN(writer, rand, int64(pad))
+ return err
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
index 2fc43864..f04e6c6b 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
@@ -9,22 +9,28 @@ import (
"crypto"
"crypto/cipher"
"crypto/dsa"
- "crypto/rand"
"crypto/rsa"
"crypto/sha1"
+ "crypto/sha256"
+ "crypto/subtle"
+ "fmt"
"io"
- "io/ioutil"
"math/big"
"strconv"
"time"
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
+ "github.com/ProtonMail/go-crypto/openpgp/ed25519"
+ "github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
"github.com/ProtonMail/go-crypto/openpgp/s2k"
+ "github.com/ProtonMail/go-crypto/openpgp/x25519"
+ "github.com/ProtonMail/go-crypto/openpgp/x448"
+ "golang.org/x/crypto/hkdf"
)
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
@@ -35,14 +41,14 @@ type PrivateKey struct {
encryptedData []byte
cipher CipherFunction
s2k func(out, in []byte)
- // An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519}.PrivateKey or
+ aead AEADMode // only relevant if S2KAEAD is enabled
+ // An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519|ed448}.PrivateKey or
// crypto.Signer/crypto.Decrypter (Decryptor RSA only).
- PrivateKey interface{}
- sha1Checksum bool
- iv []byte
+ PrivateKey interface{}
+ iv []byte
// Type of encryption of the S2K packet
- // Allowed values are 0 (Not encrypted), 254 (SHA1), or
+ // Allowed values are 0 (Not encrypted), 253 (AEAD), 254 (SHA1), or
// 255 (2-byte checksum)
s2kType S2KType
// Full parameters of the S2K packet
@@ -55,6 +61,8 @@ type S2KType uint8
const (
// S2KNON unencrypt
S2KNON S2KType = 0
+ // S2KAEAD use authenticated encryption
+ S2KAEAD S2KType = 253
// S2KSHA1 sha1 sum check
S2KSHA1 S2KType = 254
// S2KCHECKSUM sum check
@@ -103,6 +111,34 @@ func NewECDHPrivateKey(creationTime time.Time, priv *ecdh.PrivateKey) *PrivateKe
return pk
}
+func NewX25519PrivateKey(creationTime time.Time, priv *x25519.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
+func NewX448PrivateKey(creationTime time.Time, priv *x448.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
+func NewEd25519PrivateKey(creationTime time.Time, priv *ed25519.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewEd25519PublicKey(creationTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
+func NewEd448PrivateKey(creationTime time.Time, priv *ed448.PrivateKey) *PrivateKey {
+ pk := new(PrivateKey)
+ pk.PublicKey = *NewEd448PublicKey(creationTime, &priv.PublicKey)
+ pk.PrivateKey = priv
+ return pk
+}
+
// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
// implements RSA, ECDSA or EdDSA.
func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey {
@@ -122,6 +158,14 @@ func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
case eddsa.PrivateKey:
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
+ case *ed25519.PrivateKey:
+ pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey)
+ case ed25519.PrivateKey:
+ pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey)
+ case *ed448.PrivateKey:
+ pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey)
+ case ed448.PrivateKey:
+ pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey)
default:
panic("openpgp: unknown signer type in NewSignerPrivateKey")
}
@@ -129,7 +173,7 @@ func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey
return pk
}
-// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh}.PrivateKey.
+// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh|x25519|x448}.PrivateKey.
func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *PrivateKey {
pk := new(PrivateKey)
switch priv := decrypter.(type) {
@@ -139,6 +183,10 @@ func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *Priv
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey)
case *ecdh.PrivateKey:
pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey)
+ case *x25519.PrivateKey:
+ pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey)
+ case *x448.PrivateKey:
+ pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey)
default:
panic("openpgp: unknown decrypter type in NewDecrypterPrivateKey")
}
@@ -152,6 +200,11 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
return
}
v5 := pk.PublicKey.Version == 5
+ v6 := pk.PublicKey.Version == 6
+
+ if V5Disabled && v5 {
+ return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
+ }
var buf [1]byte
_, err = readFull(r, buf[:])
@@ -160,7 +213,7 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
}
pk.s2kType = S2KType(buf[0])
var optCount [1]byte
- if v5 {
+ if v5 || (v6 && pk.s2kType != S2KNON) {
if _, err = readFull(r, optCount[:]); err != nil {
return
}
@@ -170,9 +223,9 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
case S2KNON:
pk.s2k = nil
pk.Encrypted = false
- case S2KSHA1, S2KCHECKSUM:
- if v5 && pk.s2kType == S2KCHECKSUM {
- return errors.StructuralError("wrong s2k identifier for version 5")
+ case S2KSHA1, S2KCHECKSUM, S2KAEAD:
+ if (v5 || v6) && pk.s2kType == S2KCHECKSUM {
+ return errors.StructuralError(fmt.Sprintf("wrong s2k identifier for version %d", pk.Version))
}
_, err = readFull(r, buf[:])
if err != nil {
@@ -182,6 +235,29 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
if pk.cipher != 0 && !pk.cipher.IsSupported() {
return errors.UnsupportedError("unsupported cipher function in private key")
}
+ // [Optional] If string-to-key usage octet was 253,
+ // a one-octet AEAD algorithm.
+ if pk.s2kType == S2KAEAD {
+ _, err = readFull(r, buf[:])
+ if err != nil {
+ return
+ }
+ pk.aead = AEADMode(buf[0])
+ if !pk.aead.IsSupported() {
+ return errors.UnsupportedError("unsupported aead mode in private key")
+ }
+ }
+
+ // [Optional] Only for a version 6 packet,
+ // and if string-to-key usage octet was 255, 254, or 253,
+ // an one-octet count of the following field.
+ if v6 {
+ _, err = readFull(r, buf[:])
+ if err != nil {
+ return
+ }
+ }
+
pk.s2kParams, err = s2k.ParseIntoParams(r)
if err != nil {
return
@@ -189,28 +265,43 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
if pk.s2kParams.Dummy() {
return
}
+ if pk.s2kParams.Mode() == s2k.Argon2S2K && pk.s2kType != S2KAEAD {
+ return errors.StructuralError("using Argon2 S2K without AEAD is not allowed")
+ }
+ if pk.s2kParams.Mode() == s2k.SimpleS2K && pk.Version == 6 {
+ return errors.StructuralError("using Simple S2K with version 6 keys is not allowed")
+ }
pk.s2k, err = pk.s2kParams.Function()
if err != nil {
return
}
pk.Encrypted = true
- if pk.s2kType == S2KSHA1 {
- pk.sha1Checksum = true
- }
default:
return errors.UnsupportedError("deprecated s2k function in private key")
}
if pk.Encrypted {
- blockSize := pk.cipher.blockSize()
- if blockSize == 0 {
+ var ivSize int
+ // If the S2K usage octet was 253, the IV is of the size expected by the AEAD mode,
+ // unless it's a version 5 key, in which case it's the size of the symmetric cipher's block size.
+ // For all other S2K modes, it's always the block size.
+ if !v5 && pk.s2kType == S2KAEAD {
+ ivSize = pk.aead.IvLength()
+ } else {
+ ivSize = pk.cipher.blockSize()
+ }
+
+ if ivSize == 0 {
return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
}
- pk.iv = make([]byte, blockSize)
+ pk.iv = make([]byte, ivSize)
_, err = readFull(r, pk.iv)
if err != nil {
return
}
+ if v5 && pk.s2kType == S2KAEAD {
+ pk.iv = pk.iv[:pk.aead.IvLength()]
+ }
}
var privateKeyData []byte
@@ -230,7 +321,7 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
return
}
} else {
- privateKeyData, err = ioutil.ReadAll(r)
+ privateKeyData, err = io.ReadAll(r)
if err != nil {
return
}
@@ -239,16 +330,22 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
if len(privateKeyData) < 2 {
return errors.StructuralError("truncated private key data")
}
- var sum uint16
- for i := 0; i < len(privateKeyData)-2; i++ {
- sum += uint16(privateKeyData[i])
- }
- if privateKeyData[len(privateKeyData)-2] != uint8(sum>>8) ||
- privateKeyData[len(privateKeyData)-1] != uint8(sum) {
- return errors.StructuralError("private key checksum failure")
+ if pk.Version != 6 {
+ // checksum
+ var sum uint16
+ for i := 0; i < len(privateKeyData)-2; i++ {
+ sum += uint16(privateKeyData[i])
+ }
+ if privateKeyData[len(privateKeyData)-2] != uint8(sum>>8) ||
+ privateKeyData[len(privateKeyData)-1] != uint8(sum) {
+ return errors.StructuralError("private key checksum failure")
+ }
+ privateKeyData = privateKeyData[:len(privateKeyData)-2]
+ return pk.parsePrivateKey(privateKeyData)
+ } else {
+ // No checksum
+ return pk.parsePrivateKey(privateKeyData)
}
- privateKeyData = privateKeyData[:len(privateKeyData)-2]
- return pk.parsePrivateKey(privateKeyData)
}
pk.encryptedData = privateKeyData
@@ -280,18 +377,59 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
optional := bytes.NewBuffer(nil)
if pk.Encrypted || pk.Dummy() {
- optional.Write([]byte{uint8(pk.cipher)})
- if err := pk.s2kParams.Serialize(optional); err != nil {
+ // [Optional] If string-to-key usage octet was 255, 254, or 253,
+ // a one-octet symmetric encryption algorithm.
+ if _, err = optional.Write([]byte{uint8(pk.cipher)}); err != nil {
+ return
+ }
+ // [Optional] If string-to-key usage octet was 253,
+ // a one-octet AEAD algorithm.
+ if pk.s2kType == S2KAEAD {
+ if _, err = optional.Write([]byte{uint8(pk.aead)}); err != nil {
+ return
+ }
+ }
+
+ s2kBuffer := bytes.NewBuffer(nil)
+ if err := pk.s2kParams.Serialize(s2kBuffer); err != nil {
return err
}
+ // [Optional] Only for a version 6 packet, and if string-to-key
+ // usage octet was 255, 254, or 253, an one-octet
+ // count of the following field.
+ if pk.Version == 6 {
+ if _, err = optional.Write([]byte{uint8(s2kBuffer.Len())}); err != nil {
+ return
+ }
+ }
+ // [Optional] If string-to-key usage octet was 255, 254, or 253,
+ // a string-to-key (S2K) specifier. The length of the string-to-key specifier
+ // depends on its type
+ if _, err = io.Copy(optional, s2kBuffer); err != nil {
+ return
+ }
+
+ // IV
if pk.Encrypted {
- optional.Write(pk.iv)
+ if _, err = optional.Write(pk.iv); err != nil {
+ return
+ }
+ if pk.Version == 5 && pk.s2kType == S2KAEAD {
+ // Add padding for version 5
+ padding := make([]byte, pk.cipher.blockSize()-len(pk.iv))
+ if _, err = optional.Write(padding); err != nil {
+ return
+ }
+ }
}
}
- if pk.Version == 5 {
+ if pk.Version == 5 || (pk.Version == 6 && pk.s2kType != S2KNON) {
contents.Write([]byte{uint8(optional.Len())})
}
- io.Copy(contents, optional)
+
+ if _, err := io.Copy(contents, optional); err != nil {
+ return err
+ }
if !pk.Dummy() {
l := 0
@@ -303,8 +441,10 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
return err
}
l = buf.Len()
- checksum := mod64kHash(buf.Bytes())
- buf.Write([]byte{byte(checksum >> 8), byte(checksum)})
+ if pk.Version != 6 {
+ checksum := mod64kHash(buf.Bytes())
+ buf.Write([]byte{byte(checksum >> 8), byte(checksum)})
+ }
priv = buf.Bytes()
} else {
priv, l = pk.encryptedData, len(pk.encryptedData)
@@ -370,6 +510,26 @@ func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error {
return err
}
+func serializeX25519PrivateKey(w io.Writer, priv *x25519.PrivateKey) error {
+ _, err := w.Write(priv.Secret)
+ return err
+}
+
+func serializeX448PrivateKey(w io.Writer, priv *x448.PrivateKey) error {
+ _, err := w.Write(priv.Secret)
+ return err
+}
+
+func serializeEd25519PrivateKey(w io.Writer, priv *ed25519.PrivateKey) error {
+ _, err := w.Write(priv.MarshalByteSecret())
+ return err
+}
+
+func serializeEd448PrivateKey(w io.Writer, priv *ed448.PrivateKey) error {
+ _, err := w.Write(priv.MarshalByteSecret())
+ return err
+}
+
// decrypt decrypts an encrypted private key using a decryption key.
func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
if pk.Dummy() {
@@ -378,37 +538,51 @@ func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
if !pk.Encrypted {
return nil
}
-
block := pk.cipher.new(decryptionKey)
- 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 data []byte
+ switch pk.s2kType {
+ case S2KAEAD:
+ aead := pk.aead.new(block)
+ additionalData, err := pk.additionalData()
+ if err != nil {
+ return err
}
- var sum uint16
- for i := 0; i < len(data)-2; i++ {
- sum += uint16(data[i])
+ // Decrypt the encrypted key material with aead
+ data, err = aead.Open(nil, pk.iv, pk.encryptedData, additionalData)
+ if err != nil {
+ return err
}
- if data[len(data)-2] != uint8(sum>>8) ||
- data[len(data)-1] != uint8(sum) {
- return errors.StructuralError("private key checksum failure")
+ case S2KSHA1, S2KCHECKSUM:
+ cfb := cipher.NewCFBDecrypter(block, pk.iv)
+ data = make([]byte, len(pk.encryptedData))
+ cfb.XORKeyStream(data, pk.encryptedData)
+ if pk.s2kType == S2KSHA1 {
+ 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]
}
- data = data[:len(data)-2]
+ default:
+ return errors.InvalidArgumentError("invalid s2k type")
}
err := pk.parsePrivateKey(data)
@@ -424,7 +598,6 @@ func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
pk.s2k = nil
pk.Encrypted = false
pk.encryptedData = nil
-
return nil
}
@@ -440,6 +613,9 @@ func (pk *PrivateKey) decryptWithCache(passphrase []byte, keyCache *s2k.Cache) e
if err != nil {
return err
}
+ if pk.s2kType == S2KAEAD {
+ key = pk.applyHKDF(key)
+ }
return pk.decrypt(key)
}
@@ -454,11 +630,14 @@ func (pk *PrivateKey) Decrypt(passphrase []byte) error {
key := make([]byte, pk.cipher.KeySize())
pk.s2k(key, passphrase)
+ if pk.s2kType == S2KAEAD {
+ key = pk.applyHKDF(key)
+ }
return pk.decrypt(key)
}
// DecryptPrivateKeys decrypts all encrypted keys with the given config and passphrase.
-// Avoids recomputation of similar s2k key derivations.
+// Avoids recomputation of similar s2k key derivations.
func DecryptPrivateKeys(keys []*PrivateKey, passphrase []byte) error {
// Create a cache to avoid recomputation of key derviations for the same passphrase.
s2kCache := &s2k.Cache{}
@@ -474,7 +653,7 @@ func DecryptPrivateKeys(keys []*PrivateKey, passphrase []byte) error {
}
// encrypt encrypts an unencrypted private key.
-func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, cipherFunction CipherFunction) error {
+func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, s2kType S2KType, cipherFunction CipherFunction, rand io.Reader) error {
if pk.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
@@ -485,7 +664,15 @@ func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, cipherFunction Cip
if len(key) != cipherFunction.KeySize() {
return errors.InvalidArgumentError("supplied encryption key has the wrong size")
}
-
+
+ if params.Mode() == s2k.Argon2S2K && s2kType != S2KAEAD {
+ return errors.InvalidArgumentError("using Argon2 S2K without AEAD is not allowed")
+ }
+ if params.Mode() != s2k.Argon2S2K && params.Mode() != s2k.IteratedSaltedS2K &&
+ params.Mode() != s2k.SaltedS2K { // only allowed for high-entropy passphrases
+ return errors.InvalidArgumentError("insecure S2K mode")
+ }
+
priv := bytes.NewBuffer(nil)
err := pk.serializePrivateKey(priv)
if err != nil {
@@ -497,35 +684,53 @@ func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, cipherFunction Cip
pk.s2k, err = pk.s2kParams.Function()
if err != nil {
return err
- }
+ }
privateKeyBytes := priv.Bytes()
- pk.sha1Checksum = true
+ pk.s2kType = s2kType
block := pk.cipher.new(key)
- pk.iv = make([]byte, pk.cipher.blockSize())
- _, err = rand.Read(pk.iv)
- if err != nil {
- return err
- }
- cfb := cipher.NewCFBEncrypter(block, pk.iv)
-
- if pk.sha1Checksum {
- pk.s2kType = S2KSHA1
- h := sha1.New()
- h.Write(privateKeyBytes)
- sum := h.Sum(nil)
- privateKeyBytes = append(privateKeyBytes, sum...)
- } else {
- pk.s2kType = S2KCHECKSUM
- var sum uint16
- for _, b := range privateKeyBytes {
- sum += uint16(b)
+ switch s2kType {
+ case S2KAEAD:
+ if pk.aead == 0 {
+ return errors.StructuralError("aead mode is not set on key")
}
- priv.Write([]byte{uint8(sum >> 8), uint8(sum)})
+ aead := pk.aead.new(block)
+ additionalData, err := pk.additionalData()
+ if err != nil {
+ return err
+ }
+ pk.iv = make([]byte, aead.NonceSize())
+ _, err = io.ReadFull(rand, pk.iv)
+ if err != nil {
+ return err
+ }
+ // Decrypt the encrypted key material with aead
+ pk.encryptedData = aead.Seal(nil, pk.iv, privateKeyBytes, additionalData)
+ case S2KSHA1, S2KCHECKSUM:
+ pk.iv = make([]byte, pk.cipher.blockSize())
+ _, err = io.ReadFull(rand, pk.iv)
+ if err != nil {
+ return err
+ }
+ cfb := cipher.NewCFBEncrypter(block, pk.iv)
+ if s2kType == S2KSHA1 {
+ h := sha1.New()
+ h.Write(privateKeyBytes)
+ sum := h.Sum(nil)
+ privateKeyBytes = append(privateKeyBytes, sum...)
+ } else {
+ var sum uint16
+ for _, b := range privateKeyBytes {
+ sum += uint16(b)
+ }
+ privateKeyBytes = append(privateKeyBytes, []byte{uint8(sum >> 8), uint8(sum)}...)
+ }
+ pk.encryptedData = make([]byte, len(privateKeyBytes))
+ cfb.XORKeyStream(pk.encryptedData, privateKeyBytes)
+ default:
+ return errors.InvalidArgumentError("invalid s2k type for encryption")
}
- pk.encryptedData = make([]byte, len(privateKeyBytes))
- cfb.XORKeyStream(pk.encryptedData, privateKeyBytes)
pk.Encrypted = true
pk.PrivateKey = nil
return err
@@ -544,8 +749,15 @@ func (pk *PrivateKey) EncryptWithConfig(passphrase []byte, config *Config) error
return err
}
s2k(key, passphrase)
+ s2kType := S2KSHA1
+ if config.AEAD() != nil {
+ s2kType = S2KAEAD
+ pk.aead = config.AEAD().Mode()
+ pk.cipher = config.Cipher()
+ key = pk.applyHKDF(key)
+ }
// Encrypt the private key with the derived encryption key.
- return pk.encrypt(key, params, config.Cipher())
+ return pk.encrypt(key, params, s2kType, config.Cipher(), config.Random())
}
// EncryptPrivateKeys encrypts all unencrypted keys with the given config and passphrase.
@@ -564,7 +776,16 @@ func EncryptPrivateKeys(keys []*PrivateKey, passphrase []byte, config *Config) e
s2k(encryptionKey, passphrase)
for _, key := range keys {
if key != nil && !key.Dummy() && !key.Encrypted {
- err = key.encrypt(encryptionKey, params, config.Cipher())
+ s2kType := S2KSHA1
+ if config.AEAD() != nil {
+ s2kType = S2KAEAD
+ key.aead = config.AEAD().Mode()
+ key.cipher = config.Cipher()
+ derivedKey := key.applyHKDF(encryptionKey)
+ err = key.encrypt(derivedKey, params, s2kType, config.Cipher(), config.Random())
+ } else {
+ err = key.encrypt(encryptionKey, params, s2kType, config.Cipher(), config.Random())
+ }
if err != nil {
return err
}
@@ -581,7 +802,7 @@ func (pk *PrivateKey) Encrypt(passphrase []byte) error {
S2KMode: s2k.IteratedSaltedS2K,
S2KCount: 65536,
Hash: crypto.SHA256,
- } ,
+ },
DefaultCipher: CipherAES256,
}
return pk.EncryptWithConfig(passphrase, config)
@@ -601,6 +822,14 @@ func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
err = serializeEdDSAPrivateKey(w, priv)
case *ecdh.PrivateKey:
err = serializeECDHPrivateKey(w, priv)
+ case *x25519.PrivateKey:
+ err = serializeX25519PrivateKey(w, priv)
+ case *x448.PrivateKey:
+ err = serializeX448PrivateKey(w, priv)
+ case *ed25519.PrivateKey:
+ err = serializeEd25519PrivateKey(w, priv)
+ case *ed448.PrivateKey:
+ err = serializeEd448PrivateKey(w, priv)
default:
err = errors.InvalidArgumentError("unknown private key type")
}
@@ -621,8 +850,18 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
return pk.parseECDHPrivateKey(data)
case PubKeyAlgoEdDSA:
return pk.parseEdDSAPrivateKey(data)
+ case PubKeyAlgoX25519:
+ return pk.parseX25519PrivateKey(data)
+ case PubKeyAlgoX448:
+ return pk.parseX448PrivateKey(data)
+ case PubKeyAlgoEd25519:
+ return pk.parseEd25519PrivateKey(data)
+ case PubKeyAlgoEd448:
+ return pk.parseEd448PrivateKey(data)
+ default:
+ err = errors.StructuralError("unknown private key type")
+ return
}
- panic("impossible")
}
func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
@@ -743,6 +982,86 @@ func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
return nil
}
+func (pk *PrivateKey) parseX25519PrivateKey(data []byte) (err error) {
+ publicKey := pk.PublicKey.PublicKey.(*x25519.PublicKey)
+ privateKey := x25519.NewPrivateKey(*publicKey)
+ privateKey.PublicKey = *publicKey
+
+ privateKey.Secret = make([]byte, x25519.KeySize)
+
+ if len(data) != x25519.KeySize {
+ err = errors.StructuralError("wrong x25519 key size")
+ return err
+ }
+ subtle.ConstantTimeCopy(1, privateKey.Secret, data)
+ if err = x25519.Validate(privateKey); err != nil {
+ return err
+ }
+ pk.PrivateKey = privateKey
+ return nil
+}
+
+func (pk *PrivateKey) parseX448PrivateKey(data []byte) (err error) {
+ publicKey := pk.PublicKey.PublicKey.(*x448.PublicKey)
+ privateKey := x448.NewPrivateKey(*publicKey)
+ privateKey.PublicKey = *publicKey
+
+ privateKey.Secret = make([]byte, x448.KeySize)
+
+ if len(data) != x448.KeySize {
+ err = errors.StructuralError("wrong x448 key size")
+ return err
+ }
+ subtle.ConstantTimeCopy(1, privateKey.Secret, data)
+ if err = x448.Validate(privateKey); err != nil {
+ return err
+ }
+ pk.PrivateKey = privateKey
+ return nil
+}
+
+func (pk *PrivateKey) parseEd25519PrivateKey(data []byte) (err error) {
+ publicKey := pk.PublicKey.PublicKey.(*ed25519.PublicKey)
+ privateKey := ed25519.NewPrivateKey(*publicKey)
+ privateKey.PublicKey = *publicKey
+
+ if len(data) != ed25519.SeedSize {
+ err = errors.StructuralError("wrong ed25519 key size")
+ return err
+ }
+ err = privateKey.UnmarshalByteSecret(data)
+ if err != nil {
+ return err
+ }
+ err = ed25519.Validate(privateKey)
+ if err != nil {
+ return err
+ }
+ pk.PrivateKey = privateKey
+ return nil
+}
+
+func (pk *PrivateKey) parseEd448PrivateKey(data []byte) (err error) {
+ publicKey := pk.PublicKey.PublicKey.(*ed448.PublicKey)
+ privateKey := ed448.NewPrivateKey(*publicKey)
+ privateKey.PublicKey = *publicKey
+
+ if len(data) != ed448.SeedSize {
+ err = errors.StructuralError("wrong ed448 key size")
+ return err
+ }
+ err = privateKey.UnmarshalByteSecret(data)
+ if err != nil {
+ return err
+ }
+ err = ed448.Validate(privateKey)
+ if err != nil {
+ return err
+ }
+ pk.PrivateKey = privateKey
+ return nil
+}
+
func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
eddsaPub := pk.PublicKey.PublicKey.(*eddsa.PublicKey)
eddsaPriv := eddsa.NewPrivateKey(*eddsaPub)
@@ -767,6 +1086,41 @@ func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
return nil
}
+func (pk *PrivateKey) additionalData() ([]byte, error) {
+ additionalData := bytes.NewBuffer(nil)
+ // Write additional data prefix based on packet type
+ var packetByte byte
+ if pk.PublicKey.IsSubkey {
+ packetByte = 0xc7
+ } else {
+ packetByte = 0xc5
+ }
+ // Write public key to additional data
+ _, err := additionalData.Write([]byte{packetByte})
+ if err != nil {
+ return nil, err
+ }
+ err = pk.PublicKey.serializeWithoutHeaders(additionalData)
+ if err != nil {
+ return nil, err
+ }
+ return additionalData.Bytes(), nil
+}
+
+func (pk *PrivateKey) applyHKDF(inputKey []byte) []byte {
+ var packetByte byte
+ if pk.PublicKey.IsSubkey {
+ packetByte = 0xc7
+ } else {
+ packetByte = 0xc5
+ }
+ associatedData := []byte{packetByte, byte(pk.Version), byte(pk.cipher), byte(pk.aead)}
+ hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData)
+ encryptionKey := make([]byte, pk.cipher.KeySize())
+ _, _ = readFull(hkdfReader, encryptionKey)
+ return encryptionKey
+}
+
func validateDSAParameters(priv *dsa.PrivateKey) error {
p := priv.P // group prime
q := priv.Q // subgroup order
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
index 3402b8c1..f8da781b 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
@@ -5,7 +5,6 @@
package packet
import (
- "crypto"
"crypto/dsa"
"crypto/rsa"
"crypto/sha1"
@@ -21,23 +20,24 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
+ "github.com/ProtonMail/go-crypto/openpgp/ed25519"
+ "github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
+ "github.com/ProtonMail/go-crypto/openpgp/x25519"
+ "github.com/ProtonMail/go-crypto/openpgp/x448"
)
-type kdfHashFunction byte
-type kdfAlgorithm byte
-
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
type PublicKey struct {
Version int
CreationTime time.Time
PubKeyAlgo PublicKeyAlgorithm
- PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey
+ PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey, *x25519.PublicKey, *x448.PublicKey, *ed25519.PublicKey, *ed448.PublicKey
Fingerprint []byte
KeyId uint64
IsSubkey bool
@@ -61,11 +61,19 @@ func (pk *PublicKey) UpgradeToV5() {
pk.setFingerprintAndKeyId()
}
+// UpgradeToV6 updates the version of the key to v6, and updates all necessary
+// fields.
+func (pk *PublicKey) UpgradeToV6() error {
+ pk.Version = 6
+ pk.setFingerprintAndKeyId()
+ return pk.checkV6Compatibility()
+}
+
// signingKey provides a convenient abstraction over signature verification
// for v3 and v4 public keys.
type signingKey interface {
SerializeForHash(io.Writer) error
- SerializeSignaturePrefix(io.Writer)
+ SerializeSignaturePrefix(io.Writer) error
serializeWithoutHeaders(io.Writer) error
}
@@ -174,6 +182,54 @@ func NewEdDSAPublicKey(creationTime time.Time, pub *eddsa.PublicKey) *PublicKey
return pk
}
+func NewX25519PublicKey(creationTime time.Time, pub *x25519.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ Version: 4,
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoX25519,
+ PublicKey: pub,
+ }
+
+ pk.setFingerprintAndKeyId()
+ return pk
+}
+
+func NewX448PublicKey(creationTime time.Time, pub *x448.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ Version: 4,
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoX448,
+ PublicKey: pub,
+ }
+
+ pk.setFingerprintAndKeyId()
+ return pk
+}
+
+func NewEd25519PublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ Version: 4,
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoEd25519,
+ PublicKey: pub,
+ }
+
+ pk.setFingerprintAndKeyId()
+ return pk
+}
+
+func NewEd448PublicKey(creationTime time.Time, pub *ed448.PublicKey) *PublicKey {
+ pk := &PublicKey{
+ Version: 4,
+ CreationTime: creationTime,
+ PubKeyAlgo: PubKeyAlgoEd448,
+ PublicKey: pub,
+ }
+
+ pk.setFingerprintAndKeyId()
+ return pk
+}
+
func (pk *PublicKey) parse(r io.Reader) (err error) {
// RFC 4880, section 5.5.2
var buf [6]byte
@@ -181,12 +237,19 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
if err != nil {
return
}
- if buf[0] != 4 && buf[0] != 5 {
+
+ pk.Version = int(buf[0])
+ if pk.Version != 4 && pk.Version != 5 && pk.Version != 6 {
return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0])))
}
- pk.Version = int(buf[0])
- if pk.Version == 5 {
+ if V5Disabled && pk.Version == 5 {
+ return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
+ }
+
+ if pk.Version >= 5 {
+ // Read the four-octet scalar octet count
+ // The count is not used in this implementation
var n [4]byte
_, err = readFull(r, n[:])
if err != nil {
@@ -195,6 +258,7 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
}
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])
+ // Ignore four-ocet length
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
err = pk.parseRSA(r)
@@ -208,6 +272,14 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
err = pk.parseECDH(r)
case PubKeyAlgoEdDSA:
err = pk.parseEdDSA(r)
+ case PubKeyAlgoX25519:
+ err = pk.parseX25519(r)
+ case PubKeyAlgoX448:
+ err = pk.parseX448(r)
+ case PubKeyAlgoEd25519:
+ err = pk.parseEd25519(r)
+ case PubKeyAlgoEd448:
+ err = pk.parseEd448(r)
default:
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
}
@@ -221,21 +293,44 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
func (pk *PublicKey) setFingerprintAndKeyId() {
// RFC 4880, section 12.2
- if pk.Version == 5 {
+ if pk.Version >= 5 {
fingerprint := sha256.New()
- pk.SerializeForHash(fingerprint)
+ if err := pk.SerializeForHash(fingerprint); err != nil {
+ // Should not happen for a hash.
+ panic(err)
+ }
pk.Fingerprint = make([]byte, 32)
copy(pk.Fingerprint, fingerprint.Sum(nil))
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8])
} else {
fingerprint := sha1.New()
- pk.SerializeForHash(fingerprint)
+ if err := pk.SerializeForHash(fingerprint); err != nil {
+ // Should not happen for a hash.
+ panic(err)
+ }
pk.Fingerprint = make([]byte, 20)
copy(pk.Fingerprint, fingerprint.Sum(nil))
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
}
}
+func (pk *PublicKey) checkV6Compatibility() error {
+ // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoECDH:
+ curveInfo := ecc.FindByOid(pk.oid)
+ if curveInfo == nil {
+ return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
+ }
+ if curveInfo.GenName == ecc.Curve25519GenName {
+ return errors.StructuralError("cannot generate v6 key with deprecated OID: Curve25519Legacy")
+ }
+ case PubKeyAlgoEdDSA:
+ return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
+ }
+ return nil
+}
+
// 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) {
@@ -324,16 +419,17 @@ func (pk *PublicKey) parseECDSA(r io.Reader) (err error) {
if _, err = pk.oid.ReadFrom(r); err != nil {
return
}
- pk.p = new(encoding.MPI)
- if _, err = pk.p.ReadFrom(r); err != nil {
- return
- }
curveInfo := ecc.FindByOid(pk.oid)
if curveInfo == nil {
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
}
+ pk.p = new(encoding.MPI)
+ if _, err = pk.p.ReadFrom(r); err != nil {
+ return
+ }
+
c, ok := curveInfo.Curve.(ecc.ECDSACurve)
if !ok {
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
@@ -353,6 +449,17 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
if _, err = pk.oid.ReadFrom(r); err != nil {
return
}
+
+ curveInfo := ecc.FindByOid(pk.oid)
+ if curveInfo == nil {
+ return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
+ }
+
+ if pk.Version == 6 && curveInfo.GenName == ecc.Curve25519GenName {
+ // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
+ return errors.StructuralError("cannot read v6 key with deprecated OID: Curve25519Legacy")
+ }
+
pk.p = new(encoding.MPI)
if _, err = pk.p.ReadFrom(r); err != nil {
return
@@ -362,12 +469,6 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
return
}
- curveInfo := ecc.FindByOid(pk.oid)
-
- if curveInfo == nil {
- return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
- }
-
c, ok := curveInfo.Curve.(ecc.ECDHCurve)
if !ok {
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
@@ -396,10 +497,16 @@ func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
}
func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
+ if pk.Version == 6 {
+ // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
+ return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
+ }
+
pk.oid = new(encoding.OID)
if _, err = pk.oid.ReadFrom(r); err != nil {
return
}
+
curveInfo := ecc.FindByOid(pk.oid)
if curveInfo == nil {
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
@@ -435,75 +542,145 @@ func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
return
}
+func (pk *PublicKey) parseX25519(r io.Reader) (err error) {
+ point := make([]byte, x25519.KeySize)
+ _, err = io.ReadFull(r, point)
+ if err != nil {
+ return
+ }
+ pub := &x25519.PublicKey{
+ Point: point,
+ }
+ pk.PublicKey = pub
+ return
+}
+
+func (pk *PublicKey) parseX448(r io.Reader) (err error) {
+ point := make([]byte, x448.KeySize)
+ _, err = io.ReadFull(r, point)
+ if err != nil {
+ return
+ }
+ pub := &x448.PublicKey{
+ Point: point,
+ }
+ pk.PublicKey = pub
+ return
+}
+
+func (pk *PublicKey) parseEd25519(r io.Reader) (err error) {
+ point := make([]byte, ed25519.PublicKeySize)
+ _, err = io.ReadFull(r, point)
+ if err != nil {
+ return
+ }
+ pub := &ed25519.PublicKey{
+ Point: point,
+ }
+ pk.PublicKey = pub
+ return
+}
+
+func (pk *PublicKey) parseEd448(r io.Reader) (err error) {
+ point := make([]byte, ed448.PublicKeySize)
+ _, err = io.ReadFull(r, point)
+ if err != nil {
+ return
+ }
+ pub := &ed448.PublicKey{
+ Point: point,
+ }
+ pk.PublicKey = pub
+ return
+}
+
// SerializeForHash serializes the PublicKey to w with the special packet
// header format needed for hashing.
func (pk *PublicKey) SerializeForHash(w io.Writer) error {
- pk.SerializeSignaturePrefix(w)
+ if err := pk.SerializeSignaturePrefix(w); err != nil {
+ return err
+ }
return pk.serializeWithoutHeaders(w)
}
// 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(w io.Writer) {
+func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) error {
var pLength = pk.algorithmSpecificByteCount()
- if pk.Version == 5 {
- pLength += 10 // version, timestamp (4), algorithm, key octet count (4).
- w.Write([]byte{
- 0x9A,
+ // version, timestamp, algorithm
+ pLength += versionSize + timestampSize + algorithmSize
+ if pk.Version >= 5 {
+ // key octet count (4).
+ pLength += 4
+ _, err := w.Write([]byte{
+ // When a v4 signature is made over a key, the hash data starts with the octet 0x99, followed by a two-octet length
+ // of the key, and then the body of the key packet. When a v6 signature is made over a key, the hash data starts
+ // with the salt, then octet 0x9B, followed by a four-octet length of the key, and then the body of the key packet.
+ 0x95 + byte(pk.Version),
byte(pLength >> 24),
byte(pLength >> 16),
byte(pLength >> 8),
byte(pLength),
})
- return
+ return err
}
- pLength += 6
- w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
+ if _, err := w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}); err != nil {
+ return err
+ }
+ return nil
}
func (pk *PublicKey) Serialize(w io.Writer) (err error) {
- length := 6 // 6 byte header
+ length := uint32(versionSize + timestampSize + algorithmSize) // 6 byte header
length += pk.algorithmSpecificByteCount()
- if pk.Version == 5 {
+ if pk.Version >= 5 {
length += 4 // octet key count
}
packetType := packetTypePublicKey
if pk.IsSubkey {
packetType = packetTypePublicSubkey
}
- err = serializeHeader(w, packetType, length)
+ err = serializeHeader(w, packetType, int(length))
if err != nil {
return
}
return pk.serializeWithoutHeaders(w)
}
-func (pk *PublicKey) algorithmSpecificByteCount() int {
- length := 0
+func (pk *PublicKey) algorithmSpecificByteCount() uint32 {
+ length := uint32(0)
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
- length += int(pk.n.EncodedLength())
- length += int(pk.e.EncodedLength())
+ length += uint32(pk.n.EncodedLength())
+ length += uint32(pk.e.EncodedLength())
case PubKeyAlgoDSA:
- length += int(pk.p.EncodedLength())
- length += int(pk.q.EncodedLength())
- length += int(pk.g.EncodedLength())
- length += int(pk.y.EncodedLength())
+ length += uint32(pk.p.EncodedLength())
+ length += uint32(pk.q.EncodedLength())
+ length += uint32(pk.g.EncodedLength())
+ length += uint32(pk.y.EncodedLength())
case PubKeyAlgoElGamal:
- length += int(pk.p.EncodedLength())
- length += int(pk.g.EncodedLength())
- length += int(pk.y.EncodedLength())
+ length += uint32(pk.p.EncodedLength())
+ length += uint32(pk.g.EncodedLength())
+ length += uint32(pk.y.EncodedLength())
case PubKeyAlgoECDSA:
- length += int(pk.oid.EncodedLength())
- length += int(pk.p.EncodedLength())
+ length += uint32(pk.oid.EncodedLength())
+ length += uint32(pk.p.EncodedLength())
case PubKeyAlgoECDH:
- length += int(pk.oid.EncodedLength())
- length += int(pk.p.EncodedLength())
- length += int(pk.kdf.EncodedLength())
+ length += uint32(pk.oid.EncodedLength())
+ length += uint32(pk.p.EncodedLength())
+ length += uint32(pk.kdf.EncodedLength())
case PubKeyAlgoEdDSA:
- length += int(pk.oid.EncodedLength())
- length += int(pk.p.EncodedLength())
+ length += uint32(pk.oid.EncodedLength())
+ length += uint32(pk.p.EncodedLength())
+ case PubKeyAlgoX25519:
+ length += x25519.KeySize
+ case PubKeyAlgoX448:
+ length += x448.KeySize
+ case PubKeyAlgoEd25519:
+ length += ed25519.PublicKeySize
+ case PubKeyAlgoEd448:
+ length += ed448.PublicKeySize
default:
panic("unknown public key algorithm")
}
@@ -522,7 +699,7 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
return
}
- if pk.Version == 5 {
+ if pk.Version >= 5 {
n := pk.algorithmSpecificByteCount()
if _, err = w.Write([]byte{
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
@@ -580,6 +757,22 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
}
_, err = w.Write(pk.p.EncodedBytes())
return
+ case PubKeyAlgoX25519:
+ publicKey := pk.PublicKey.(*x25519.PublicKey)
+ _, err = w.Write(publicKey.Point)
+ return
+ case PubKeyAlgoX448:
+ publicKey := pk.PublicKey.(*x448.PublicKey)
+ _, err = w.Write(publicKey.Point)
+ return
+ case PubKeyAlgoEd25519:
+ publicKey := pk.PublicKey.(*ed25519.PublicKey)
+ _, err = w.Write(publicKey.Point)
+ return
+ case PubKeyAlgoEd448:
+ publicKey := pk.PublicKey.(*ed448.PublicKey)
+ _, err = w.Write(publicKey.Point)
+ return
}
return errors.InvalidArgumentError("bad public-key algorithm")
}
@@ -589,6 +782,20 @@ func (pk *PublicKey) CanSign() bool {
return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH
}
+// VerifyHashTag returns nil iff sig appears to be a plausible signature of the data
+// hashed into signed, based solely on its HashTag. signed is mutated by this call.
+func VerifyHashTag(signed hash.Hash, sig *Signature) (err error) {
+ if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
+ sig.AddMetadataToHashSuffix()
+ }
+ 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")
+ }
+ return nil
+}
+
// 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) {
@@ -600,7 +807,8 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
}
signed.Write(sig.HashSuffix)
hashBytes := signed.Sum(nil)
- if sig.Version == 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) {
+ // see discussion https://github.com/ProtonMail/go-crypto/issues/107
+ if sig.Version >= 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) {
return errors.SignatureError("hash tag doesn't match")
}
@@ -639,6 +847,18 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
return errors.SignatureError("EdDSA verification failure")
}
return nil
+ case PubKeyAlgoEd25519:
+ ed25519PublicKey := pk.PublicKey.(*ed25519.PublicKey)
+ if !ed25519.Verify(ed25519PublicKey, hashBytes, sig.EdSig) {
+ return errors.SignatureError("Ed25519 verification failure")
+ }
+ return nil
+ case PubKeyAlgoEd448:
+ ed448PublicKey := pk.PublicKey.(*ed448.PublicKey)
+ if !ed448.Verify(ed448PublicKey, hashBytes, sig.EdSig) {
+ return errors.SignatureError("ed448 verification failure")
+ }
+ return nil
default:
return errors.SignatureError("Unsupported public key algorithm used in signature")
}
@@ -646,11 +866,8 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
// 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()
+func keySignatureHash(pk, signed signingKey, hashFunc hash.Hash) (h hash.Hash, err error) {
+ h = hashFunc
// RFC 4880, section 5.2.4
err = pk.SerializeForHash(h)
@@ -662,10 +879,28 @@ func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash,
return
}
+// VerifyKeyHashTag returns nil iff sig appears to be a plausible signature over this
+// primary key and subkey, based solely on its HashTag.
+func (pk *PublicKey) VerifyKeyHashTag(signed *PublicKey, sig *Signature) error {
+ preparedHash, err := sig.PrepareVerify()
+ if err != nil {
+ return err
+ }
+ h, err := keySignatureHash(pk, signed, preparedHash)
+ if err != nil {
+ return err
+ }
+ return VerifyHashTag(h, sig)
+}
+
// 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)
+ preparedHash, err := sig.PrepareVerify()
+ if err != nil {
+ return err
+ }
+ h, err := keySignatureHash(pk, signed, preparedHash)
if err != nil {
return err
}
@@ -679,10 +914,14 @@ func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error
if sig.EmbeddedSignature == nil {
return errors.StructuralError("signing subkey is missing cross-signature")
}
+ preparedHashEmbedded, err := sig.EmbeddedSignature.PrepareVerify()
+ if err != nil {
+ return err
+ }
// 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 {
+ if h, err = keySignatureHash(pk, signed, preparedHashEmbedded); err != nil {
return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
}
if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
@@ -693,32 +932,44 @@ func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) 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
- err = pk.SerializeForHash(h)
+func keyRevocationHash(pk signingKey, hashFunc hash.Hash) (err error) {
+ return pk.SerializeForHash(hashFunc)
+}
- return
+// VerifyRevocationHashTag returns nil iff sig appears to be a plausible signature
+// over this public key, based solely on its HashTag.
+func (pk *PublicKey) VerifyRevocationHashTag(sig *Signature) (err error) {
+ preparedHash, err := sig.PrepareVerify()
+ if err != nil {
+ return err
+ }
+ if err = keyRevocationHash(pk, preparedHash); err != nil {
+ return err
+ }
+ return VerifyHashTag(preparedHash, sig)
}
// 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)
+ preparedHash, err := sig.PrepareVerify()
if err != nil {
return err
}
- return pk.VerifySignature(h, sig)
+ if err = keyRevocationHash(pk, preparedHash); err != nil {
+ return err
+ }
+ return pk.VerifySignature(preparedHash, sig)
}
// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature,
// made by this public key, of signed.
func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *PublicKey) (err error) {
- h, err := keySignatureHash(pk, signed, sig.Hash)
+ preparedHash, err := sig.PrepareVerify()
+ if err != nil {
+ return err
+ }
+ h, err := keySignatureHash(pk, signed, preparedHash)
if err != nil {
return err
}
@@ -727,15 +978,15 @@ func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *Pub
// 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()
+func userIdSignatureHash(id string, pk *PublicKey, h hash.Hash) (err error) {
// RFC 4880, section 5.2.4
- pk.SerializeSignaturePrefix(h)
- pk.serializeWithoutHeaders(h)
+ if err := pk.SerializeSignaturePrefix(h); err != nil {
+ return err
+ }
+ if err := pk.serializeWithoutHeaders(h); err != nil {
+ return err
+ }
var buf [5]byte
buf[0] = 0xb4
@@ -746,16 +997,51 @@ func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash
h.Write(buf[:])
h.Write([]byte(id))
- return
+ return nil
+}
+
+// directKeySignatureHash returns a Hash of the message that needs to be signed.
+func directKeySignatureHash(pk *PublicKey, h hash.Hash) (err error) {
+ return pk.SerializeForHash(h)
+}
+
+// VerifyUserIdHashTag returns nil iff sig appears to be a plausible signature over this
+// public key and UserId, based solely on its HashTag
+func (pk *PublicKey) VerifyUserIdHashTag(id string, sig *Signature) (err error) {
+ preparedHash, err := sig.PrepareVerify()
+ if err != nil {
+ return err
+ }
+ err = userIdSignatureHash(id, pk, preparedHash)
+ if err != nil {
+ return err
+ }
+ return VerifyHashTag(preparedHash, sig)
}
// 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)
+ h, err := sig.PrepareVerify()
+ if err != nil {
+ return err
+ }
+ if err := userIdSignatureHash(id, pub, h); err != nil {
+ return err
+ }
+ return pk.VerifySignature(h, sig)
+}
+
+// VerifyDirectKeySignature returns nil iff sig is a valid signature, made by this
+// public key.
+func (pk *PublicKey) VerifyDirectKeySignature(sig *Signature) (err error) {
+ h, err := sig.PrepareVerify()
if err != nil {
return err
}
+ if err := directKeySignatureHash(pk, h); err != nil {
+ return err
+ }
return pk.VerifySignature(h, sig)
}
@@ -786,21 +1072,49 @@ func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
bitLength = pk.p.BitLength()
case PubKeyAlgoEdDSA:
bitLength = pk.p.BitLength()
+ case PubKeyAlgoX25519:
+ bitLength = x25519.KeySize * 8
+ case PubKeyAlgoX448:
+ bitLength = x448.KeySize * 8
+ case PubKeyAlgoEd25519:
+ bitLength = ed25519.PublicKeySize * 8
+ case PubKeyAlgoEd448:
+ bitLength = ed448.PublicKeySize * 8
default:
err = errors.InvalidArgumentError("bad public-key algorithm")
}
return
}
+// Curve returns the used elliptic curve of this public key.
+// Returns an error if no elliptic curve is used.
+func (pk *PublicKey) Curve() (curve Curve, err error) {
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoECDSA, PubKeyAlgoECDH, PubKeyAlgoEdDSA:
+ curveInfo := ecc.FindByOid(pk.oid)
+ if curveInfo == nil {
+ return "", errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
+ }
+ curve = Curve(curveInfo.GenName)
+ case PubKeyAlgoEd25519, PubKeyAlgoX25519:
+ curve = Curve25519
+ case PubKeyAlgoEd448, PubKeyAlgoX448:
+ curve = Curve448
+ default:
+ err = errors.InvalidArgumentError("public key does not operate with an elliptic curve")
+ }
+ return
+}
+
// KeyExpired returns whether sig is a self-signature of a key that has
// expired or is created in the future.
func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool {
- if pk.CreationTime.After(currentTime) {
+ if pk.CreationTime.Unix() > currentTime.Unix() {
return true
}
if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 {
return false
}
expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
- return currentTime.After(expiry)
+ return currentTime.Unix() > expiry.Unix()
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
index 10215fe5..dd840923 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
@@ -10,6 +10,12 @@ import (
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
+type PacketReader interface {
+ Next() (p Packet, err error)
+ Push(reader io.Reader) (err error)
+ Unread(p Packet)
+}
+
// 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 {
@@ -26,37 +32,81 @@ type Reader struct {
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.
+// the top-most io.Reader. Unknown/unsupported/Marker packet types are skipped.
func (r *Reader) Next() (p Packet, err error) {
+ for {
+ p, err := r.read()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ if _, ok := err.(errors.UnknownPacketTypeError); ok {
+ continue
+ }
+ if _, ok := err.(errors.UnsupportedError); ok {
+ switch p.(type) {
+ case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
+ return nil, err
+ }
+ continue
+ }
+ return nil, err
+ } else {
+ //A marker packet MUST be ignored when received
+ switch p.(type) {
+ case *Marker:
+ continue
+ }
+ return p, nil
+ }
+ }
+ return nil, io.EOF
+}
+
+// Next returns the most recently unread Packet, or reads another packet from
+// the top-most io.Reader. Unknown/Marker packet types are skipped while unsupported
+// packets are returned as UnsupportedPacket type.
+func (r *Reader) NextWithUnsupported() (p Packet, err error) {
+ for {
+ p, err = r.read()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ if _, ok := err.(errors.UnknownPacketTypeError); ok {
+ continue
+ }
+ if casteErr, ok := err.(errors.UnsupportedError); ok {
+ return &UnsupportedPacket{
+ IncompletePacket: p,
+ Error: casteErr,
+ }, nil
+ }
+ return
+ } else {
+ //A marker packet MUST be ignored when received
+ switch p.(type) {
+ case *Marker:
+ continue
+ }
+ return
+ }
+ }
+ return nil, io.EOF
+}
+
+func (r *Reader) read() (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
}
- // TODO: Add strict mode that rejects unknown packets, instead of ignoring them.
- if _, ok := err.(errors.UnknownPacketTypeError); ok {
- continue
- }
- if _, ok := err.(errors.UnsupportedError); ok {
- switch p.(type) {
- case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
- return nil, err
- }
- continue
- }
- return nil, err
+ return p, err
}
-
return nil, io.EOF
}
@@ -84,3 +134,76 @@ func NewReader(r io.Reader) *Reader {
readers: []io.Reader{r},
}
}
+
+// CheckReader is similar to Reader but additionally
+// uses the pushdown automata to verify the read packet sequence.
+type CheckReader struct {
+ Reader
+ verifier *SequenceVerifier
+ fullyRead bool
+}
+
+// Next returns the most recently unread Packet, or reads another packet from
+// the top-most io.Reader. Unknown packet types are skipped.
+// If the read packet sequence does not conform to the packet composition
+// rules in rfc4880, it returns an error.
+func (r *CheckReader) Next() (p Packet, err error) {
+ if r.fullyRead {
+ return nil, io.EOF
+ }
+ if len(r.q) > 0 {
+ p = r.q[len(r.q)-1]
+ r.q = r.q[:len(r.q)-1]
+ return
+ }
+ var errMsg error
+ for len(r.readers) > 0 {
+ p, errMsg, err = ReadWithCheck(r.readers[len(r.readers)-1], r.verifier)
+ if errMsg != nil {
+ err = errMsg
+ return
+ }
+ if err == nil {
+ return
+ }
+ if err == io.EOF {
+ r.readers = r.readers[:len(r.readers)-1]
+ continue
+ }
+ //A marker packet MUST be ignored when received
+ switch p.(type) {
+ case *Marker:
+ continue
+ }
+ if _, ok := err.(errors.UnknownPacketTypeError); ok {
+ continue
+ }
+ if _, ok := err.(errors.UnsupportedError); ok {
+ switch p.(type) {
+ case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
+ return nil, err
+ }
+ continue
+ }
+ return nil, err
+ }
+ if errMsg = r.verifier.Next(EOSSymbol); errMsg != nil {
+ return nil, errMsg
+ }
+ if errMsg = r.verifier.AssertValid(); errMsg != nil {
+ return nil, errMsg
+ }
+ r.fullyRead = true
+ return nil, io.EOF
+}
+
+func NewCheckReader(r io.Reader) *CheckReader {
+ return &CheckReader{
+ Reader: Reader{
+ q: nil,
+ readers: []io.Reader{r},
+ },
+ verifier: NewSequenceVerifier(),
+ fullyRead: false,
+ }
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go
new file mode 100644
index 00000000..fb2e362e
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go
@@ -0,0 +1,15 @@
+package packet
+
+// Recipient type represents a Intended Recipient Fingerprint subpacket
+// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-intended-recipient-fingerpr
+type Recipient struct {
+ KeyVersion int
+ Fingerprint []byte
+}
+
+func (r *Recipient) Serialize() []byte {
+ packet := make([]byte, len(r.Fingerprint)+1)
+ packet[0] = byte(r.KeyVersion)
+ copy(packet[1:], r.Fingerprint)
+ return packet
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
index 80d0bb98..3a4b366d 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
@@ -8,13 +8,17 @@ import (
"bytes"
"crypto"
"crypto/dsa"
+ "encoding/asn1"
"encoding/binary"
"hash"
"io"
+ "math/big"
"strconv"
"time"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
+ "github.com/ProtonMail/go-crypto/openpgp/ed25519"
+ "github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
@@ -22,7 +26,8 @@ import (
)
const (
- // See RFC 4880, section 5.2.3.21 for details.
+ // First octet of key flags.
+ // See RFC 9580, section 5.2.3.29 for details.
KeyFlagCertify = 1 << iota
KeyFlagSign
KeyFlagEncryptCommunications
@@ -33,12 +38,30 @@ const (
KeyFlagGroupKey
)
-// Signature represents a signature. See RFC 4880, section 5.2.
+const (
+ // First octet of keyserver preference flags.
+ // See RFC 9580, section 5.2.3.25 for details.
+ _ = 1 << iota
+ _
+ _
+ _
+ _
+ _
+ _
+ KeyserverPrefNoModify
+)
+
+const SaltNotationName = "salt@notations.openpgpjs.org"
+
+// Signature represents a signature. See RFC 9580, section 5.2.
type Signature struct {
Version int
SigType SignatureType
PubKeyAlgo PublicKeyAlgorithm
Hash crypto.Hash
+ // salt contains a random salt value for v6 signatures
+ // See RFC 9580 Section 5.2.4.
+ salt []byte
// HashSuffix is extra data that is hashed in after the signed data.
HashSuffix []byte
@@ -57,6 +80,7 @@ type Signature struct {
DSASigR, DSASigS encoding.Field
ECDSASigR, ECDSASigS encoding.Field
EdDSASigR, EdDSASigS encoding.Field
+ EdSig []byte
// rawSubpackets contains the unparsed subpackets, in order.
rawSubpackets []outputSubpacket
@@ -72,31 +96,42 @@ type Signature struct {
SignerUserId *string
IsPrimaryId *bool
Notations []*Notation
+ IntendedRecipients []*Recipient
// TrustLevel and TrustAmount can be set by the signer to assert that
// the key is not only valid but also trustworthy at the specified
// level.
- // See RFC 4880, section 5.2.3.13 for details.
+ // See RFC 9580, section 5.2.3.21 for details.
TrustLevel TrustLevel
TrustAmount TrustAmount
// TrustRegularExpression can be used in conjunction with trust Signature
// packets to limit the scope of the trust that is extended.
- // See RFC 4880, section 5.2.3.14 for details.
+ // See RFC 9580, section 5.2.3.22 for details.
TrustRegularExpression *string
+ // KeyserverPrefsValid is set if any keyserver preferences were given. See RFC 9580, section
+ // 5.2.3.25 for details.
+ KeyserverPrefsValid bool
+ KeyserverPrefNoModify bool
+
+ // PreferredKeyserver can be set to a URI where the latest version of the
+ // key that this signature is made over can be found. See RFC 9580, section
+ // 5.2.3.26 for details.
+ PreferredKeyserver string
+
// PolicyURI can be set to the URI of a document that describes the
- // policy under which the signature was issued. See RFC 4880, section
- // 5.2.3.20 for details.
+ // policy under which the signature was issued. See RFC 9580, section
+ // 5.2.3.28 for details.
PolicyURI string
- // FlagsValid is set if any flags were given. See RFC 4880, section
- // 5.2.3.21 for details.
+ // FlagsValid is set if any flags were given. See RFC 9580, section
+ // 5.2.3.29 for details.
FlagsValid bool
FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage, FlagSplitKey, FlagAuthenticate, FlagGroupKey bool
// RevocationReason is set if this signature has been revoked.
- // See RFC 4880, section 5.2.3.23 for details.
+ // See RFC 9580, section 5.2.3.31 for details.
RevocationReason *ReasonForRevocation
RevocationReasonText string
@@ -113,26 +148,57 @@ type Signature struct {
outSubpackets []outputSubpacket
}
+// VerifiableSignature internally keeps state if the
+// the signature has been verified before.
+type VerifiableSignature struct {
+ Valid *bool // nil if it has not been verified yet
+ Packet *Signature
+}
+
+// NewVerifiableSig returns a struct of type VerifiableSignature referencing the input signature.
+func NewVerifiableSig(signature *Signature) *VerifiableSignature {
+ return &VerifiableSignature{
+ Packet: signature,
+ }
+}
+
+// Salt returns the signature salt for v6 signatures.
+func (sig *Signature) Salt() []byte {
+ if sig == nil {
+ return nil
+ }
+ return sig.salt
+}
+
func (sig *Signature) parse(r io.Reader) (err error) {
- // RFC 4880, section 5.2.3
- var buf [5]byte
+ // RFC 9580, section 5.2.3
+ var buf [7]byte
_, err = readFull(r, buf[:1])
if err != nil {
return
}
- if buf[0] != 4 && buf[0] != 5 {
+ sig.Version = int(buf[0])
+ if sig.Version != 4 && sig.Version != 5 && sig.Version != 6 {
err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
return
}
- sig.Version = int(buf[0])
- _, err = readFull(r, buf[:5])
+
+ if V5Disabled && sig.Version == 5 {
+ return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
+ }
+
+ if sig.Version == 6 {
+ _, err = readFull(r, buf[:7])
+ } else {
+ _, 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, PubKeyAlgoEdDSA:
+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA, PubKeyAlgoEd25519, PubKeyAlgoEd448:
default:
err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
return
@@ -150,7 +216,17 @@ func (sig *Signature) parse(r io.Reader) (err error) {
return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
}
- hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
+ var hashedSubpacketsLength int
+ if sig.Version == 6 {
+ // For a v6 signature, a four-octet length is used.
+ hashedSubpacketsLength =
+ int(buf[3])<<24 |
+ int(buf[4])<<16 |
+ int(buf[5])<<8 |
+ int(buf[6])
+ } else {
+ hashedSubpacketsLength = int(buf[3])<<8 | int(buf[4])
+ }
hashedSubpackets := make([]byte, hashedSubpacketsLength)
_, err = readFull(r, hashedSubpackets)
if err != nil {
@@ -166,11 +242,21 @@ func (sig *Signature) parse(r io.Reader) (err error) {
return
}
- _, err = readFull(r, buf[:2])
+ if sig.Version == 6 {
+ _, err = readFull(r, buf[:4])
+ } else {
+ _, err = readFull(r, buf[:2])
+ }
+
if err != nil {
return
}
- unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
+ var unhashedSubpacketsLength uint32
+ if sig.Version == 6 {
+ unhashedSubpacketsLength = uint32(buf[0])<<24 | uint32(buf[1])<<16 | uint32(buf[2])<<8 | uint32(buf[3])
+ } else {
+ unhashedSubpacketsLength = uint32(buf[0])<<8 | uint32(buf[1])
+ }
unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
_, err = readFull(r, unhashedSubpackets)
if err != nil {
@@ -186,6 +272,30 @@ func (sig *Signature) parse(r io.Reader) (err error) {
return
}
+ if sig.Version == 6 {
+ // Only for v6 signatures, a variable-length field containing the salt
+ _, err = readFull(r, buf[:1])
+ if err != nil {
+ return
+ }
+ saltLength := int(buf[0])
+ var expectedSaltLength int
+ expectedSaltLength, err = SaltLengthForHash(sig.Hash)
+ if err != nil {
+ return
+ }
+ if saltLength != expectedSaltLength {
+ err = errors.StructuralError("unexpected salt size for the given hash algorithm")
+ return
+ }
+ salt := make([]byte, expectedSaltLength)
+ _, err = readFull(r, salt)
+ if err != nil {
+ return
+ }
+ sig.salt = salt
+ }
+
switch sig.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
sig.RSASignature = new(encoding.MPI)
@@ -216,6 +326,16 @@ func (sig *Signature) parse(r io.Reader) (err error) {
if _, err = sig.EdDSASigS.ReadFrom(r); err != nil {
return
}
+ case PubKeyAlgoEd25519:
+ sig.EdSig, err = ed25519.ReadSignature(r)
+ if err != nil {
+ return
+ }
+ case PubKeyAlgoEd448:
+ sig.EdSig, err = ed448.ReadSignature(r)
+ if err != nil {
+ return
+ }
default:
panic("unreachable")
}
@@ -223,7 +343,7 @@ func (sig *Signature) parse(r io.Reader) (err error) {
}
// parseSignatureSubpackets parses subpackets of the main signature packet. See
-// RFC 4880, section 5.2.3.1.
+// RFC 9580, 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)
@@ -244,6 +364,7 @@ type signatureSubpacketType uint8
const (
creationTimeSubpacket signatureSubpacketType = 2
signatureExpirationSubpacket signatureSubpacketType = 3
+ exportableCertSubpacket signatureSubpacketType = 4
trustSubpacket signatureSubpacketType = 5
regularExpressionSubpacket signatureSubpacketType = 6
keyExpirationSubpacket signatureSubpacketType = 9
@@ -252,6 +373,8 @@ const (
notationDataSubpacket signatureSubpacketType = 20
prefHashAlgosSubpacket signatureSubpacketType = 21
prefCompressionSubpacket signatureSubpacketType = 22
+ keyserverPrefsSubpacket signatureSubpacketType = 23
+ prefKeyserverSubpacket signatureSubpacketType = 24
primaryUserIdSubpacket signatureSubpacketType = 25
policyUriSubpacket signatureSubpacketType = 26
keyFlagsSubpacket signatureSubpacketType = 27
@@ -260,12 +383,13 @@ const (
featuresSubpacket signatureSubpacketType = 30
embeddedSignatureSubpacket signatureSubpacketType = 32
issuerFingerprintSubpacket signatureSubpacketType = 33
+ intendedRecipientSubpacket signatureSubpacketType = 35
prefCipherSuitesSubpacket signatureSubpacketType = 39
)
// 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
+ // RFC 9580, section 5.2.3.7
var (
length uint32
packetType signatureSubpacketType
@@ -323,19 +447,24 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
t := binary.BigEndian.Uint32(subpacket)
sig.CreationTime = time.Unix(int64(t), 0)
case signatureExpirationSubpacket:
- // Signature expiration time, section 5.2.3.10
+ // Signature expiration time, section 5.2.3.18
if len(subpacket) != 4 {
err = errors.StructuralError("expiration subpacket with bad length")
return
}
sig.SigLifetimeSecs = new(uint32)
*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
+ case exportableCertSubpacket:
+ if subpacket[0] == 0 {
+ err = errors.UnsupportedError("signature with non-exportable certification")
+ return
+ }
case trustSubpacket:
if len(subpacket) != 2 {
err = errors.StructuralError("trust subpacket with bad length")
return
}
- // Trust level and amount, section 5.2.3.13
+ // Trust level and amount, section 5.2.3.21
sig.TrustLevel = TrustLevel(subpacket[0])
sig.TrustAmount = TrustAmount(subpacket[1])
case regularExpressionSubpacket:
@@ -343,7 +472,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
err = errors.StructuralError("regexp subpacket with bad length")
return
}
- // Trust regular expression, section 5.2.3.14
+ // Trust regular expression, section 5.2.3.22
// RFC specifies the string should be null-terminated; remove a null byte from the end
if subpacket[len(subpacket)-1] != 0x00 {
err = errors.StructuralError("expected regular expression to be null-terminated")
@@ -352,7 +481,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
trustRegularExpression := string(subpacket[:len(subpacket)-1])
sig.TrustRegularExpression = &trustRegularExpression
case keyExpirationSubpacket:
- // Key expiration time, section 5.2.3.6
+ // Key expiration time, section 5.2.3.13
if len(subpacket) != 4 {
err = errors.StructuralError("key expiration subpacket with bad length")
return
@@ -360,23 +489,25 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
sig.KeyLifetimeSecs = new(uint32)
*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
case prefSymmetricAlgosSubpacket:
- // Preferred symmetric algorithms, section 5.2.3.7
+ // Preferred symmetric algorithms, section 5.2.3.14
sig.PreferredSymmetric = make([]byte, len(subpacket))
copy(sig.PreferredSymmetric, subpacket)
case issuerSubpacket:
- // Issuer, section 5.2.3.5
- if sig.Version > 4 {
- err = errors.StructuralError("issuer subpacket found in v5 key")
+ // Issuer, section 5.2.3.12
+ if sig.Version > 4 && isHashed {
+ err = errors.StructuralError("issuer subpacket found in v6 key")
return
}
if len(subpacket) != 8 {
err = errors.StructuralError("issuer subpacket with bad length")
return
}
- sig.IssuerKeyId = new(uint64)
- *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
+ if sig.Version <= 4 {
+ sig.IssuerKeyId = new(uint64)
+ *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
+ }
case notationDataSubpacket:
- // Notation data, section 5.2.3.16
+ // Notation data, section 5.2.3.24
if len(subpacket) < 8 {
err = errors.StructuralError("notation data subpacket with bad length")
return
@@ -398,15 +529,27 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
sig.Notations = append(sig.Notations, ¬ation)
case prefHashAlgosSubpacket:
- // Preferred hash algorithms, section 5.2.3.8
+ // Preferred hash algorithms, section 5.2.3.16
sig.PreferredHash = make([]byte, len(subpacket))
copy(sig.PreferredHash, subpacket)
case prefCompressionSubpacket:
- // Preferred compression algorithms, section 5.2.3.9
+ // Preferred compression algorithms, section 5.2.3.17
sig.PreferredCompression = make([]byte, len(subpacket))
copy(sig.PreferredCompression, subpacket)
+ case keyserverPrefsSubpacket:
+ // Keyserver preferences, section 5.2.3.25
+ sig.KeyserverPrefsValid = true
+ if len(subpacket) == 0 {
+ return
+ }
+ if subpacket[0]&KeyserverPrefNoModify != 0 {
+ sig.KeyserverPrefNoModify = true
+ }
+ case prefKeyserverSubpacket:
+ // Preferred keyserver, section 5.2.3.26
+ sig.PreferredKeyserver = string(subpacket)
case primaryUserIdSubpacket:
- // Primary User ID, section 5.2.3.19
+ // Primary User ID, section 5.2.3.27
if len(subpacket) != 1 {
err = errors.StructuralError("primary user id subpacket with bad length")
return
@@ -416,12 +559,11 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
*sig.IsPrimaryId = true
}
case keyFlagsSubpacket:
- // Key flags, section 5.2.3.21
+ // Key flags, section 5.2.3.29
+ sig.FlagsValid = true
if len(subpacket) == 0 {
- err = errors.StructuralError("empty key flags subpacket")
return
}
- sig.FlagsValid = true
if subpacket[0]&KeyFlagCertify != 0 {
sig.FlagCertify = true
}
@@ -447,16 +589,16 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
userId := string(subpacket)
sig.SignerUserId = &userId
case reasonForRevocationSubpacket:
- // Reason For Revocation, section 5.2.3.23
+ // Reason For Revocation, section 5.2.3.31
if len(subpacket) == 0 {
err = errors.StructuralError("empty revocation reason subpacket")
return
}
sig.RevocationReason = new(ReasonForRevocation)
- *sig.RevocationReason = ReasonForRevocation(subpacket[0])
+ *sig.RevocationReason = NewReasonForRevocation(subpacket[0])
sig.RevocationReasonText = string(subpacket[1:])
case featuresSubpacket:
- // Features subpacket, section 5.2.3.24 specifies a very general
+ // Features subpacket, section 5.2.3.32 specifies a very general
// mechanism for OpenPGP implementations to signal support for new
// features.
if len(subpacket) > 0 {
@@ -470,16 +612,13 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
}
case embeddedSignatureSubpacket:
// Only usage is in signatures that cross-certify
- // signing subkeys. section 5.2.3.26 describes the
+ // signing subkeys. section 5.2.3.34 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
}
@@ -487,7 +626,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
}
case policyUriSubpacket:
- // Policy URI, section 5.2.3.20
+ // Policy URI, section 5.2.3.28
sig.PolicyURI = string(subpacket)
case issuerFingerprintSubpacket:
if len(subpacket) == 0 {
@@ -495,20 +634,31 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
return
}
v, l := subpacket[0], len(subpacket[1:])
- if v == 5 && l != 32 || v != 5 && l != 20 {
+ if v >= 5 && l != 32 || v < 5 && l != 20 {
return nil, errors.StructuralError("bad fingerprint length")
}
sig.IssuerFingerprint = make([]byte, l)
copy(sig.IssuerFingerprint, subpacket[1:])
sig.IssuerKeyId = new(uint64)
- if v == 5 {
+ if v >= 5 {
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[1:9])
} else {
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[13:21])
}
+ case intendedRecipientSubpacket:
+ // Intended Recipient Fingerprint, section 5.2.3.36
+ if len(subpacket) < 1 {
+ return nil, errors.StructuralError("invalid intended recipient fingerpring length")
+ }
+ version, length := subpacket[0], len(subpacket[1:])
+ if version >= 5 && length != 32 || version < 5 && length != 20 {
+ return nil, errors.StructuralError("invalid fingerprint length")
+ }
+ fingerprint := make([]byte, length)
+ copy(fingerprint, subpacket[1:])
+ sig.IntendedRecipients = append(sig.IntendedRecipients, &Recipient{int(version), fingerprint})
case prefCipherSuitesSubpacket:
- // Preferred AEAD cipher suites
- // See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#name-preferred-aead-ciphersuites
+ // Preferred AEAD cipher suites, section 5.2.3.15
if len(subpacket)%2 != 0 {
err = errors.StructuralError("invalid aead cipher suite length")
return
@@ -550,9 +700,16 @@ func (sig *Signature) CheckKeyIdOrFingerprint(pk *PublicKey) bool {
return sig.IssuerKeyId != nil && *sig.IssuerKeyId == pk.KeyId
}
+func (sig *Signature) CheckKeyIdOrFingerprintExplicit(fingerprint []byte, keyId uint64) bool {
+ if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) >= 20 && fingerprint != nil {
+ return bytes.Equal(sig.IssuerFingerprint, fingerprint)
+ }
+ return sig.IssuerKeyId != nil && *sig.IssuerKeyId == keyId
+}
+
// serializeSubpacketLength marshals the given length into to.
func serializeSubpacketLength(to []byte, length int) int {
- // RFC 4880, Section 4.2.2.
+ // RFC 9580, Section 4.2.1.
if length < 192 {
to[0] = byte(length)
return 1
@@ -598,20 +755,19 @@ func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
to = to[n:]
}
}
- return
}
// SigExpired returns whether sig is a signature that has expired or is created
// in the future.
func (sig *Signature) SigExpired(currentTime time.Time) bool {
- if sig.CreationTime.After(currentTime) {
+ if sig.CreationTime.Unix() > currentTime.Unix() {
return true
}
if sig.SigLifetimeSecs == nil || *sig.SigLifetimeSecs == 0 {
return false
}
expiry := sig.CreationTime.Add(time.Duration(*sig.SigLifetimeSecs) * time.Second)
- return currentTime.After(expiry)
+ return currentTime.Unix() > expiry.Unix()
}
// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
@@ -635,20 +791,36 @@ func (sig *Signature) buildHashSuffix(hashedSubpackets []byte) (err error) {
uint8(sig.SigType),
uint8(sig.PubKeyAlgo),
uint8(hashId),
- uint8(len(hashedSubpackets) >> 8),
- uint8(len(hashedSubpackets)),
})
+ hashedSubpacketsLength := len(hashedSubpackets)
+ if sig.Version == 6 {
+ // v6 signatures store the length in 4 octets
+ hashedFields.Write([]byte{
+ uint8(hashedSubpacketsLength >> 24),
+ uint8(hashedSubpacketsLength >> 16),
+ uint8(hashedSubpacketsLength >> 8),
+ uint8(hashedSubpacketsLength),
+ })
+ } else {
+ hashedFields.Write([]byte{
+ uint8(hashedSubpacketsLength >> 8),
+ uint8(hashedSubpacketsLength),
+ })
+ }
+ lenPrefix := hashedFields.Len()
hashedFields.Write(hashedSubpackets)
- var l uint64 = uint64(6 + len(hashedSubpackets))
+ var l uint64 = uint64(lenPrefix + len(hashedSubpackets))
if sig.Version == 5 {
+ // v5 case
hashedFields.Write([]byte{0x05, 0xff})
hashedFields.Write([]byte{
uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32),
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
})
} else {
- hashedFields.Write([]byte{0x04, 0xff})
+ // v4 and v6 case
+ hashedFields.Write([]byte{byte(sig.Version), 0xff})
hashedFields.Write([]byte{
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
})
@@ -676,6 +848,67 @@ func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
return
}
+// PrepareSign must be called to create a hash object before Sign for v6 signatures.
+// The created hash object initially hashes a randomly generated salt
+// as required by v6 signatures. The generated salt is stored in sig. If the signature is not v6,
+// the method returns an empty hash object.
+// See RFC 9580 Section 5.2.4.
+func (sig *Signature) PrepareSign(config *Config) (hash.Hash, error) {
+ if !sig.Hash.Available() {
+ return nil, errors.UnsupportedError("hash function")
+ }
+ hasher := sig.Hash.New()
+ if sig.Version == 6 {
+ if sig.salt == nil {
+ var err error
+ sig.salt, err = SignatureSaltForHash(sig.Hash, config.Random())
+ if err != nil {
+ return nil, err
+ }
+ }
+ hasher.Write(sig.salt)
+ }
+ return hasher, nil
+}
+
+// SetSalt sets the signature salt for v6 signatures.
+// Assumes salt is generated correctly and checks if length matches.
+// If the signature is not v6, the method ignores the salt.
+// Use PrepareSign whenever possible instead of generating and
+// hashing the salt externally.
+// See RFC 9580 Section 5.2.4.
+func (sig *Signature) SetSalt(salt []byte) error {
+ if sig.Version == 6 {
+ expectedSaltLength, err := SaltLengthForHash(sig.Hash)
+ if err != nil {
+ return err
+ }
+ if salt == nil || len(salt) != expectedSaltLength {
+ return errors.InvalidArgumentError("unexpected salt size for the given hash algorithm")
+ }
+ sig.salt = salt
+ }
+ return nil
+}
+
+// PrepareVerify must be called to create a hash object before verifying v6 signatures.
+// The created hash object initially hashes the internally stored salt.
+// If the signature is not v6, the method returns an empty hash object.
+// See RFC 9580 Section 5.2.4.
+func (sig *Signature) PrepareVerify() (hash.Hash, error) {
+ if !sig.Hash.Available() {
+ return nil, errors.UnsupportedError("hash function")
+ }
+ hasher := sig.Hash.New()
+ if sig.Version == 6 {
+ if sig.salt == nil {
+ return nil, errors.StructuralError("v6 requires a salt for the hash to be signed")
+ }
+ hasher.Write(sig.salt)
+ }
+ return hasher, nil
+}
+
// 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.
@@ -686,6 +919,20 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
}
sig.Version = priv.PublicKey.Version
sig.IssuerFingerprint = priv.PublicKey.Fingerprint
+ if sig.Version < 6 && config.RandomizeSignaturesViaNotation() {
+ sig.removeNotationsWithName(SaltNotationName)
+ salt, err := SignatureSaltForHash(sig.Hash, config.Random())
+ if err != nil {
+ return err
+ }
+ notation := Notation{
+ Name: SaltNotationName,
+ Value: salt,
+ IsCritical: false,
+ IsHumanReadable: false,
+ }
+ sig.Notations = append(sig.Notations, ¬ation)
+ }
sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey)
if err != nil {
return err
@@ -715,8 +962,16 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
sig.DSASigS = new(encoding.MPI).SetBig(s)
}
case PubKeyAlgoECDSA:
- sk := priv.PrivateKey.(*ecdsa.PrivateKey)
- r, s, err := ecdsa.Sign(config.Random(), sk, digest)
+ var r, s *big.Int
+ if sk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
+ r, s, err = ecdsa.Sign(config.Random(), sk, 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 = new(encoding.MPI).SetBig(r)
@@ -729,6 +984,18 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
sig.EdDSASigR = encoding.NewMPI(r)
sig.EdDSASigS = encoding.NewMPI(s)
}
+ case PubKeyAlgoEd25519:
+ sk := priv.PrivateKey.(*ed25519.PrivateKey)
+ signature, err := ed25519.Sign(sk, digest)
+ if err == nil {
+ sig.EdSig = signature
+ }
+ case PubKeyAlgoEd448:
+ sk := priv.PrivateKey.(*ed448.PrivateKey)
+ signature, err := ed448.Sign(sk, digest)
+ if err == nil {
+ sig.EdSig = signature
+ }
default:
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
}
@@ -736,6 +1003,18 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
return
}
+// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA signature.
+func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
+ var ecsdaSig struct {
+ R, S *big.Int
+ }
+ _, err = asn1.Unmarshal(b, &ecsdaSig)
+ if err != nil {
+ return
+ }
+ return ecsdaSig.R, ecsdaSig.S, nil
+}
+
// SignUserId computes a signature from priv, asserting that pub is a valid
// key for the identity id. On success, the signature is stored in sig. Call
// Serialize to write it out.
@@ -744,11 +1023,32 @@ func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, co
if priv.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
- h, err := userIdSignatureHash(id, pub, sig.Hash)
+ prepareHash, err := sig.PrepareSign(config)
if err != nil {
return err
}
- return sig.Sign(h, priv, config)
+ if err := userIdSignatureHash(id, pub, prepareHash); err != nil {
+ return err
+ }
+ return sig.Sign(prepareHash, priv, config)
+}
+
+// SignDirectKeyBinding computes a signature from priv
+// 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) SignDirectKeyBinding(pub *PublicKey, priv *PrivateKey, config *Config) error {
+ if priv.Dummy() {
+ return errors.ErrDummyPrivateKey("dummy key found")
+ }
+ prepareHash, err := sig.PrepareSign(config)
+ if err != nil {
+ return err
+ }
+ if err := directKeySignatureHash(pub, prepareHash); err != nil {
+ return err
+ }
+ return sig.Sign(prepareHash, priv, config)
}
// CrossSignKey computes a signature from signingKey on pub hashed using hashKey. On success,
@@ -756,7 +1056,11 @@ func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, co
// If config is nil, sensible defaults will be used.
func (sig *Signature) CrossSignKey(pub *PublicKey, hashKey *PublicKey, signingKey *PrivateKey,
config *Config) error {
- h, err := keySignatureHash(hashKey, pub, sig.Hash)
+ prepareHash, err := sig.PrepareSign(config)
+ if err != nil {
+ return err
+ }
+ h, err := keySignatureHash(hashKey, pub, prepareHash)
if err != nil {
return err
}
@@ -770,7 +1074,11 @@ func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config)
if priv.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
- h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
+ prepareHash, err := sig.PrepareSign(config)
+ if err != nil {
+ return err
+ }
+ h, err := keySignatureHash(&priv.PublicKey, pub, prepareHash)
if err != nil {
return err
}
@@ -781,11 +1089,14 @@ func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config)
// stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) RevokeKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
- h, err := keyRevocationHash(pub, sig.Hash)
+ prepareHash, err := sig.PrepareSign(config)
if err != nil {
return err
}
- return sig.Sign(h, priv, config)
+ if err := keyRevocationHash(pub, prepareHash); err != nil {
+ return err
+ }
+ return sig.Sign(prepareHash, priv, config)
}
// RevokeSubkey computes a subkey revocation signature of pub using priv.
@@ -802,7 +1113,7 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
if len(sig.outSubpackets) == 0 {
sig.outSubpackets = sig.rawSubpackets
}
- if sig.RSASignature == nil && sig.DSASigR == nil && sig.ECDSASigR == nil && sig.EdDSASigR == nil {
+ if sig.RSASignature == nil && sig.DSASigR == nil && sig.ECDSASigR == nil && sig.EdDSASigR == nil && sig.EdSig == nil {
return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
}
@@ -819,16 +1130,24 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
case PubKeyAlgoEdDSA:
sigLength = int(sig.EdDSASigR.EncodedLength())
sigLength += int(sig.EdDSASigS.EncodedLength())
+ case PubKeyAlgoEd25519:
+ sigLength = ed25519.SignatureSize
+ case PubKeyAlgoEd448:
+ sigLength = ed448.SignatureSize
default:
panic("impossible")
}
+ hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
- length := len(sig.HashSuffix) - 6 /* trailer not included */ +
+ length := 4 + /* length of version|signature type|public-key algorithm|hash algorithm */
+ 2 /* length of hashed subpackets */ + hashedSubpacketsLen +
2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
2 /* hash tag */ + sigLength
- if sig.Version == 5 {
- length -= 4 // eight-octet instead of four-octet big endian
+ if sig.Version == 6 {
+ length += 4 + /* the two length fields are four-octet instead of two */
+ 1 + /* salt length */
+ len(sig.salt) /* length salt */
}
err = serializeHeader(w, packetTypeSignature, length)
if err != nil {
@@ -842,18 +1161,41 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
}
func (sig *Signature) serializeBody(w io.Writer) (err error) {
- hashedSubpacketsLen := uint16(uint16(sig.HashSuffix[4])<<8) | uint16(sig.HashSuffix[5])
- fields := sig.HashSuffix[:6+hashedSubpacketsLen]
+ var fields []byte
+ if sig.Version == 6 {
+ // v6 signatures use 4 octets for length
+ hashedSubpacketsLen :=
+ uint32(uint32(sig.HashSuffix[4])<<24) |
+ uint32(uint32(sig.HashSuffix[5])<<16) |
+ uint32(uint32(sig.HashSuffix[6])<<8) |
+ uint32(sig.HashSuffix[7])
+ fields = sig.HashSuffix[:8+hashedSubpacketsLen]
+ } else {
+ hashedSubpacketsLen := uint16(uint16(sig.HashSuffix[4])<<8) |
+ uint16(sig.HashSuffix[5])
+ fields = sig.HashSuffix[:6+hashedSubpacketsLen]
+
+ }
_, err = w.Write(fields)
if err != nil {
return
}
unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
- unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
- unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
- unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
- serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
+ var unhashedSubpackets []byte
+ if sig.Version == 6 {
+ unhashedSubpackets = make([]byte, 4+unhashedSubpacketsLen)
+ unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 24)
+ unhashedSubpackets[1] = byte(unhashedSubpacketsLen >> 16)
+ unhashedSubpackets[2] = byte(unhashedSubpacketsLen >> 8)
+ unhashedSubpackets[3] = byte(unhashedSubpacketsLen)
+ serializeSubpackets(unhashedSubpackets[4:], sig.outSubpackets, false)
+ } else {
+ 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 {
@@ -864,6 +1206,18 @@ func (sig *Signature) serializeBody(w io.Writer) (err error) {
return
}
+ if sig.Version == 6 {
+ // write salt for v6 signatures
+ _, err = w.Write([]byte{uint8(len(sig.salt))})
+ if err != nil {
+ return
+ }
+ _, err = w.Write(sig.salt)
+ if err != nil {
+ return
+ }
+ }
+
switch sig.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
_, err = w.Write(sig.RSASignature.EncodedBytes())
@@ -882,6 +1236,10 @@ func (sig *Signature) serializeBody(w io.Writer) (err error) {
return
}
_, err = w.Write(sig.EdDSASigS.EncodedBytes())
+ case PubKeyAlgoEd25519:
+ err = ed25519.WriteSignature(w, sig.EdSig)
+ case PubKeyAlgoEd448:
+ err = ed448.WriteSignature(w, sig.EdSig)
default:
panic("impossible")
}
@@ -899,28 +1257,81 @@ type outputSubpacket struct {
func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubpacket, err error) {
creationTime := make([]byte, 4)
binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
- subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
-
+ // Signature Creation Time
+ subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, true, creationTime})
+ // Signature Expiration Time
+ 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})
+ }
+ // Trust Signature
+ if sig.TrustLevel != 0 {
+ subpackets = append(subpackets, outputSubpacket{true, trustSubpacket, true, []byte{byte(sig.TrustLevel), byte(sig.TrustAmount)}})
+ }
+ // Regular Expression
+ if sig.TrustRegularExpression != nil {
+ // RFC specifies the string should be null-terminated; add a null byte to the end
+ subpackets = append(subpackets, outputSubpacket{true, regularExpressionSubpacket, true, []byte(*sig.TrustRegularExpression + "\000")})
+ }
+ // Key Expiration Time
+ 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})
+ }
+ // Preferred Symmetric Ciphers for v1 SEIPD
+ if len(sig.PreferredSymmetric) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
+ }
+ // Issuer Key ID
if sig.IssuerKeyId != nil && sig.Version == 4 {
keyId := make([]byte, 8)
binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
- subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
+ subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, true, keyId})
}
- if sig.IssuerFingerprint != nil {
- contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...)
- subpackets = append(subpackets, outputSubpacket{true, issuerFingerprintSubpacket, sig.Version == 5, contents})
+ // Notation Data
+ for _, notation := range sig.Notations {
+ subpackets = append(
+ subpackets,
+ outputSubpacket{
+ true,
+ notationDataSubpacket,
+ notation.IsCritical,
+ notation.getData(),
+ })
}
- if sig.SignerUserId != nil {
- subpackets = append(subpackets, outputSubpacket{true, signerUserIdSubpacket, false, []byte(*sig.SignerUserId)})
+ // Preferred Hash Algorithms
+ if len(sig.PreferredHash) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
}
- 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})
+ // Preferred Compression Algorithms
+ if len(sig.PreferredCompression) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
}
-
+ // Keyserver Preferences
+ // Keyserver preferences may only appear in self-signatures or certification signatures.
+ if sig.KeyserverPrefsValid {
+ var prefs byte
+ if sig.KeyserverPrefNoModify {
+ prefs |= KeyserverPrefNoModify
+ }
+ subpackets = append(subpackets, outputSubpacket{true, keyserverPrefsSubpacket, false, []byte{prefs}})
+ }
+ // Preferred Keyserver
+ if len(sig.PreferredKeyserver) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, prefKeyserverSubpacket, false, []uint8(sig.PreferredKeyserver)})
+ }
+ // Primary User ID
+ if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
+ subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
+ }
+ // Policy URI
+ if len(sig.PolicyURI) > 0 {
+ subpackets = append(subpackets, outputSubpacket{true, policyUriSubpacket, false, []uint8(sig.PolicyURI)})
+ }
+ // Key Flags
// Key flags may only appear in self-signatures or certification signatures.
-
if sig.FlagsValid {
var flags byte
if sig.FlagCertify {
@@ -944,22 +1355,19 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp
if sig.FlagGroupKey {
flags |= KeyFlagGroupKey
}
- subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
+ subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, true, []byte{flags}})
}
-
- for _, notation := range sig.Notations {
- subpackets = append(
- subpackets,
- outputSubpacket{
- true,
- notationDataSubpacket,
- notation.IsCritical,
- notation.getData(),
- })
+ // Signer's User ID
+ if sig.SignerUserId != nil {
+ subpackets = append(subpackets, outputSubpacket{true, signerUserIdSubpacket, false, []byte(*sig.SignerUserId)})
}
-
- // The following subpackets may only appear in self-signatures.
-
+ // Reason for Revocation
+ // Revocation reason appears only in revocation signatures and is serialized as per section 5.2.3.31.
+ if sig.RevocationReason != nil {
+ subpackets = append(subpackets, outputSubpacket{true, reasonForRevocationSubpacket, true,
+ append([]uint8{uint8(*sig.RevocationReason)}, []uint8(sig.RevocationReasonText)...)})
+ }
+ // Features
var features = byte(0x00)
if sig.SEIPDv1 {
features |= 0x01
@@ -967,46 +1375,36 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp
if sig.SEIPDv2 {
features |= 0x08
}
-
if features != 0x00 {
subpackets = append(subpackets, outputSubpacket{true, featuresSubpacket, false, []byte{features}})
}
-
- if sig.TrustLevel != 0 {
- subpackets = append(subpackets, outputSubpacket{true, trustSubpacket, true, []byte{byte(sig.TrustLevel), byte(sig.TrustAmount)}})
- }
-
- if sig.TrustRegularExpression != nil {
- // RFC specifies the string should be null-terminated; add a null byte to the end
- subpackets = append(subpackets, outputSubpacket{true, regularExpressionSubpacket, true, []byte(*sig.TrustRegularExpression + "\000")})
- }
-
- if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
- keyLifetime := make([]byte, 4)
- binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
- 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})
+ // Embedded Signature
+ // EmbeddedSignature appears only in subkeys capable of signing and is serialized as per section 5.2.3.34.
+ if sig.EmbeddedSignature != nil {
+ var buf bytes.Buffer
+ err = sig.EmbeddedSignature.serializeBody(&buf)
+ if err != nil {
+ return
+ }
+ subpackets = append(subpackets, outputSubpacket{true, embeddedSignatureSubpacket, true, buf.Bytes()})
}
-
- if len(sig.PreferredCompression) > 0 {
- subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
+ // Issuer Fingerprint
+ if sig.IssuerFingerprint != nil {
+ contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...)
+ subpackets = append(subpackets, outputSubpacket{true, issuerFingerprintSubpacket, sig.Version >= 5, contents})
}
-
- if len(sig.PolicyURI) > 0 {
- subpackets = append(subpackets, outputSubpacket{true, policyUriSubpacket, false, []uint8(sig.PolicyURI)})
+ // Intended Recipient Fingerprint
+ for _, recipient := range sig.IntendedRecipients {
+ subpackets = append(
+ subpackets,
+ outputSubpacket{
+ true,
+ intendedRecipientSubpacket,
+ false,
+ recipient.Serialize(),
+ })
}
-
+ // Preferred AEAD Ciphersuites
if len(sig.PreferredCipherSuites) > 0 {
serialized := make([]byte, len(sig.PreferredCipherSuites)*2)
for i, cipherSuite := range sig.PreferredCipherSuites {
@@ -1015,23 +1413,6 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp
}
subpackets = append(subpackets, outputSubpacket{true, prefCipherSuitesSubpacket, false, serialized})
}
-
- // Revocation reason appears only in revocation signatures and is serialized as per section 5.2.3.23.
- if sig.RevocationReason != nil {
- subpackets = append(subpackets, outputSubpacket{true, reasonForRevocationSubpacket, true,
- append([]uint8{uint8(*sig.RevocationReason)}, []uint8(sig.RevocationReasonText)...)})
- }
-
- // EmbeddedSignature appears only in subkeys capable of signing and is serialized as per section 5.2.3.26.
- if sig.EmbeddedSignature != nil {
- var buf bytes.Buffer
- err = sig.EmbeddedSignature.serializeBody(&buf)
- if err != nil {
- return
- }
- subpackets = append(subpackets, outputSubpacket{true, embeddedSignatureSubpacket, true, buf.Bytes()})
- }
-
return
}
@@ -1073,8 +1454,6 @@ func (sig *Signature) AddMetadataToHashSuffix() {
binary.BigEndian.PutUint32(buf[:], lit.Time)
suffix.Write(buf[:])
- // Update the counter and restore trailing bytes
- l = uint64(suffix.Len())
suffix.Write([]byte{0x05, 0xff})
suffix.Write([]byte{
uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32),
@@ -1082,3 +1461,49 @@ func (sig *Signature) AddMetadataToHashSuffix() {
})
sig.HashSuffix = suffix.Bytes()
}
+
+// SaltLengthForHash selects the required salt length for the given hash algorithm,
+// as per Table 23 (Hash algorithm registry) of the crypto refresh.
+// See RFC 9580 Section 9.5.
+func SaltLengthForHash(hash crypto.Hash) (int, error) {
+ switch hash {
+ case crypto.SHA256, crypto.SHA224, crypto.SHA3_256:
+ return 16, nil
+ case crypto.SHA384:
+ return 24, nil
+ case crypto.SHA512, crypto.SHA3_512:
+ return 32, nil
+ default:
+ return 0, errors.UnsupportedError("hash function not supported for V6 signatures")
+ }
+}
+
+// SignatureSaltForHash generates a random signature salt
+// with the length for the given hash algorithm.
+// See RFC 9580 Section 9.5.
+func SignatureSaltForHash(hash crypto.Hash, randReader io.Reader) ([]byte, error) {
+ saltLength, err := SaltLengthForHash(hash)
+ if err != nil {
+ return nil, err
+ }
+ salt := make([]byte, saltLength)
+ _, err = io.ReadFull(randReader, salt)
+ if err != nil {
+ return nil, err
+ }
+ return salt, nil
+}
+
+// removeNotationsWithName removes all notations in this signature with the given name.
+func (sig *Signature) removeNotationsWithName(name string) {
+ if sig == nil || sig.Notations == nil {
+ return
+ }
+ updatedNotations := make([]*Notation, 0, len(sig.Notations))
+ for _, notation := range sig.Notations {
+ if notation.Name != name {
+ updatedNotations = append(updatedNotations, notation)
+ }
+ }
+ sig.Notations = updatedNotations
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
index bac2b132..2812a1db 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
@@ -7,11 +7,13 @@ package packet
import (
"bytes"
"crypto/cipher"
+ "crypto/sha256"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/s2k"
+ "golang.org/x/crypto/hkdf"
)
// This is the largest session key that we'll support. Since at most 256-bit cipher
@@ -39,10 +41,21 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
return err
}
ske.Version = int(buf[0])
- if ske.Version != 4 && ske.Version != 5 {
+ if ske.Version != 4 && ske.Version != 5 && ske.Version != 6 {
return errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
}
+ if V5Disabled && ske.Version == 5 {
+ return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
+ }
+
+ if ske.Version > 5 {
+ // Scalar octet count
+ if _, err := readFull(r, buf[:]); err != nil {
+ return err
+ }
+ }
+
// Cipher function
if _, err := readFull(r, buf[:]); err != nil {
return err
@@ -52,7 +65,7 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[0])))
}
- if ske.Version == 5 {
+ if ske.Version >= 5 {
// AEAD mode
if _, err := readFull(r, buf[:]); err != nil {
return errors.StructuralError("cannot read AEAD octet from packet")
@@ -60,6 +73,13 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
ske.Mode = AEADMode(buf[0])
}
+ if ske.Version > 5 {
+ // Scalar octet count
+ if _, err := readFull(r, buf[:]); err != nil {
+ return err
+ }
+ }
+
var err error
if ske.s2k, err = s2k.Parse(r); err != nil {
if _, ok := err.(errors.ErrDummyPrivateKey); ok {
@@ -68,7 +88,7 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
return err
}
- if ske.Version == 5 {
+ if ske.Version >= 5 {
// AEAD IV
iv := make([]byte, ske.Mode.IvLength())
_, err := readFull(r, iv)
@@ -109,8 +129,8 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunc
case 4:
plaintextKey, cipherFunc, err := ske.decryptV4(key)
return plaintextKey, cipherFunc, err
- case 5:
- plaintextKey, err := ske.decryptV5(key)
+ case 5, 6:
+ plaintextKey, err := ske.aeadDecrypt(ske.Version, key)
return plaintextKey, CipherFunction(0), err
}
err := errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
@@ -136,9 +156,9 @@ func (ske *SymmetricKeyEncrypted) decryptV4(key []byte) ([]byte, CipherFunction,
return plaintextKey, cipherFunc, nil
}
-func (ske *SymmetricKeyEncrypted) decryptV5(key []byte) ([]byte, error) {
- adata := []byte{0xc3, byte(5), byte(ske.CipherFunc), byte(ske.Mode)}
- aead := getEncryptedKeyAeadInstance(ske.CipherFunc, ske.Mode, key, adata)
+func (ske *SymmetricKeyEncrypted) aeadDecrypt(version int, key []byte) ([]byte, error) {
+ adata := []byte{0xc3, byte(version), byte(ske.CipherFunc), byte(ske.Mode)}
+ aead := getEncryptedKeyAeadInstance(ske.CipherFunc, ske.Mode, key, adata, version)
plaintextKey, err := aead.Open(nil, ske.iv, ske.encryptedKey, adata)
if err != nil {
@@ -175,10 +195,22 @@ func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Conf
// the given passphrase. The returned session key must be passed to
// SerializeSymmetricallyEncrypted.
// If config is nil, sensible defaults will be used.
+// Deprecated: Use SerializeSymmetricKeyEncryptedAEADReuseKey instead.
func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, config *Config) (err error) {
+ return SerializeSymmetricKeyEncryptedAEADReuseKey(w, sessionKey, passphrase, config.AEAD() != nil, config)
+}
+
+// SerializeSymmetricKeyEncryptedAEADReuseKey serializes a symmetric key packet to w.
+// The packet contains the given session key, encrypted by a key derived from
+// the given passphrase. The returned session key must be passed to
+// SerializeSymmetricallyEncrypted.
+// If aeadSupported is set, SKESK v6 is used, otherwise v4.
+// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
+// If config is nil, sensible defaults will be used.
+func SerializeSymmetricKeyEncryptedAEADReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, aeadSupported bool, config *Config) (err error) {
var version int
- if config.AEAD() != nil {
- version = 5
+ if aeadSupported {
+ version = 6
} else {
version = 4
}
@@ -203,11 +235,15 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
switch version {
case 4:
packetLength = 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
- case 5:
+ case 5, 6:
ivLen := config.AEAD().Mode().IvLength()
tagLen := config.AEAD().Mode().TagLength()
packetLength = 3 + len(s2kBytes) + ivLen + keySize + tagLen
}
+ if version > 5 {
+ packetLength += 2 // additional octet count fields
+ }
+
err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
if err != nil {
return
@@ -216,13 +252,22 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
// Symmetric Key Encrypted Version
buf := []byte{byte(version)}
+ if version > 5 {
+ // Scalar octet count
+ buf = append(buf, byte(3+len(s2kBytes)+config.AEAD().Mode().IvLength()))
+ }
+
// Cipher function
buf = append(buf, byte(cipherFunc))
- if version == 5 {
+ if version >= 5 {
// AEAD mode
buf = append(buf, byte(config.AEAD().Mode()))
}
+ if version > 5 {
+ // Scalar octet count
+ buf = append(buf, byte(len(s2kBytes)))
+ }
_, err = w.Write(buf)
if err != nil {
return
@@ -243,10 +288,10 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
if err != nil {
return
}
- case 5:
+ case 5, 6:
mode := config.AEAD().Mode()
- adata := []byte{0xc3, byte(5), byte(cipherFunc), byte(mode)}
- aead := getEncryptedKeyAeadInstance(cipherFunc, mode, keyEncryptingKey, adata)
+ adata := []byte{0xc3, byte(version), byte(cipherFunc), byte(mode)}
+ aead := getEncryptedKeyAeadInstance(cipherFunc, mode, keyEncryptingKey, adata, version)
// Sample iv using random reader
iv := make([]byte, config.AEAD().Mode().IvLength())
@@ -270,7 +315,17 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass
return
}
-func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte) (aead cipher.AEAD) {
- blockCipher := c.new(inputKey)
+func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte, version int) (aead cipher.AEAD) {
+ var blockCipher cipher.Block
+ if version > 5 {
+ hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData)
+
+ encryptionKey := make([]byte, c.KeySize())
+ _, _ = readFull(hkdfReader, encryptionKey)
+
+ blockCipher = c.new(encryptionKey)
+ } else {
+ blockCipher = c.new(inputKey)
+ }
return mode.new(blockCipher)
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
index e9bbf032..0e898742 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
@@ -74,6 +74,10 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read
// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
// to w and returns a WriteCloser to which the to-be-encrypted packets can be
// written.
+// If aeadSupported is set to true, SEIPDv2 is used with the indicated CipherSuite.
+// Otherwise, SEIPDv1 is used with the indicated CipherFunction.
+// Note: aeadSupported MUST match the value passed to SerializeEncryptedKeyAEAD
+// and/or SerializeSymmetricKeyEncryptedAEADReuseKey.
// If config is nil, sensible defaults will be used.
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, aeadSupported bool, cipherSuite CipherSuite, key []byte, config *Config) (Contents io.WriteCloser, err error) {
writeCloser := noOpCloser{w}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
index e96252c1..3957b2d5 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
@@ -7,7 +7,9 @@ package packet
import (
"crypto/cipher"
"crypto/sha256"
+ "fmt"
"io"
+ "strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"golang.org/x/crypto/hkdf"
@@ -25,19 +27,19 @@ func (se *SymmetricallyEncrypted) parseAead(r io.Reader) error {
se.Cipher = CipherFunction(headerData[0])
// cipherFunc must have block size 16 to use AEAD
if se.Cipher.blockSize() != 16 {
- return errors.UnsupportedError("invalid aead cipher: " + string(se.Cipher))
+ return errors.UnsupportedError("invalid aead cipher: " + strconv.Itoa(int(se.Cipher)))
}
// Mode
se.Mode = AEADMode(headerData[1])
if se.Mode.TagLength() == 0 {
- return errors.UnsupportedError("unknown aead mode: " + string(se.Mode))
+ return errors.UnsupportedError("unknown aead mode: " + strconv.Itoa(int(se.Mode)))
}
// Chunk size
se.ChunkSizeByte = headerData[2]
if se.ChunkSizeByte > 16 {
- return errors.UnsupportedError("invalid aead chunk size byte: " + string(se.ChunkSizeByte))
+ return errors.UnsupportedError("invalid aead chunk size byte: " + strconv.Itoa(int(se.ChunkSizeByte)))
}
// Salt
@@ -62,8 +64,11 @@ func (se *SymmetricallyEncrypted) associatedData() []byte {
// decryptAead decrypts a V2 SEIPD packet (AEAD) as specified in
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, error) {
- aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData())
+ if se.Cipher.KeySize() != len(inputKey) {
+ return nil, errors.StructuralError(fmt.Sprintf("invalid session key length for cipher: got %d bytes, but expected %d bytes", len(inputKey), se.Cipher.KeySize()))
+ }
+ aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData())
// Carry the first tagLen bytes
tagLen := se.Mode.TagLength()
peekedBytes := make([]byte, tagLen)
@@ -115,7 +120,7 @@ func serializeSymmetricallyEncryptedAead(ciphertext io.WriteCloser, cipherSuite
// Random salt
salt := make([]byte, aeadSaltSize)
- if _, err := rand.Read(salt); err != nil {
+ if _, err := io.ReadFull(rand, salt); err != nil {
return nil, err
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
index fa26bebe..8b186236 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
@@ -148,7 +148,7 @@ const mdcPacketTagByte = byte(0x80) | 0x40 | 19
func (ser *seMDCReader) Close() error {
if ser.error {
- return errors.ErrMDCMissing
+ return errors.ErrMDCHashMismatch
}
for !ser.eof {
@@ -159,7 +159,7 @@ func (ser *seMDCReader) Close() error {
break
}
if err != nil {
- return errors.ErrMDCMissing
+ return errors.ErrMDCHashMismatch
}
}
@@ -172,7 +172,7 @@ func (ser *seMDCReader) Close() error {
// The hash already includes the MDC header, but we still check its value
// to confirm encryption correctness
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
- return errors.ErrMDCMissing
+ return errors.ErrMDCHashMismatch
}
return nil
}
@@ -237,9 +237,9 @@ func serializeSymmetricallyEncryptedMdc(ciphertext io.WriteCloser, c CipherFunct
block := c.new(key)
blockSize := block.BlockSize()
iv := make([]byte, blockSize)
- _, err = config.Random().Read(iv)
+ _, err = io.ReadFull(config.Random(), iv)
if err != nil {
- return
+ return nil, err
}
s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
_, err = ciphertext.Write(prefix)
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
index 88ec72c6..63814ed1 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
@@ -9,7 +9,6 @@ import (
"image"
"image/jpeg"
"io"
- "io/ioutil"
)
const UserAttrImageSubpacket = 1
@@ -63,7 +62,7 @@ func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute {
func (uat *UserAttribute) parse(r io.Reader) (err error) {
// RFC 4880, section 5.13
- b, err := ioutil.ReadAll(r)
+ b, err := io.ReadAll(r)
if err != nil {
return
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go
index 614fbafd..3c7451a3 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go
@@ -6,7 +6,6 @@ package packet
import (
"io"
- "io/ioutil"
"strings"
)
@@ -66,7 +65,7 @@ func NewUserId(name, comment, email string) *UserId {
func (uid *UserId) parse(r io.Reader) (err error) {
// RFC 4880, section 5.11
- b, err := ioutil.ReadAll(r)
+ b, err := io.ReadAll(r)
if err != nil {
return
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
index 8499c737..e6dd9b5f 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
@@ -46,6 +46,7 @@ type MessageDetails struct {
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.
+ SignedByFingerprint []byte // the key fingerprint 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.
@@ -117,7 +118,7 @@ ParsePackets:
// 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, packet.PubKeyAlgoECDH:
+ case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH, packet.PubKeyAlgoX25519, packet.PubKeyAlgoX448:
break
default:
continue
@@ -232,7 +233,7 @@ FindKey:
}
mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config)
if sensitiveParsingErr != nil {
- return nil, errors.StructuralError("parsing error")
+ return nil, errors.HandleSensitiveParsingError(sensitiveParsingErr, md.decrypted != nil)
}
return mdFinal, nil
}
@@ -270,13 +271,17 @@ FindLiteralData:
prevLast = true
}
- h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
+ h, wrappedHash, err = hashForSignature(p.Hash, p.SigType, p.Salt)
if err != nil {
md.SignatureError = err
}
md.IsSigned = true
+ if p.Version == 6 {
+ md.SignedByFingerprint = p.KeyFingerprint
+ }
md.SignedByKeyId = p.KeyId
+
if keyring != nil {
keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
if len(keys) > 0 {
@@ -292,7 +297,7 @@ FindLiteralData:
if md.IsSigned && md.SignatureError == nil {
md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config}
} else if md.decrypted != nil {
- md.UnverifiedBody = checkReader{md}
+ md.UnverifiedBody = &checkReader{md, false}
} else {
md.UnverifiedBody = md.LiteralData.Body
}
@@ -300,12 +305,22 @@ FindLiteralData:
return md, nil
}
+func wrapHashForSignature(hashFunc hash.Hash, sigType packet.SignatureType) (hash.Hash, error) {
+ switch sigType {
+ case packet.SigTypeBinary:
+ return hashFunc, nil
+ case packet.SigTypeText:
+ return NewCanonicalTextHash(hashFunc), nil
+ }
+ return nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
+}
+
// 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(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
+func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType, sigSalt []byte) (hash.Hash, hash.Hash, error) {
if _, ok := algorithm.HashToHashIdWithSha1(hashFunc); !ok {
return nil, nil, errors.UnsupportedError("unsupported hash function")
}
@@ -313,14 +328,19 @@ func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.
return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashFunc)))
}
h := hashFunc.New()
-
+ if sigSalt != nil {
+ h.Write(sigSalt)
+ }
+ wrappedHash, err := wrapHashForSignature(h, sigType)
+ if err != nil {
+ return nil, nil, err
+ }
switch sigType {
case packet.SigTypeBinary:
- return h, h, nil
+ return h, wrappedHash, nil
case packet.SigTypeText:
- return h, NewCanonicalTextHash(h), nil
+ return h, wrappedHash, nil
}
-
return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
}
@@ -328,21 +348,27 @@ func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.
// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
// MDC checks.
type checkReader struct {
- md *MessageDetails
+ md *MessageDetails
+ checked bool
}
-func (cr checkReader) Read(buf []byte) (int, error) {
+func (cr *checkReader) Read(buf []byte) (int, error) {
n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf)
if sensitiveParsingError == io.EOF {
+ if cr.checked {
+ // Only check once
+ return n, io.EOF
+ }
mdcErr := cr.md.decrypted.Close()
if mdcErr != nil {
return n, mdcErr
}
+ cr.checked = true
return n, io.EOF
}
if sensitiveParsingError != nil {
- return n, errors.StructuralError("parsing error")
+ return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
}
return n, nil
@@ -366,6 +392,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
scr.wrappedHash.Write(buf[:n])
}
+ readsDecryptedData := scr.md.decrypted != nil
if sensitiveParsingError == io.EOF {
var p packet.Packet
var readError error
@@ -384,7 +411,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
key := scr.md.SignedBy
signatureError := key.PublicKey.VerifySignature(scr.h, sig)
if signatureError == nil {
- signatureError = checkSignatureDetails(key, sig, scr.config)
+ signatureError = checkMessageSignatureDetails(key, sig, scr.config)
}
scr.md.Signature = sig
scr.md.SignatureError = signatureError
@@ -408,16 +435,15 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
// 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 {
- return n, mdcErr
+ if sensitiveParsingError := scr.md.decrypted.Close(); sensitiveParsingError != nil {
+ return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
}
}
return n, io.EOF
}
if sensitiveParsingError != nil {
- return n, errors.StructuralError("parsing error")
+ return n, errors.HandleSensitiveParsingError(sensitiveParsingError, readsDecryptedData)
}
return n, nil
@@ -428,14 +454,13 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
// if any, and a possible signature verification error.
// If the signer isn't known, ErrUnknownIssuer is returned.
func VerifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
- var expectedHashes []crypto.Hash
- return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
+ return verifyDetachedSignature(keyring, signed, signature, nil, false, config)
}
// VerifyDetachedSignatureAndHash performs the same actions as
// VerifyDetachedSignature and checks that the expected hash functions were used.
func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
- return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
+ return verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
}
// CheckDetachedSignature takes a signed file and a detached signature and
@@ -443,25 +468,24 @@ func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader
// signature verification error. If the signer isn't known,
// ErrUnknownIssuer is returned.
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
- var expectedHashes []crypto.Hash
- return CheckDetachedSignatureAndHash(keyring, signed, signature, expectedHashes, config)
+ _, signer, err = verifyDetachedSignature(keyring, signed, signature, nil, false, config)
+ return
}
// CheckDetachedSignatureAndHash performs the same actions as
// CheckDetachedSignature and checks that the expected hash functions were used.
func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) {
- _, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
+ _, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
return
}
-func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
+func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, checkHashes bool, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
var issuerKeyId uint64
var hashFunc crypto.Hash
var sigType packet.SignatureType
var keys []Key
var p packet.Packet
- expectedHashesLen := len(expectedHashes)
packets := packet.NewReader(signature)
for {
p, err = packets.Next()
@@ -483,16 +507,19 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
issuerKeyId = *sig.IssuerKeyId
hashFunc = sig.Hash
sigType = sig.SigType
-
- for i, expectedHash := range expectedHashes {
- if hashFunc == expectedHash {
- break
+ if checkHashes {
+ matchFound := false
+ // check for hashes
+ for _, expectedHash := range expectedHashes {
+ if hashFunc == expectedHash {
+ matchFound = true
+ break
+ }
}
- if i+1 == expectedHashesLen {
- return nil, nil, errors.StructuralError("hash algorithm mismatch with cleartext message headers")
+ if !matchFound {
+ return nil, nil, errors.StructuralError("hash algorithm or salt mismatch with cleartext message headers")
}
}
-
keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
if len(keys) > 0 {
break
@@ -503,7 +530,11 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
panic("unreachable")
}
- h, wrappedHash, err := hashForSignature(hashFunc, sigType)
+ h, err := sig.PrepareVerify()
+ if err != nil {
+ return nil, nil, err
+ }
+ wrappedHash, err := wrapHashForSignature(h, sigType)
if err != nil {
return nil, nil, err
}
@@ -515,7 +546,7 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
for _, key := range keys {
err = key.PublicKey.VerifySignature(h, sig)
if err == nil {
- return sig, key.Entity, checkSignatureDetails(&key, sig, config)
+ return sig, key.Entity, checkMessageSignatureDetails(&key, sig, config)
}
}
@@ -533,7 +564,7 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader,
return CheckDetachedSignature(keyring, signed, body, config)
}
-// checkSignatureDetails returns an error if:
+// checkMessageSignatureDetails returns an error if:
// - The signature (or one of the binding signatures mentioned below)
// has a unknown critical notation data subpacket
// - The primary key of the signing entity is revoked
@@ -551,15 +582,11 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader,
// NOTE: The order of these checks is important, as the caller may choose to
// ignore ErrSignatureExpired or ErrKeyExpired errors, but should never
// ignore any other errors.
-//
-// TODO: Also return an error if:
-// - The primary key is expired according to a direct-key signature
-// - (For V5 keys only:) The direct-key signature (exists and) is expired
-func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
+func checkMessageSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
now := config.Now()
- primaryIdentity := key.Entity.PrimaryIdentity()
+ primarySelfSignature, primaryIdentity := key.Entity.PrimarySelfSignature()
signedBySubKey := key.PublicKey != key.Entity.PrimaryKey
- sigsToCheck := []*packet.Signature{signature, primaryIdentity.SelfSignature}
+ sigsToCheck := []*packet.Signature{signature, primarySelfSignature}
if signedBySubKey {
sigsToCheck = append(sigsToCheck, key.SelfSignature, key.SelfSignature.EmbeddedSignature)
}
@@ -572,10 +599,10 @@ func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet
}
if key.Entity.Revoked(now) || // primary key is revoked
(signedBySubKey && key.Revoked(now)) || // subkey is revoked
- primaryIdentity.Revoked(now) { // primary identity is revoked
+ (primaryIdentity != nil && primaryIdentity.Revoked(now)) { // primary identity is revoked for v4
return errors.ErrKeyRevoked
}
- if key.Entity.PrimaryKey.KeyExpired(primaryIdentity.SelfSignature, now) { // primary key is expired
+ if key.Entity.PrimaryKey.KeyExpired(primarySelfSignature, now) { // primary key is expired
return errors.ErrKeyExpired
}
if signedBySubKey {
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
index db6dad5c..670d6022 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
@@ -26,6 +26,8 @@ const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a43129
const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
+const ed25519wX25519Key = "c54b0663877fe31b00000020f94da7bb48d60a61e567706a6587d0331999bb9d891a08242ead84543df895a3001972817b12be707e8d5f586ce61361201d344eb266a2c82fde6835762b65b0b7c2b1061f1b0a00000042058263877fe3030b090705150a0e080c021600029b03021e09222106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc905270902070200000000ad2820103e2d7d227ec0e6d7ce4471db36bfc97083253690271498a7ef0576c07faae14585b3b903b0127ec4fda2f023045a2ec76bcb4f9571a9651e14aee1137a1d668442c88f951e33c4ffd33fb9a17d511eed758fc6d9cc50cb5fd793b2039d5804c74b0663877fe319000000208693248367f9e5015db922f8f48095dda784987f2d5985b12fbad16caf5e4435004d600a4f794d44775c57a26e0feefed558e9afffd6ad0d582d57fb2ba2dcedb8c29b06181b0a0000002c050263877fe322a106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9021b0c00000000defa20a6e9186d9d5935fc8fe56314cdb527486a5a5120f9b762a235a729f039010a56b89c658568341fbef3b894e9834ad9bc72afae2f4c9c47a43855e65f1cb0a3f77bbc5f61085c1f8249fe4e7ca59af5f0bcee9398e0fa8d76e522e1d8ab42bb0d"
+
const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
@@ -160,18 +162,78 @@ TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw==
=IiS2
-----END PGP PRIVATE KEY BLOCK-----`
-// Generated with the above private key
-const v5PrivKeyMsg = `-----BEGIN PGP MESSAGE-----
-Version: OpenPGP.js v4.10.7
-Comment: https://openpgpjs.org
+// See OpenPGP crypto refresh Section A.3.
+const v6PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+xUsGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laMAGXKB
+exK+cH6NX1hs5hNhIB00TrJmosgv3mg1ditlsLfCsQYfGwoAAABCBYJjh3/jAwsJ
+BwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6
+2azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lwgyU2kCcUmKfvBXbAf6rh
+RYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaEQsiPlR4zxP/TP7mhfVEe
+7XWPxtnMUMtf15OyA51YBMdLBmOHf+MZAAAAIIaTJINn+eUBXbki+PSAld2nhJh/
+LVmFsS+60WyvXkQ1AE1gCk95TUR3XFeibg/u/tVY6a//1q0NWC1X+yui3O24wpsG
+GBsKAAAALAWCY4d/4wKbDCIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6
+2azJAAAAAAQBIKbpGG2dWTX8j+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDE
+M0g12vYxoWM8Y81W+bHBw805I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUr
+k0mXubZvyl4GBg==
+-----END PGP PRIVATE KEY BLOCK-----`
+
+// See OpenPGP crypto refresh merge request:
+// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/304
+const v6PrivKeyMsg = `-----BEGIN PGP MESSAGE-----
+
+wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO
+WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS
+aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l
+yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo
+bhF30A+IitsxxA==
+-----END PGP MESSAGE-----`
+
+// See OpenPGP crypto refresh merge request:
+// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/305
+const v6PrivKeyInlineSignMsg = `-----BEGIN PGP MESSAGE-----
-xA0DAQoWGTR7yYckZAIByxF1B21zZy50eHRfbIGSdGVzdMJ3BQEWCgAGBQJf
-bIGSACMiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVDQvAP9G
-y29VPonFXqi2zKkpZrvyvZxg+n5e8Nt9wNbuxeCd3QD/TtO2s+JvjrE4Siwv
-UQdl5MlBka1QSNbMq2Bz7XwNPg4=
-=6lbM
+wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO
+WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS
+aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l
+yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo
+bhF30A+IitsxxA==
-----END PGP MESSAGE-----`
+// See https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/274
+// decryption password: "correct horse battery staple"
+const v6ArgonSealedPrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+xYIGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laP9JgkC
+FARdb9ccngltHraRe25uHuyuAQQVtKipJ0+r5jL4dacGWSAheCWPpITYiyfyIOPS
+3gIDyg8f7strd1OB4+LZsUhcIjOMpVHgmiY/IutJkulneoBYwrEGHxsKAAAAQgWC
+Y4d/4wMLCQcFFQoOCAwCFgACmwMCHgkiIQbLGGxPBgmml+TVLfpscisMHx4nwYpW
+cI9lJewnutmsyQUnCQIHAgAAAACtKCAQPi19In7A5tfORHHbNr/JcIMlNpAnFJin
+7wV2wH+q4UWFs7kDsBJ+xP2i8CMEWi7Ha8tPlXGpZR4UruETeh1mhELIj5UeM8T/
+0z+5oX1RHu11j8bZzFDLX9eTsgOdWATHggZjh3/jGQAAACCGkySDZ/nlAV25Ivj0
+gJXdp4SYfy1ZhbEvutFsr15ENf0mCQIUBA5hhGgp2oaavg6mFUXcFMwBBBUuE8qf
+9Ock+xwusd+GAglBr5LVyr/lup3xxQvHXFSjjA2haXfoN6xUGRdDEHI6+uevKjVR
+v5oAxgu7eJpaXNjCmwYYGwoAAAAsBYJjh3/jApsMIiEGyxhsTwYJppfk1S36bHIr
+DB8eJ8GKVnCPZSXsJ7rZrMkAAAAABAEgpukYbZ1ZNfyP5WMUzbUnSGpaUSD5t2Ki
+Nacp8DkBClZRa2c3AMQzSDXa9jGhYzxjzVb5scHDzTkjyRZWRdTq8U6L4da+/+Kt
+ruh8m7Xo2ehSSFyWRSuTSZe5tm/KXgYG
+-----END PGP PRIVATE KEY BLOCK-----`
+
+const v4Key25519 = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+xUkEZB3qzRto01j2k2pwN5ux9w70stPinAdXULLr20CRW7U7h2GSeACch0M+
+qzQg8yjFQ8VBvu3uwgKH9senoHmj72lLSCLTmhFKzQR0ZXN0wogEEBsIAD4F
+gmQd6s0ECwkHCAmQIf45+TuC+xMDFQgKBBYAAgECGQECmwMCHgEWIQSWEzMi
+jJUHvyIbVKIh/jn5O4L7EwAAUhaHNlgudvxARdPPETUzVgjuWi+YIz8w1xIb
+lHQMvIrbe2sGCQIethpWofd0x7DHuv/ciHg+EoxJ/Td6h4pWtIoKx0kEZB3q
+zRm4CyA7quliq7yx08AoOqHTuuCgvpkSdEhpp3pEyejQOgBo0p6ywIiLPllY
+0t+jpNspHpAGfXID6oqjpYuJw3AfVRBlwnQEGBsIACoFgmQd6s0JkCH+Ofk7
+gvsTApsMFiEElhMzIoyVB78iG1SiIf45+TuC+xMAAGgQuN9G73446ykvJ/mL
+sCZ7zGFId2gBd1EnG0FTC4npfOKpck0X8dngByrCxU8LDSfvjsEp/xDAiKsQ
+aU71tdtNBQ==
+=e7jT
+-----END PGP PRIVATE KEY BLOCK-----`
+
const keyWithExpiredCrossSig = `-----BEGIN PGP PUBLIC KEY BLOCK-----
xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
@@ -272,3 +334,124 @@ AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY
hz3tYjKhoFTKEIq3y3Pp
=h/aX
-----END PGP PUBLIC KEY BLOCK-----`
+
+const keyv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+Comment: Bob's OpenPGP Transferable Secret Key
+
+lQVYBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
+/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz
+/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/
+5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3
+X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv
+9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0
+qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb
+SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb
+vLIwa3T4CyshfT0AEQEAAQAL/RZqbJW2IqQDCnJi4Ozm++gPqBPiX1RhTWSjwxfM
+cJKUZfzLj414rMKm6Jh1cwwGY9jekROhB9WmwaaKT8HtcIgrZNAlYzANGRCM4TLK
+3VskxfSwKKna8l+s+mZglqbAjUg3wmFuf9Tj2xcUZYmyRm1DEmcN2ZzpvRtHgX7z
+Wn1mAKUlSDJZSQks0zjuMNbupcpyJokdlkUg2+wBznBOTKzgMxVNC9b2g5/tMPUs
+hGGWmF1UH+7AHMTaS6dlmr2ZBIyogdnfUqdNg5sZwsxSNrbglKP4sqe7X61uEAIQ
+bD7rT3LonLbhkrj3I8wilUD8usIwt5IecoHhd9HziqZjRCc1BUBkboUEoyedbDV4
+i4qfsFZ6CEWoLuD5pW7dEp0M+WeuHXO164Rc+LnH6i1VQrpb1Okl4qO6ejIpIjBI
+1t3GshtUu/mwGBBxs60KBX5g77mFQ9lLCRj8lSYqOsHRKBhUp4qM869VA+fD0BRP
+fqPT0I9IH4Oa/A3jYJcg622GwQYA1LhnP208Waf6PkQSJ6kyr8ymY1yVh9VBE/g6
+fRDYA+pkqKnw9wfH2Qho3ysAA+OmVOX8Hldg+Pc0Zs0e5pCavb0En8iFLvTA0Q2E
+LR5rLue9uD7aFuKFU/VdcddY9Ww/vo4k5p/tVGp7F8RYCFn9rSjIWbfvvZi1q5Tx
++akoZbga+4qQ4WYzB/obdX6SCmi6BndcQ1QdjCCQU6gpYx0MddVERbIp9+2SXDyL
+hpxjSyz+RGsZi/9UAshT4txP4+MZBgDfK3ZqtW+h2/eMRxkANqOJpxSjMyLO/FXN
+WxzTDYeWtHNYiAlOwlQZEPOydZFty9IVzzNFQCIUCGjQ/nNyhw7adSgUk3+BXEx/
+MyJPYY0BYuhLxLYcrfQ9nrhaVKxRJj25SVHj2ASsiwGJRZW4CC3uw40OYxfKEvNC
+mer/VxM3kg8qqGf9KUzJ1dVdAvjyx2Hz6jY2qWCyRQ6IMjWHyd43C4r3jxooYKUC
+YnstRQyb/gCSKahveSEjo07CiXMr88UGALwzEr3npFAsPW3osGaFLj49y1oRe11E
+he9gCHFm+fuzbXrWmdPjYU5/ZdqdojzDqfu4ThfnipknpVUM1o6MQqkjM896FHm8
+zbKVFSMhEP6DPHSCexMFrrSgN03PdwHTO6iBaIBBFqmGY01tmJ03SxvSpiBPON9P
+NVvy/6UZFedTq8A07OUAxO62YUSNtT5pmK2vzs3SAZJmbFbMh+NN204TRI72GlqT
+t5hcfkuv8hrmwPS/ZR6q312mKQ6w/1pqO9qitCFCb2IgQmFiYmFnZSA8Ym9iQG9w
+ZW5wZ3AuZXhhbXBsZT6JAc4EEwEKADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgEC
+F4AWIQTRpm4aI7GCyZgPeIz7/MgqAV5zMAUCXaWe+gAKCRD7/MgqAV5zMG9sC/9U
+2T3RrqEbw533FPNfEflhEVRIZ8gDXKM8hU6cqqEzCmzZT6xYTe6sv4y+PJBGXJFX
+yhj0g6FDkSyboM5litOcTupURObVqMgA/Y4UKERznm4fzzH9qek85c4ljtLyNufe
+doL2pp3vkGtn7eD0QFRaLLmnxPKQ/TlZKdLE1G3u8Uot8QHicaR6GnAdc5UXQJE3
+BiV7jZuDyWmZ1cUNwJkKL6oRtp+ZNDOQCrLNLecKHcgCqrpjSQG5oouba1I1Q6Vl
+sP44dhA1nkmLHtxlTOzpeHj4jnk1FaXmyasurrrI5CgU/L2Oi39DGKTH/A/cywDN
+4ZplIQ9zR8enkbXquUZvFDe+Xz+6xRXtb5MwQyWODB3nHw85HocLwRoIN9WdQEI+
+L8a/56AuOwhs8llkSuiITjR7r9SgKJC2WlAHl7E8lhJ3VDW3ELC56KH308d6mwOG
+ZRAqIAKzM1T5FGjMBhq7ZV0eqdEntBh3EcOIfj2M8rg1MzJv+0mHZOIjByawikad
+BVgEXaWc8gEMANYwv1xsYyunXYK0X1vY/rP1NNPvhLyLIE7NpK90YNBj+xS1ldGD
+bUdZqZeef2xJe8gMQg05DoD1DF3GipZ0Ies65beh+d5hegb7N4pzh0LzrBrVNHar
+29b5ExdI7i4iYD5TO6Vr/qTUOiAN/byqELEzAb+L+b2DVz/RoCm4PIp1DU9ewcc2
+WB38Ofqut3nLYA5tqJ9XvAiEQme+qAVcM3ZFcaMt4I4dXhDZZNg+D9LiTWcxdUPB
+leu8iwDRjAgyAhPzpFp+nWoqWA81uIiULWD1Fj+IVoY3ZvgivoYOiEFBJ9lbb4te
+g9m5UT/AaVDTWuHzbspVlbiVe+qyB77C2daWzNyx6UYBPLOo4r0t0c91kbNE5lgj
+Z7xz6los0N1U8vq91EFSeQJoSQ62XWavYmlCLmdNT6BNfgh4icLsT7Vr1QMX9jzn
+JtTPxdXytSdHvpSpULsqJ016l0dtmONcK3z9mj5N5z0k1tg1AH970TGYOe2aUcSx
+IRDMXDOPyzEfjwARAQABAAv9F2CwsjS+Sjh1M1vegJbZjei4gF1HHpEM0K0PSXsp
+SfVvpR4AoSJ4He6CXSMWg0ot8XKtDuZoV9jnJaES5UL9pMAD7JwIOqZm/DYVJM5h
+OASCh1c356/wSbFbzRHPtUdZO9Q30WFNJM5pHbCJPjtNoRmRGkf71RxtvHBzy7np
+Ga+W6U/NVKHw0i0CYwMI0YlKDakYW3Pm+QL+gHZFvngGweTod0f9l2VLLAmeQR/c
++EZs7lNumhuZ8mXcwhUc9JQIhOkpO+wreDysEFkAcsKbkQP3UDUsA1gFx9pbMzT0
+tr1oZq2a4QBtxShHzP/ph7KLpN+6qtjks3xB/yjTgaGmtrwM8tSe0wD1RwXS+/1o
+BHpXTnQ7TfeOGUAu4KCoOQLv6ELpKWbRBLWuiPwMdbGpvVFALO8+kvKAg9/r+/ny
+zM2GQHY+J3Jh5JxPiJnHfXNZjIKLbFbIPdSKNyJBuazXW8xIa//mEHMI5OcvsZBK
+clAIp7LXzjEjKXIwHwDcTn9pBgDpdOKTHOtJ3JUKx0rWVsDH6wq6iKV/FTVSY5jl
+zN+puOEsskF1Lfxn9JsJihAVO3yNsp6RvkKtyNlFazaCVKtDAmkjoh60XNxcNRqr
+gCnwdpbgdHP6v/hvZY54ZaJjz6L2e8unNEkYLxDt8cmAyGPgH2XgL7giHIp9jrsQ
+aS381gnYwNX6wE1aEikgtY91nqJjwPlibF9avSyYQoMtEqM/1UjTjB2KdD/MitK5
+fP0VpvuXpNYZedmyq4UOMwdkiNMGAOrfmOeT0olgLrTMT5H97Cn3Yxbk13uXHNu/
+ZUZZNe8s+QtuLfUlKAJtLEUutN33TlWQY522FV0m17S+b80xJib3yZVJteVurrh5
+HSWHAM+zghQAvCesg5CLXa2dNMkTCmZKgCBvfDLZuZbjFwnwCI6u/NhOY9egKuUf
+SA/je/RXaT8m5VxLYMxwqQXKApzD87fv0tLPlVIEvjEsaf992tFEFSNPcG1l/jpd
+5AVXw6kKuf85UkJtYR1x2MkQDrqY1QX/XMw00kt8y9kMZUre19aCArcmor+hDhRJ
+E3Gt4QJrD9z/bICESw4b4z2DbgD/Xz9IXsA/r9cKiM1h5QMtXvuhyfVeM01enhxM
+GbOH3gjqqGNKysx0UODGEwr6AV9hAd8RWXMchJLaExK9J5SRawSg671ObAU24SdY
+vMQ9Z4kAQ2+1ReUZzf3ogSMRZtMT+d18gT6L90/y+APZIaoArLPhebIAGq39HLmJ
+26x3z0WAgrpA1kNsjXEXkoiZGPLKIGoe3hqJAbYEGAEKACAWIQTRpm4aI7GCyZgP
+eIz7/MgqAV5zMAUCXaWc8gIbDAAKCRD7/MgqAV5zMOn/C/9ugt+HZIwX308zI+QX
+c5vDLReuzmJ3ieE0DMO/uNSC+K1XEioSIZP91HeZJ2kbT9nn9fuReuoff0T0Dief
+rbwcIQQHFFkrqSp1K3VWmUGp2JrUsXFVdjy/fkBIjTd7c5boWljv/6wAsSfiv2V0
+JSM8EFU6TYXxswGjFVfc6X97tJNeIrXL+mpSmPPqy2bztcCCHkWS5lNLWQw+R7Vg
+71Fe6yBSNVrqC2/imYG2J9zlowjx1XU63Wdgqp2Wxt0l8OmsB/W80S1fRF5G4SDH
+s9HXglXXqPsBRZJYfP+VStm9L5P/sKjCcX6WtZR7yS6G8zj/X767MLK/djANvpPd
+NVniEke6hM3CNBXYPAMhQBMWhCulcoz+0lxi8L34rMN+Dsbma96psdUrn7uLaB91
+6we0CTfF8qqm7BsVAgalon/UUiuMY80U3ueoj3okiSTiHIjD/YtpXSPioC8nMng7
+xqAY9Bwizt4FWgXuLm1a4+So4V9j1TRCXd12Uc2l2RNmgDE=
+=miES
+-----END PGP PRIVATE KEY BLOCK-----
+`
+
+const certv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd
+fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA
+Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC
+X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI
+CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9
+M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA
+MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD
+AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF
+GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb
+DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7
+TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw==
+=IiS2
+-----END PGP PRIVATE KEY BLOCK-----
+`
+
+const msgv5Test = `-----BEGIN PGP MESSAGE-----
+
+wcDMA3wvqk35PDeyAQv+PcQiLsoYTH30nJYQh3j3cJaO2+jErtVCrIQRIU0+
+rmgMddERYST4A9mA0DQIiTI4FQ0Lp440D3BWCgpq3LlNWewGzduaWwym5rN6
+cwHz5ccDqOcqbd9X0GXXGy/ZH/ljSgzuVMIytMAXKdF/vrRrVgH/+I7cxvm9
+HwnhjMN5dF0j4aEt996H2T7cbtzSr2GN9SWGW8Gyu7I8Zx73hgrGUI7gDiJB
+Afaff+P6hfkkHSGOItr94dde8J/7AUF4VEwwxdVVPvsNEFyvv6gRIbYtOCa2
+6RE6h1V/QTxW2O7zZgzWALrE2ui0oaYr9QuqQSssd9CdgExLfdPbI+3/ZAnE
+v31Idzpk3/6ILiakYHtXkElPXvf46mCNpobty8ysT34irF+fy3C1p3oGwAsx
+5VDV9OSFU6z5U+UPbSPYAy9rkc5ZssuIKxCER2oTvZ2L8Q5cfUvEUiJtRGGn
+CJlHrVDdp3FssKv2tlKgLkvxJLyoOjuEkj44H1qRk+D02FzmmUT/0sAHAYYx
+lTir6mjHeLpcGjn4waUuWIAJyph8SxUexP60bic0L0NBa6Qp5SxxijKsPIDb
+FPHxWwfJSDZRrgUyYT7089YFB/ZM4FHyH9TZcnxn0f0xIB7NS6YNDsxzN2zT
+EVEYf+De4qT/dQTsdww78Chtcv9JY9r2kDm77dk2MUGHL2j7n8jasbLtgA7h
+pn2DMIWLrGamMLWRmlwslolKr1sMV5x8w+5Ias6C33iBMl9phkg42an0gYmc
+byVJHvLO/XErtC+GNIJeMg==
+=liRq
+-----END PGP MESSAGE-----
+`
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
index a4369596..6871b84f 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
@@ -87,10 +87,10 @@ func decodeCount(c uint8) int {
// encodeMemory converts the Argon2 "memory" in the range parallelism*8 to
// 2**31, inclusive, to an encoded memory. The return value is the
// octet that is actually stored in the GPG file. encodeMemory panics
-// if is not in the above range
+// if is not in the above range
// See OpenPGP crypto refresh Section 3.7.1.4.
func encodeMemory(memory uint32, parallelism uint8) uint8 {
- if memory < (8 * uint32(parallelism)) || memory > uint32(2147483648) {
+ if memory < (8*uint32(parallelism)) || memory > uint32(2147483648) {
panic("Memory argument memory is outside the required range")
}
@@ -199,8 +199,8 @@ func Generate(rand io.Reader, c *Config) (*Params, error) {
}
params = &Params{
- mode: SaltedS2K,
- hashId: hashId,
+ mode: SaltedS2K,
+ hashId: hashId,
}
} else { // Enforce IteratedSaltedS2K method otherwise
hashId, ok := algorithm.HashToHashId(c.hash())
@@ -211,7 +211,7 @@ func Generate(rand io.Reader, c *Config) (*Params, error) {
c.S2KMode = IteratedSaltedS2K
}
params = &Params{
- mode: IteratedSaltedS2K,
+ mode: IteratedSaltedS2K,
hashId: hashId,
countByte: c.EncodedCount(),
}
@@ -283,6 +283,9 @@ func ParseIntoParams(r io.Reader) (params *Params, err error) {
params.passes = buf[Argon2SaltSize]
params.parallelism = buf[Argon2SaltSize+1]
params.memoryExp = buf[Argon2SaltSize+2]
+ if err := validateArgon2Params(params); err != nil {
+ return nil, err
+ }
return params, nil
case GnuS2K:
// This is a GNU extension. See
@@ -300,15 +303,22 @@ func ParseIntoParams(r io.Reader) (params *Params, err error) {
return nil, errors.UnsupportedError("S2K function")
}
+func (params *Params) Mode() Mode {
+ return params.mode
+}
+
func (params *Params) Dummy() bool {
return params != nil && params.mode == GnuS2K
}
func (params *Params) salt() []byte {
switch params.mode {
- case SaltedS2K, IteratedSaltedS2K: return params.saltBytes[:8]
- case Argon2S2K: return params.saltBytes[:Argon2SaltSize]
- default: return nil
+ case SaltedS2K, IteratedSaltedS2K:
+ return params.saltBytes[:8]
+ case Argon2S2K:
+ return params.saltBytes[:Argon2SaltSize]
+ default:
+ return nil
}
}
@@ -405,3 +415,22 @@ func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Co
f(key, passphrase)
return nil
}
+
+// validateArgon2Params checks that the argon2 parameters are valid according to RFC9580.
+func validateArgon2Params(params *Params) error {
+ // The number of passes t and the degree of parallelism p MUST be non-zero.
+ if params.parallelism == 0 {
+ return errors.StructuralError("invalid argon2 params: parallelism is 0")
+ }
+ if params.passes == 0 {
+ return errors.StructuralError("invalid argon2 params: iterations is 0")
+ }
+
+ // The encoded memory size MUST be a value from 3+ceil(log2(p)) to 31,
+ // such that the decoded memory size m is a value from 8*p to 2^31.
+ if params.memoryExp > 31 || decodeMemory(params.memoryExp) < 8*uint32(params.parallelism) {
+ return errors.StructuralError("invalid argon2 params: memory is out of bounds")
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go
index 25a4442d..616e0d12 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go
@@ -5,7 +5,7 @@ package s2k
// the same parameters.
type Cache map[Params][]byte
-// GetOrComputeDerivedKey tries to retrieve the key
+// GetOrComputeDerivedKey tries to retrieve the key
// for the given s2k parameters from the cache.
// If there is no hit, it derives the key with the s2k function from the passphrase,
// updates the cache, and returns the key.
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
index b40be522..b93db1ab 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
@@ -50,9 +50,9 @@ type Config struct {
type Argon2Config struct {
NumberOfPasses uint8
DegreeOfParallelism uint8
- // The memory parameter for Argon2 specifies desired memory usage in kibibytes.
+ // Memory specifies the desired Argon2 memory usage in kibibytes.
// For example memory=64*1024 sets the memory cost to ~64 MB.
- Memory uint32
+ Memory uint32
}
func (c *Config) Mode() Mode {
@@ -115,7 +115,7 @@ func (c *Argon2Config) EncodedMemory() uint8 {
}
memory := c.Memory
- lowerBound := uint32(c.Parallelism())*8
+ lowerBound := uint32(c.Parallelism()) * 8
upperBound := uint32(2147483648)
switch {
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
index 7fdd13a3..b0f6ef7b 100644
--- a/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
@@ -76,7 +76,11 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
sig := createSignaturePacket(signingKey.PublicKey, sigType, config)
- h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
+ h, err := sig.PrepareSign(config)
+ if err != nil {
+ return
+ }
+ wrappedHash, err := wrapHashForSignature(h, sig.SigType)
if err != nil {
return
}
@@ -275,14 +279,28 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
}
+ var salt []byte
if signer != nil {
+ var opsVersion = 3
+ if signer.Version == 6 {
+ opsVersion = signer.Version
+ }
ops := &packet.OnePassSignature{
+ Version: opsVersion,
SigType: sigType,
Hash: hash,
PubKeyAlgo: signer.PubKeyAlgo,
KeyId: signer.KeyId,
IsLast: true,
}
+ if opsVersion == 6 {
+ ops.KeyFingerprint = signer.Fingerprint
+ salt, err = packet.SignatureSaltForHash(hash, config.Random())
+ if err != nil {
+ return nil, err
+ }
+ ops.Salt = salt
+ }
if err := ops.Serialize(payload); err != nil {
return nil, err
}
@@ -310,19 +328,19 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
}
if signer != nil {
- h, wrappedHash, err := hashForSignature(hash, sigType)
+ h, wrappedHash, err := hashForSignature(hash, sigType, salt)
if err != nil {
return nil, err
}
metadata := &packet.LiteralData{
- Format: 't',
+ Format: 'u',
FileName: hints.FileName,
Time: epochSeconds,
}
if hints.IsBinary {
metadata.Format = 'b'
}
- return signatureWriter{payload, literalData, hash, wrappedHash, h, signer, sigType, config, metadata}, nil
+ return signatureWriter{payload, literalData, hash, wrappedHash, h, salt, signer, sigType, config, metadata}, nil
}
return literalData, nil
}
@@ -380,15 +398,19 @@ func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *En
return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no valid encryption keys")
}
- sig := to[i].PrimaryIdentity().SelfSignature
- if !sig.SEIPDv2 {
+ primarySelfSignature, _ := to[i].PrimarySelfSignature()
+ if primarySelfSignature == nil {
+ return nil, errors.InvalidArgumentError("entity without a self-signature")
+ }
+
+ if !primarySelfSignature.SEIPDv2 {
aeadSupported = false
}
- candidateCiphers = intersectPreferences(candidateCiphers, sig.PreferredSymmetric)
- candidateHashes = intersectPreferences(candidateHashes, sig.PreferredHash)
- candidateCipherSuites = intersectCipherSuites(candidateCipherSuites, sig.PreferredCipherSuites)
- candidateCompression = intersectPreferences(candidateCompression, sig.PreferredCompression)
+ candidateCiphers = intersectPreferences(candidateCiphers, primarySelfSignature.PreferredSymmetric)
+ candidateHashes = intersectPreferences(candidateHashes, primarySelfSignature.PreferredHash)
+ candidateCipherSuites = intersectCipherSuites(candidateCipherSuites, primarySelfSignature.PreferredCipherSuites)
+ candidateCompression = intersectPreferences(candidateCompression, primarySelfSignature.PreferredCompression)
}
// In the event that the intersection of supported algorithms is empty we use the ones
@@ -422,13 +444,19 @@ func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *En
}
}
- symKey := make([]byte, cipher.KeySize())
+ var symKey []byte
+ if aeadSupported {
+ symKey = make([]byte, aeadCipherSuite.Cipher.KeySize())
+ } else {
+ 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(keyWriter, key.PublicKey, cipher, symKey, config); err != nil {
+ if err := packet.SerializeEncryptedKeyAEAD(keyWriter, key.PublicKey, cipher, aeadSupported, symKey, config); err != nil {
return nil, err
}
}
@@ -465,13 +493,17 @@ func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Con
hashToHashId(crypto.SHA3_512),
}
defaultHashes := candidateHashes[0:1]
- preferredHashes := signed.PrimaryIdentity().SelfSignature.PreferredHash
+ primarySelfSignature, _ := signed.PrimarySelfSignature()
+ if primarySelfSignature == nil {
+ return nil, errors.StructuralError("signed entity has no self-signature")
+ }
+ preferredHashes := primarySelfSignature.PreferredHash
if len(preferredHashes) == 0 {
preferredHashes = defaultHashes
}
candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
if len(candidateHashes) == 0 {
- return nil, errors.InvalidArgumentError("cannot sign because signing key shares no common algorithms with candidate hashes")
+ return nil, errors.StructuralError("cannot sign because signing key shares no common algorithms with candidate hashes")
}
return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, packet.SigTypeBinary, config)
@@ -486,6 +518,7 @@ type signatureWriter struct {
hashType crypto.Hash
wrappedHash hash.Hash
h hash.Hash
+ salt []byte // v6 only
signer *packet.PrivateKey
sigType packet.SignatureType
config *packet.Config
@@ -509,6 +542,10 @@ func (s signatureWriter) Close() error {
sig.Hash = s.hashType
sig.Metadata = s.metadata
+ if err := sig.SetSalt(s.salt); err != nil {
+ return err
+ }
+
if err := sig.Sign(s.h, s.signer, s.config); err != nil {
return err
}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go
new file mode 100644
index 00000000..38afcc74
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go
@@ -0,0 +1,221 @@
+package x25519
+
+import (
+ "crypto/sha256"
+ "crypto/subtle"
+ "io"
+
+ "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+ x25519lib "github.com/cloudflare/circl/dh/x25519"
+ "golang.org/x/crypto/hkdf"
+)
+
+const (
+ hkdfInfo = "OpenPGP X25519"
+ aes128KeySize = 16
+ // The size of a public or private key in bytes.
+ KeySize = x25519lib.Size
+)
+
+type PublicKey struct {
+ // Point represents the encoded elliptic curve point of the public key.
+ Point []byte
+}
+
+type PrivateKey struct {
+ PublicKey
+ // Secret represents the secret of the private key.
+ Secret []byte
+}
+
+// NewPrivateKey creates a new empty private key including the public key.
+func NewPrivateKey(key PublicKey) *PrivateKey {
+ return &PrivateKey{
+ PublicKey: key,
+ }
+}
+
+// Validate validates that the provided public key matches the private key.
+func Validate(pk *PrivateKey) (err error) {
+ var expectedPublicKey, privateKey x25519lib.Key
+ subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret)
+ x25519lib.KeyGen(&expectedPublicKey, &privateKey)
+ if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 {
+ return errors.KeyInvalidError("x25519: invalid key")
+ }
+ return nil
+}
+
+// GenerateKey generates a new x25519 key pair.
+func GenerateKey(rand io.Reader) (*PrivateKey, error) {
+ var privateKey, publicKey x25519lib.Key
+ privateKeyOut := new(PrivateKey)
+ err := generateKey(rand, &privateKey, &publicKey)
+ if err != nil {
+ return nil, err
+ }
+ privateKeyOut.PublicKey.Point = publicKey[:]
+ privateKeyOut.Secret = privateKey[:]
+ return privateKeyOut, nil
+}
+
+func generateKey(rand io.Reader, privateKey *x25519lib.Key, publicKey *x25519lib.Key) error {
+ maxRounds := 10
+ isZero := true
+ for round := 0; isZero; round++ {
+ if round == maxRounds {
+ return errors.InvalidArgumentError("x25519: zero keys only, randomness source might be corrupt")
+ }
+ _, err := io.ReadFull(rand, privateKey[:])
+ if err != nil {
+ return err
+ }
+ isZero = constantTimeIsZero(privateKey[:])
+ }
+ x25519lib.KeyGen(publicKey, privateKey)
+ return nil
+}
+
+// Encrypt encrypts a sessionKey with x25519 according to
+// the OpenPGP crypto refresh specification section 5.1.6. The function assumes that the
+// sessionKey has the correct format and padding according to the specification.
+func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) {
+ var ephemeralPrivate, ephemeralPublic, staticPublic, shared x25519lib.Key
+ // Check that the input static public key has 32 bytes
+ if len(publicKey.Point) != KeySize {
+ err = errors.KeyInvalidError("x25519: the public key has the wrong size")
+ return
+ }
+ copy(staticPublic[:], publicKey.Point)
+ // Generate ephemeral keyPair
+ err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic)
+ if err != nil {
+ return
+ }
+ // Compute shared key
+ ok := x25519lib.Shared(&shared, &ephemeralPrivate, &staticPublic)
+ if !ok {
+ err = errors.KeyInvalidError("x25519: the public key is a low order point")
+ return
+ }
+ // Derive the encryption key from the shared secret
+ encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:])
+ ephemeralPublicKey = &PublicKey{
+ Point: ephemeralPublic[:],
+ }
+ // Encrypt the sessionKey with aes key wrapping
+ encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey)
+ return
+}
+
+// Decrypt decrypts a session key stored in ciphertext with the provided x25519
+// private key and ephemeral public key.
+func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) {
+ var ephemeralPublic, staticPrivate, shared x25519lib.Key
+ // Check that the input ephemeral public key has 32 bytes
+ if len(ephemeralPublicKey.Point) != KeySize {
+ err = errors.KeyInvalidError("x25519: the public key has the wrong size")
+ return
+ }
+ copy(ephemeralPublic[:], ephemeralPublicKey.Point)
+ subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret)
+ // Compute shared key
+ ok := x25519lib.Shared(&shared, &staticPrivate, &ephemeralPublic)
+ if !ok {
+ err = errors.KeyInvalidError("x25519: the ephemeral public key is a low order point")
+ return
+ }
+ // Derive the encryption key from the shared secret
+ encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:])
+ // Decrypt the session key with aes key wrapping
+ encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext)
+ return
+}
+
+func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte {
+ inputKey := make([]byte, 3*KeySize)
+ // ephemeral public key | recipient public key | shared secret
+ subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey)
+ subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey)
+ subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret)
+ hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, []byte(hkdfInfo))
+ encryptionKey := make([]byte, aes128KeySize)
+ _, _ = io.ReadFull(hkdfReader, encryptionKey)
+ return encryptionKey
+}
+
+func constantTimeIsZero(bytes []byte) bool {
+ isZero := byte(0)
+ for _, b := range bytes {
+ isZero |= b
+ }
+ return isZero == 0
+}
+
+// ENCODING/DECODING ciphertexts:
+
+// EncodeFieldsLength returns the length of the ciphertext encoding
+// given the encrypted session key.
+func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int {
+ lenCipherFunction := 0
+ if !v6 {
+ lenCipherFunction = 1
+ }
+ return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction
+}
+
+// EncodeField encodes x25519 session key encryption fields as
+// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey
+// and writes it to writer.
+func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) {
+ lenAlgorithm := 0
+ if !v6 {
+ lenAlgorithm = 1
+ }
+ if _, err = writer.Write(ephemeralPublicKey.Point); err != nil {
+ return err
+ }
+ if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil {
+ return err
+ }
+ if !v6 {
+ if _, err = writer.Write([]byte{cipherFunction}); err != nil {
+ return err
+ }
+ }
+ _, err = writer.Write(encryptedSessionKey)
+ return err
+}
+
+// DecodeField decodes a x25519 session key encryption as
+// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey.
+func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) {
+ var buf [1]byte
+ ephemeralPublicKey = &PublicKey{
+ Point: make([]byte, KeySize),
+ }
+ // 32 octets representing an ephemeral x25519 public key.
+ if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil {
+ return nil, nil, 0, err
+ }
+ // A one-octet size of the following fields.
+ if _, err = io.ReadFull(reader, buf[:]); err != nil {
+ return nil, nil, 0, err
+ }
+ followingLen := buf[0]
+ // The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
+ if !v6 {
+ if _, err = io.ReadFull(reader, buf[:]); err != nil {
+ return nil, nil, 0, err
+ }
+ cipherFunction = buf[0]
+ followingLen -= 1
+ }
+ // The encrypted session key.
+ encryptedSessionKey = make([]byte, followingLen)
+ if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil {
+ return nil, nil, 0, err
+ }
+ return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil
+}
diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go
new file mode 100644
index 00000000..65a082da
--- /dev/null
+++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go
@@ -0,0 +1,229 @@
+package x448
+
+import (
+ "crypto/sha512"
+ "crypto/subtle"
+ "io"
+
+ "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
+ "github.com/ProtonMail/go-crypto/openpgp/errors"
+ x448lib "github.com/cloudflare/circl/dh/x448"
+ "golang.org/x/crypto/hkdf"
+)
+
+const (
+ hkdfInfo = "OpenPGP X448"
+ aes256KeySize = 32
+ // The size of a public or private key in bytes.
+ KeySize = x448lib.Size
+)
+
+type PublicKey struct {
+ // Point represents the encoded elliptic curve point of the public key.
+ Point []byte
+}
+
+type PrivateKey struct {
+ PublicKey
+ // Secret represents the secret of the private key.
+ Secret []byte
+}
+
+// NewPrivateKey creates a new empty private key including the public key.
+func NewPrivateKey(key PublicKey) *PrivateKey {
+ return &PrivateKey{
+ PublicKey: key,
+ }
+}
+
+// Validate validates that the provided public key matches
+// the private key.
+func Validate(pk *PrivateKey) (err error) {
+ var expectedPublicKey, privateKey x448lib.Key
+ subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret)
+ x448lib.KeyGen(&expectedPublicKey, &privateKey)
+ if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 {
+ return errors.KeyInvalidError("x448: invalid key")
+ }
+ return nil
+}
+
+// GenerateKey generates a new x448 key pair.
+func GenerateKey(rand io.Reader) (*PrivateKey, error) {
+ var privateKey, publicKey x448lib.Key
+ privateKeyOut := new(PrivateKey)
+ err := generateKey(rand, &privateKey, &publicKey)
+ if err != nil {
+ return nil, err
+ }
+ privateKeyOut.PublicKey.Point = publicKey[:]
+ privateKeyOut.Secret = privateKey[:]
+ return privateKeyOut, nil
+}
+
+func generateKey(rand io.Reader, privateKey *x448lib.Key, publicKey *x448lib.Key) error {
+ maxRounds := 10
+ isZero := true
+ for round := 0; isZero; round++ {
+ if round == maxRounds {
+ return errors.InvalidArgumentError("x448: zero keys only, randomness source might be corrupt")
+ }
+ _, err := io.ReadFull(rand, privateKey[:])
+ if err != nil {
+ return err
+ }
+ isZero = constantTimeIsZero(privateKey[:])
+ }
+ x448lib.KeyGen(publicKey, privateKey)
+ return nil
+}
+
+// Encrypt encrypts a sessionKey with x448 according to
+// the OpenPGP crypto refresh specification section 5.1.7. The function assumes that the
+// sessionKey has the correct format and padding according to the specification.
+func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) {
+ var ephemeralPrivate, ephemeralPublic, staticPublic, shared x448lib.Key
+ // Check that the input static public key has 56 bytes.
+ if len(publicKey.Point) != KeySize {
+ err = errors.KeyInvalidError("x448: the public key has the wrong size")
+ return nil, nil, err
+ }
+ copy(staticPublic[:], publicKey.Point)
+ // Generate ephemeral keyPair.
+ if err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic); err != nil {
+ return nil, nil, err
+ }
+ // Compute shared key.
+ ok := x448lib.Shared(&shared, &ephemeralPrivate, &staticPublic)
+ if !ok {
+ err = errors.KeyInvalidError("x448: the public key is a low order point")
+ return nil, nil, err
+ }
+ // Derive the encryption key from the shared secret.
+ encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:])
+ ephemeralPublicKey = &PublicKey{
+ Point: ephemeralPublic[:],
+ }
+ // Encrypt the sessionKey with aes key wrapping.
+ encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ return ephemeralPublicKey, encryptedSessionKey, nil
+}
+
+// Decrypt decrypts a session key stored in ciphertext with the provided x448
+// private key and ephemeral public key.
+func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) {
+ var ephemeralPublic, staticPrivate, shared x448lib.Key
+ // Check that the input ephemeral public key has 56 bytes.
+ if len(ephemeralPublicKey.Point) != KeySize {
+ err = errors.KeyInvalidError("x448: the public key has the wrong size")
+ return nil, err
+ }
+ copy(ephemeralPublic[:], ephemeralPublicKey.Point)
+ subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret)
+ // Compute shared key.
+ ok := x448lib.Shared(&shared, &staticPrivate, &ephemeralPublic)
+ if !ok {
+ err = errors.KeyInvalidError("x448: the ephemeral public key is a low order point")
+ return nil, err
+ }
+ // Derive the encryption key from the shared secret.
+ encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:])
+ // Decrypt the session key with aes key wrapping.
+ encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext)
+ if err != nil {
+ return nil, err
+ }
+ return encodedSessionKey, nil
+}
+
+func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte {
+ inputKey := make([]byte, 3*KeySize)
+ // ephemeral public key | recipient public key | shared secret.
+ subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey)
+ subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey)
+ subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret)
+ hkdfReader := hkdf.New(sha512.New, inputKey, []byte{}, []byte(hkdfInfo))
+ encryptionKey := make([]byte, aes256KeySize)
+ _, _ = io.ReadFull(hkdfReader, encryptionKey)
+ return encryptionKey
+}
+
+func constantTimeIsZero(bytes []byte) bool {
+ isZero := byte(0)
+ for _, b := range bytes {
+ isZero |= b
+ }
+ return isZero == 0
+}
+
+// ENCODING/DECODING ciphertexts:
+
+// EncodeFieldsLength returns the length of the ciphertext encoding
+// given the encrypted session key.
+func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int {
+ lenCipherFunction := 0
+ if !v6 {
+ lenCipherFunction = 1
+ }
+ return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction
+}
+
+// EncodeField encodes x448 session key encryption fields as
+// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey
+// and writes it to writer.
+func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) {
+ lenAlgorithm := 0
+ if !v6 {
+ lenAlgorithm = 1
+ }
+ if _, err = writer.Write(ephemeralPublicKey.Point); err != nil {
+ return err
+ }
+ if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil {
+ return err
+ }
+ if !v6 {
+ if _, err = writer.Write([]byte{cipherFunction}); err != nil {
+ return err
+ }
+ }
+ if _, err = writer.Write(encryptedSessionKey); err != nil {
+ return err
+ }
+ return nil
+}
+
+// DecodeField decodes a x448 session key encryption as
+// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey.
+func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) {
+ var buf [1]byte
+ ephemeralPublicKey = &PublicKey{
+ Point: make([]byte, KeySize),
+ }
+ // 56 octets representing an ephemeral x448 public key.
+ if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil {
+ return nil, nil, 0, err
+ }
+ // A one-octet size of the following fields.
+ if _, err = io.ReadFull(reader, buf[:]); err != nil {
+ return nil, nil, 0, err
+ }
+ followingLen := buf[0]
+ // The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
+ if !v6 {
+ if _, err = io.ReadFull(reader, buf[:]); err != nil {
+ return nil, nil, 0, err
+ }
+ cipherFunction = buf[0]
+ followingLen -= 1
+ }
+ // The encrypted session key.
+ encryptedSessionKey = make([]byte, followingLen)
+ if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil {
+ return nil, nil, 0, err
+ }
+ return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil
+}
diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION
index abd41058..3a4036fb 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/VERSION
+++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION
@@ -1 +1 @@
-0.2.4
+0.2.5
diff --git a/vendor/github.com/cyphar/filepath-securejoin/join.go b/vendor/github.com/cyphar/filepath-securejoin/join.go
index aa32b85f..5ac23b99 100644
--- a/vendor/github.com/cyphar/filepath-securejoin/join.go
+++ b/vendor/github.com/cyphar/filepath-securejoin/join.go
@@ -11,7 +11,6 @@
package securejoin
import (
- "bytes"
"errors"
"os"
"path/filepath"
@@ -19,6 +18,8 @@ import (
"syscall"
)
+const maxSymlinkLimit = 255
+
// IsNotExist tells you if err is an error that implies that either the path
// accessed does not exist (or path components don't exist). This is
// effectively a more broad version of os.IsNotExist.
@@ -51,71 +52,69 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
}
unsafePath = filepath.FromSlash(unsafePath)
- var path bytes.Buffer
- n := 0
- for unsafePath != "" {
- if n > 255 {
- return "", &os.PathError{Op: "SecureJoin", Path: root + string(filepath.Separator) + unsafePath, Err: syscall.ELOOP}
- }
-
- if v := filepath.VolumeName(unsafePath); v != "" {
- unsafePath = unsafePath[len(v):]
+ var (
+ currentPath string
+ remainingPath = unsafePath
+ linksWalked int
+ )
+ for remainingPath != "" {
+ if v := filepath.VolumeName(remainingPath); v != "" {
+ remainingPath = remainingPath[len(v):]
}
- // Next path component, p.
- i := strings.IndexRune(unsafePath, filepath.Separator)
- var p string
- if i == -1 {
- p, unsafePath = unsafePath, ""
+ // Get the next path component.
+ var part string
+ if i := strings.IndexRune(remainingPath, filepath.Separator); i == -1 {
+ part, remainingPath = remainingPath, ""
} else {
- p, unsafePath = unsafePath[:i], unsafePath[i+1:]
+ part, remainingPath = remainingPath[:i], remainingPath[i+1:]
}
- // Create a cleaned path, using the lexical semantics of /../a, to
- // create a "scoped" path component which can safely be joined to fullP
- // for evaluation. At this point, path.String() doesn't contain any
- // symlink components.
- cleanP := filepath.Clean(string(filepath.Separator) + path.String() + p)
- if cleanP == string(filepath.Separator) {
- path.Reset()
+ // Apply the component lexically to the path we are building.
+ // currentPath does not contain any symlinks, and we are lexically
+ // dealing with a single component, so it's okay to do a filepath.Clean
+ // here.
+ nextPath := filepath.Join(string(filepath.Separator), currentPath, part)
+ if nextPath == string(filepath.Separator) {
+ currentPath = ""
continue
}
- fullP := filepath.Clean(root + cleanP)
+ fullPath := root + string(filepath.Separator) + nextPath
// Figure out whether the path is a symlink.
- fi, err := vfs.Lstat(fullP)
+ fi, err := vfs.Lstat(fullPath)
if err != nil && !IsNotExist(err) {
return "", err
}
// Treat non-existent path components the same as non-symlinks (we
// can't do any better here).
if IsNotExist(err) || fi.Mode()&os.ModeSymlink == 0 {
- path.WriteString(p)
- path.WriteRune(filepath.Separator)
+ currentPath = nextPath
continue
}
- // Only increment when we actually dereference a link.
- n++
+ // It's a symlink, so get its contents and expand it by prepending it
+ // to the yet-unparsed path.
+ linksWalked++
+ if linksWalked > maxSymlinkLimit {
+ return "", &os.PathError{Op: "SecureJoin", Path: root + string(filepath.Separator) + unsafePath, Err: syscall.ELOOP}
+ }
- // It's a symlink, expand it by prepending it to the yet-unparsed path.
- dest, err := vfs.Readlink(fullP)
+ dest, err := vfs.Readlink(fullPath)
if err != nil {
return "", err
}
+ remainingPath = dest + string(filepath.Separator) + remainingPath
// Absolute symlinks reset any work we've already done.
if filepath.IsAbs(dest) {
- path.Reset()
+ currentPath = ""
}
- unsafePath = dest + string(filepath.Separator) + unsafePath
}
- // We have to clean path.String() here because it may contain '..'
- // components that are entirely lexical, but would be misleading otherwise.
- // And finally do a final clean to ensure that root is also lexically
- // clean.
- fullP := filepath.Clean(string(filepath.Separator) + path.String())
- return filepath.Clean(root + fullP), nil
+ // There should be no lexical components like ".." left in the path here,
+ // but for safety clean up the path before joining it to the root.
+ finalPath := filepath.Join(string(filepath.Separator), currentPath)
+ return filepath.Join(root, finalPath), nil
}
// SecureJoin is a wrapper around SecureJoinVFS that just uses the os.* library
diff --git a/vendor/github.com/go-git/go-billy/v5/Makefile b/vendor/github.com/go-git/go-billy/v5/Makefile
index 74dad8b4..3c95ddea 100644
--- a/vendor/github.com/go-git/go-billy/v5/Makefile
+++ b/vendor/github.com/go-git/go-billy/v5/Makefile
@@ -1,6 +1,7 @@
# Go parameters
GOCMD = go
GOTEST = $(GOCMD) test
+WASIRUN_WRAPPER := $(CURDIR)/scripts/wasirun-wrapper
.PHONY: test
test:
@@ -9,3 +10,9 @@ test:
test-coverage:
echo "" > $(COVERAGE_REPORT); \
$(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./...
+
+.PHONY: wasitest
+wasitest: export GOARCH=wasm
+wasitest: export GOOS=wasip1
+wasitest:
+ $(GOTEST) -exec $(WASIRUN_WRAPPER) ./...
diff --git a/vendor/github.com/go-git/go-billy/v5/fs.go b/vendor/github.com/go-git/go-billy/v5/fs.go
index a9efccde..d86f9d82 100644
--- a/vendor/github.com/go-git/go-billy/v5/fs.go
+++ b/vendor/github.com/go-git/go-billy/v5/fs.go
@@ -164,6 +164,8 @@ type File interface {
// Name returns the name of the file as presented to Open.
Name() string
io.Writer
+ // TODO: Add io.WriterAt for v6
+ // io.WriterAt
io.Reader
io.ReaderAt
io.Seeker
diff --git a/vendor/github.com/go-git/go-billy/v5/memfs/memory.go b/vendor/github.com/go-git/go-billy/v5/memfs/memory.go
index dab73968..6cbd7d08 100644
--- a/vendor/github.com/go-git/go-billy/v5/memfs/memory.go
+++ b/vendor/github.com/go-git/go-billy/v5/memfs/memory.go
@@ -9,6 +9,7 @@ import (
"path/filepath"
"sort"
"strings"
+ "syscall"
"time"
"github.com/go-git/go-billy/v5"
@@ -18,16 +19,19 @@ import (
const separator = filepath.Separator
-// Memory a very convenient filesystem based on memory files
+var errNotLink = errors.New("not a link")
+
+// Memory a very convenient filesystem based on memory files.
type Memory struct {
s *storage
tempCount int
}
-//New returns a new Memory filesystem.
+// New returns a new Memory filesystem.
func New() billy.Filesystem {
fs := &Memory{s: newStorage()}
+ fs.s.New("/", 0755|os.ModeDir, 0)
return chroot.New(fs, string(separator))
}
@@ -57,7 +61,9 @@ func (fs *Memory) OpenFile(filename string, flag int, perm os.FileMode) (billy.F
}
if target, isLink := fs.resolveLink(filename, f); isLink {
- return fs.OpenFile(target, flag, perm)
+ if target != filename {
+ return fs.OpenFile(target, flag, perm)
+ }
}
}
@@ -68,8 +74,6 @@ func (fs *Memory) OpenFile(filename string, flag int, perm os.FileMode) (billy.F
return f.Duplicate(filename, perm, flag), nil
}
-var errNotLink = errors.New("not a link")
-
func (fs *Memory) resolveLink(fullpath string, f *file) (target string, isLink bool) {
if !isSymlink(f.mode) {
return fullpath, false
@@ -131,8 +135,12 @@ func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (fs *Memory) ReadDir(path string) ([]os.FileInfo, error) {
if f, has := fs.s.Get(path); has {
if target, isLink := fs.resolveLink(path, f); isLink {
- return fs.ReadDir(target)
+ if target != path {
+ return fs.ReadDir(target)
+ }
}
+ } else {
+ return nil, &os.PathError{Op: "open", Path: path, Err: syscall.ENOENT}
}
var entries []os.FileInfo
@@ -169,17 +177,19 @@ func (fs *Memory) Remove(filename string) error {
return fs.s.Remove(filename)
}
+// Falls back to Go's filepath.Join, which works differently depending on the
+// OS where the code is being executed.
func (fs *Memory) Join(elem ...string) string {
return filepath.Join(elem...)
}
func (fs *Memory) Symlink(target, link string) error {
- _, err := fs.Stat(link)
+ _, err := fs.Lstat(link)
if err == nil {
return os.ErrExist
}
- if !os.IsNotExist(err) {
+ if !errors.Is(err, os.ErrNotExist) {
return err
}
@@ -230,7 +240,7 @@ func (f *file) Read(b []byte) (int, error) {
n, err := f.ReadAt(b, f.position)
f.position += int64(n)
- if err == io.EOF && n != 0 {
+ if errors.Is(err, io.EOF) && n != 0 {
err = nil
}
@@ -269,6 +279,10 @@ func (f *file) Seek(offset int64, whence int) (int64, error) {
}
func (f *file) Write(p []byte) (int, error) {
+ return f.WriteAt(p, f.position)
+}
+
+func (f *file) WriteAt(p []byte, off int64) (int, error) {
if f.isClosed {
return 0, os.ErrClosed
}
@@ -277,8 +291,8 @@ func (f *file) Write(p []byte) (int, error) {
return 0, errors.New("write not supported")
}
- n, err := f.content.WriteAt(p, f.position)
- f.position += int64(n)
+ n, err := f.content.WriteAt(p, off)
+ f.position = off + int64(n)
return n, err
}
diff --git a/vendor/github.com/go-git/go-billy/v5/memfs/storage.go b/vendor/github.com/go-git/go-billy/v5/memfs/storage.go
index e3c4e38b..16b48ce0 100644
--- a/vendor/github.com/go-git/go-billy/v5/memfs/storage.go
+++ b/vendor/github.com/go-git/go-billy/v5/memfs/storage.go
@@ -6,6 +6,7 @@ import (
"io"
"os"
"path/filepath"
+ "strings"
"sync"
)
@@ -112,7 +113,7 @@ func (s *storage) Rename(from, to string) error {
move := [][2]string{{from, to}}
for pathFrom := range s.files {
- if pathFrom == from || !filepath.HasPrefix(pathFrom, from) {
+ if pathFrom == from || !strings.HasPrefix(pathFrom, from) {
continue
}
diff --git a/vendor/github.com/go-git/go-billy/v5/osfs/os_bound.go b/vendor/github.com/go-git/go-billy/v5/osfs/os_bound.go
index b4b6dbc0..c0a61099 100644
--- a/vendor/github.com/go-git/go-billy/v5/osfs/os_bound.go
+++ b/vendor/github.com/go-git/go-billy/v5/osfs/os_bound.go
@@ -246,6 +246,10 @@ func (fs *BoundOS) insideBaseDir(filename string) (bool, error) {
// a dir that is within the fs.baseDir, by first evaluating any symlinks
// that either filename or fs.baseDir may contain.
func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) {
+ // "/" contains all others.
+ if fs.baseDir == "/" {
+ return true, nil
+ }
dir, err := filepath.EvalSymlinks(filepath.Dir(filename))
if dir == "" || os.IsNotExist(err) {
dir = filepath.Dir(filename)
@@ -255,7 +259,7 @@ func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) {
wd = fs.baseDir
}
if filename != wd && dir != wd && !strings.HasPrefix(dir, wd+string(filepath.Separator)) {
- return false, fmt.Errorf("path outside base dir")
+ return false, fmt.Errorf("%q: path outside base dir %q: %w", filename, fs.baseDir, os.ErrNotExist)
}
return true, nil
}
diff --git a/vendor/github.com/go-git/go-billy/v5/osfs/os_posix.go b/vendor/github.com/go-git/go-billy/v5/osfs/os_posix.go
index d834a114..6fb8273f 100644
--- a/vendor/github.com/go-git/go-billy/v5/osfs/os_posix.go
+++ b/vendor/github.com/go-git/go-billy/v5/osfs/os_posix.go
@@ -1,5 +1,5 @@
-//go:build !plan9 && !windows && !js
-// +build !plan9,!windows,!js
+//go:build !plan9 && !windows && !wasm
+// +build !plan9,!windows,!wasm
package osfs
diff --git a/vendor/github.com/go-git/go-billy/v5/osfs/os_wasip1.go b/vendor/github.com/go-git/go-billy/v5/osfs/os_wasip1.go
new file mode 100644
index 00000000..79e6e331
--- /dev/null
+++ b/vendor/github.com/go-git/go-billy/v5/osfs/os_wasip1.go
@@ -0,0 +1,34 @@
+//go:build wasip1
+// +build wasip1
+
+package osfs
+
+import (
+ "os"
+ "syscall"
+)
+
+func (f *file) Lock() error {
+ f.m.Lock()
+ defer f.m.Unlock()
+ return nil
+}
+
+func (f *file) Unlock() error {
+ f.m.Lock()
+ defer f.m.Unlock()
+ return nil
+}
+
+func rename(from, to string) error {
+ return os.Rename(from, to)
+}
+
+// umask sets umask to a new value, and returns a func which allows the
+// caller to reset it back to what it was originally.
+func umask(new int) func() {
+ old := syscall.Umask(new)
+ return func() {
+ syscall.Umask(old)
+ }
+}
diff --git a/vendor/github.com/go-git/go-billy/v5/util/util.go b/vendor/github.com/go-git/go-billy/v5/util/util.go
index 5c77128c..2cdd832c 100644
--- a/vendor/github.com/go-git/go-billy/v5/util/util.go
+++ b/vendor/github.com/go-git/go-billy/v5/util/util.go
@@ -1,6 +1,7 @@
package util
import (
+ "errors"
"io"
"os"
"path/filepath"
@@ -33,14 +34,14 @@ func removeAll(fs billy.Basic, path string) error {
// Simple case: if Remove works, we're done.
err := fs.Remove(path)
- if err == nil || os.IsNotExist(err) {
+ if err == nil || errors.Is(err, os.ErrNotExist) {
return nil
}
// Otherwise, is this a directory we need to recurse into?
dir, serr := fs.Stat(path)
if serr != nil {
- if os.IsNotExist(serr) {
+ if errors.Is(serr, os.ErrNotExist) {
return nil
}
@@ -60,7 +61,7 @@ func removeAll(fs billy.Basic, path string) error {
// Directory.
fis, err := dirfs.ReadDir(path)
if err != nil {
- if os.IsNotExist(err) {
+ if errors.Is(err, os.ErrNotExist) {
// Race. It was deleted between the Lstat and Open.
// Return nil per RemoveAll's docs.
return nil
@@ -81,7 +82,7 @@ func removeAll(fs billy.Basic, path string) error {
// Remove directory.
err1 := fs.Remove(path)
- if err1 == nil || os.IsNotExist(err1) {
+ if err1 == nil || errors.Is(err1, os.ErrNotExist) {
return nil
}
@@ -96,22 +97,26 @@ func removeAll(fs billy.Basic, path string) error {
// WriteFile writes data to a file named by filename in the given filesystem.
// If the file does not exist, WriteFile creates it with permissions perm;
// otherwise WriteFile truncates it before writing.
-func WriteFile(fs billy.Basic, filename string, data []byte, perm os.FileMode) error {
+func WriteFile(fs billy.Basic, filename string, data []byte, perm os.FileMode) (err error) {
f, err := fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return err
}
+ defer func() {
+ if f != nil {
+ err1 := f.Close()
+ if err == nil {
+ err = err1
+ }
+ }
+ }()
n, err := f.Write(data)
if err == nil && n < len(data) {
err = io.ErrShortWrite
}
- if err1 := f.Close(); err == nil {
- err = err1
- }
-
- return err
+ return nil
}
// Random number state.
@@ -154,7 +159,7 @@ func TempFile(fs billy.Basic, dir, prefix string) (f billy.File, err error) {
for i := 0; i < 10000; i++ {
name := filepath.Join(dir, prefix+nextSuffix())
f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
- if os.IsExist(err) {
+ if errors.Is(err, os.ErrExist) {
if nconflict++; nconflict > 10 {
randmu.Lock()
rand = reseed()
@@ -185,7 +190,7 @@ func TempDir(fs billy.Dir, dir, prefix string) (name string, err error) {
for i := 0; i < 10000; i++ {
try := filepath.Join(dir, prefix+nextSuffix())
err = fs.MkdirAll(try, 0700)
- if os.IsExist(err) {
+ if errors.Is(err, os.ErrExist) {
if nconflict++; nconflict > 10 {
randmu.Lock()
rand = reseed()
@@ -193,8 +198,8 @@ func TempDir(fs billy.Dir, dir, prefix string) (name string, err error) {
}
continue
}
- if os.IsNotExist(err) {
- if _, err := os.Stat(dir); os.IsNotExist(err) {
+ if errors.Is(err, os.ErrNotExist) {
+ if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) {
return "", err
}
}
@@ -272,7 +277,7 @@ func ReadFile(fs billy.Basic, name string) ([]byte, error) {
data = data[:len(data)+n]
if err != nil {
- if err == io.EOF {
+ if errors.Is(err, io.EOF) {
err = nil
}
diff --git a/vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md b/vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
index ff0c22c8..ba1fb90a 100644
--- a/vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
+++ b/vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
@@ -11,7 +11,7 @@ compatibility status with go-git.
| `init` | `--bare` | ✅ | | |
| `init` | `--template`
`--separate-git-dir`
`--shared` | ❌ | | |
| `clone` | | ✅ | | - [PlainClone](_examples/clone/main.go) |
-| `clone` | Authentication:
- none
- access token
- username + password
- ssh | ✅ | | - [clone ssh](_examples/clone/auth/ssh/main.go)
- [clone access token](_examples/clone/auth/basic/access_token/main.go)
- [clone user + password](_examples/clone/auth/basic/username_password/main.go) |
+| `clone` | Authentication:
- none
- access token
- username + password
- ssh | ✅ | | - [clone ssh (private_key)](_examples/clone/auth/ssh/private_key/main.go)
- [clone ssh (ssh_agent)](_examples/clone/auth/ssh/ssh_agent/main.go)
- [clone access token](_examples/clone/auth/basic/access_token/main.go)
- [clone user + password](_examples/clone/auth/basic/username_password/main.go) |
| `clone` | `--progress`
`--single-branch`
`--depth`
`--origin`
`--recurse-submodules`
`--shared` | ✅ | | - [recurse submodules](_examples/clone/main.go)
- [progress](_examples/progress/main.go) |
## Basic snapshotting
@@ -34,6 +34,7 @@ compatibility status with go-git.
| `merge` | | ⚠️ (partial) | Fast-forward only | |
| `mergetool` | | ❌ | | |
| `stash` | | ❌ | | |
+| `sparse-checkout` | | ✅ | | - [sparse-checkout](_examples/sparse-checkout/main.go) |
| `tag` | | ✅ | | - [tag](_examples/tag/main.go)
- [tag create and push](_examples/tag-create-push/main.go) |
## Sharing and updating projects
diff --git a/vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md b/vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
index fce25328..a5b01823 100644
--- a/vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
+++ b/vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
@@ -31,6 +31,13 @@ In order for a PR to be accepted it needs to pass a list of requirements:
- If the PR is a new feature, it has to come with a suite of unit tests, that tests the new functionality.
- In any case, all the PRs have to pass the personal evaluation of at least one of the maintainers of go-git.
+### Branches
+
+The `master` branch is currently used for maintaining the `v5` major release only. The accepted changes would
+be dependency bumps, bug fixes and small changes that aren't needed for `v6`. New development should target the
+`v6-exp` branch, and if agreed with at least one go-git maintainer, it can be back ported to `v5` by creating
+a new PR that targets `master`.
+
### Format of the commit message
Every commit message should describe what was changed, under which context and, if applicable, the GitHub issue it relates to:
diff --git a/vendor/github.com/go-git/go-git/v5/blame.go b/vendor/github.com/go-git/go-git/v5/blame.go
index 2a877dcd..e3cb39ae 100644
--- a/vendor/github.com/go-git/go-git/v5/blame.go
+++ b/vendor/github.com/go-git/go-git/v5/blame.go
@@ -97,13 +97,10 @@ func Blame(c *object.Commit, path string) (*BlameResult, error) {
if err != nil {
return nil, err
}
- if finished == true {
+ if finished {
break
}
}
- if err != nil {
- return nil, err
- }
b.lineToCommit = make([]*object.Commit, finalLength)
for i := range needsMap {
@@ -309,8 +306,8 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
for h := range hunks {
hLines := countLines(hunks[h].Text)
for hl := 0; hl < hLines; hl++ {
- switch {
- case hunks[h].Type == diffmatchpatch.DiffEqual:
+ switch hunks[h].Type {
+ case diffmatchpatch.DiffEqual:
prevl++
curl++
if curl == curItem.NeedsMap[need].Cur {
@@ -322,7 +319,7 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
break out
}
}
- case hunks[h].Type == diffmatchpatch.DiffInsert:
+ case diffmatchpatch.DiffInsert:
curl++
if curl == curItem.NeedsMap[need].Cur {
// the line we want is added, it may have been added here (or by another parent), skip it for now
@@ -331,7 +328,7 @@ func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
break out
}
}
- case hunks[h].Type == diffmatchpatch.DiffDelete:
+ case diffmatchpatch.DiffDelete:
prevl += hLines
continue out
default:
diff --git a/vendor/github.com/go-git/go-git/v5/config/config.go b/vendor/github.com/go-git/go-git/v5/config/config.go
index 6d41c15d..33f6e37d 100644
--- a/vendor/github.com/go-git/go-git/v5/config/config.go
+++ b/vendor/github.com/go-git/go-git/v5/config/config.go
@@ -252,6 +252,7 @@ const (
extensionsSection = "extensions"
fetchKey = "fetch"
urlKey = "url"
+ pushurlKey = "pushurl"
bareKey = "bare"
worktreeKey = "worktree"
commentCharKey = "commentChar"
@@ -633,6 +634,7 @@ func (c *RemoteConfig) unmarshal(s *format.Subsection) error {
c.Name = c.raw.Name
c.URLs = append([]string(nil), c.raw.Options.GetAll(urlKey)...)
+ c.URLs = append(c.URLs, c.raw.Options.GetAll(pushurlKey)...)
c.Fetch = fetch
c.Mirror = c.raw.Options.Get(mirrorKey) == "true"
diff --git a/vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go b/vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
index c46c21b7..2444f33e 100644
--- a/vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
+++ b/vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
@@ -43,6 +43,11 @@ func tokenizeExpression(ch rune, tokenType token, check runeCategoryValidator, r
return tokenType, string(data), nil
}
+// maxRevisionLength holds the maximum length that will be parsed for a
+// revision. Git itself doesn't enforce a max length, but rather leans on
+// the OS to enforce it via its ARG_MAX.
+const maxRevisionLength = 128 * 1024 // 128kb
+
var zeroRune = rune(0)
// scanner represents a lexical scanner.
@@ -52,7 +57,7 @@ type scanner struct {
// newScanner returns a new instance of scanner.
func newScanner(r io.Reader) *scanner {
- return &scanner{r: bufio.NewReader(r)}
+ return &scanner{r: bufio.NewReader(io.LimitReader(r, maxRevisionLength))}
}
// Scan extracts tokens and their strings counterpart
diff --git a/vendor/github.com/go-git/go-git/v5/options.go b/vendor/github.com/go-git/go-git/v5/options.go
index d7776dad..3cd0f952 100644
--- a/vendor/github.com/go-git/go-git/v5/options.go
+++ b/vendor/github.com/go-git/go-git/v5/options.go
@@ -416,6 +416,9 @@ type ResetOptions struct {
// the index (resetting it to the tree of Commit) and the working tree
// depending on Mode. If empty MixedReset is used.
Mode ResetMode
+ // Files, if not empty will constrain the reseting the index to only files
+ // specified in this list.
+ Files []string
}
// Validate validates the fields and sets the default values.
@@ -790,3 +793,26 @@ type PlainInitOptions struct {
// Validate validates the fields and sets the default values.
func (o *PlainInitOptions) Validate() error { return nil }
+
+var (
+ ErrNoRestorePaths = errors.New("you must specify path(s) to restore")
+)
+
+// RestoreOptions describes how a restore should be performed.
+type RestoreOptions struct {
+ // Marks to restore the content in the index
+ Staged bool
+ // Marks to restore the content of the working tree
+ Worktree bool
+ // List of file paths that will be restored
+ Files []string
+}
+
+// Validate validates the fields and sets the default values.
+func (o *RestoreOptions) Validate() error {
+ if len(o.Files) == 0 {
+ return ErrNoRestorePaths
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
index aca5d0db..92df5a3d 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
@@ -64,6 +64,10 @@ func ReadPatterns(fs billy.Filesystem, path []string) (ps []Pattern, err error)
for _, fi := range fis {
if fi.IsDir() && fi.Name() != gitDir {
+ if NewMatcher(ps).Match(append(path, fi.Name()), true) {
+ continue
+ }
+
var subps []Pattern
subps, err = ReadPatterns(fs, append(path, fi.Name()))
if err != nil {
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
index 6778cf74..fc25d370 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
@@ -24,8 +24,8 @@ var (
// ErrInvalidChecksum is returned by Decode if the SHA1 hash mismatch with
// the read content
ErrInvalidChecksum = errors.New("invalid checksum")
-
- errUnknownExtension = errors.New("unknown extension")
+ // ErrUnknownExtension is returned when an index extension is encountered that is considered mandatory
+ ErrUnknownExtension = errors.New("unknown extension")
)
const (
@@ -39,6 +39,7 @@ const (
// A Decoder reads and decodes index files from an input stream.
type Decoder struct {
+ buf *bufio.Reader
r io.Reader
hash hash.Hash
lastEntry *Entry
@@ -49,8 +50,10 @@ type Decoder struct {
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
h := hash.New(hash.CryptoType)
+ buf := bufio.NewReader(r)
return &Decoder{
- r: io.TeeReader(r, h),
+ buf: buf,
+ r: io.TeeReader(buf, h),
hash: h,
extReader: bufio.NewReader(nil),
}
@@ -210,71 +213,75 @@ func (d *Decoder) readExtensions(idx *Index) error {
// count that they are not supported by jgit or libgit
var expected []byte
+ var peeked []byte
var err error
- var header [4]byte
+ // we should always be able to peek for 4 bytes (header) + 4 bytes (extlen) + final hash
+ // if this fails, we know that we're at the end of the index
+ peekLen := 4 + 4 + d.hash.Size()
+
for {
expected = d.hash.Sum(nil)
-
- var n int
- if n, err = io.ReadFull(d.r, header[:]); err != nil {
- if n == 0 {
- err = io.EOF
- }
-
+ peeked, err = d.buf.Peek(peekLen)
+ if len(peeked) < peekLen {
+ // there can't be an extension at this point, so let's bail out
break
}
+ if err != nil {
+ return err
+ }
- err = d.readExtension(idx, header[:])
+ err = d.readExtension(idx)
if err != nil {
- break
+ return err
}
}
- if err != errUnknownExtension {
+ return d.readChecksum(expected)
+}
+
+func (d *Decoder) readExtension(idx *Index) error {
+ var header [4]byte
+
+ if _, err := io.ReadFull(d.r, header[:]); err != nil {
return err
}
- return d.readChecksum(expected, header)
-}
+ r, err := d.getExtensionReader()
+ if err != nil {
+ return err
+ }
-func (d *Decoder) readExtension(idx *Index, header []byte) error {
switch {
- case bytes.Equal(header, treeExtSignature):
- r, err := d.getExtensionReader()
- if err != nil {
- return err
- }
-
+ case bytes.Equal(header[:], treeExtSignature):
idx.Cache = &Tree{}
d := &treeExtensionDecoder{r}
if err := d.Decode(idx.Cache); err != nil {
return err
}
- case bytes.Equal(header, resolveUndoExtSignature):
- r, err := d.getExtensionReader()
- if err != nil {
- return err
- }
-
+ case bytes.Equal(header[:], resolveUndoExtSignature):
idx.ResolveUndo = &ResolveUndo{}
d := &resolveUndoDecoder{r}
if err := d.Decode(idx.ResolveUndo); err != nil {
return err
}
- case bytes.Equal(header, endOfIndexEntryExtSignature):
- r, err := d.getExtensionReader()
- if err != nil {
- return err
- }
-
+ case bytes.Equal(header[:], endOfIndexEntryExtSignature):
idx.EndOfIndexEntry = &EndOfIndexEntry{}
d := &endOfIndexEntryDecoder{r}
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
return err
}
default:
- return errUnknownExtension
+ // See https://git-scm.com/docs/index-format, which says:
+ // If the first byte is 'A'..'Z' the extension is optional and can be ignored.
+ if header[0] < 'A' || header[0] > 'Z' {
+ return ErrUnknownExtension
+ }
+
+ d := &unknownExtensionDecoder{r}
+ if err := d.Decode(); err != nil {
+ return err
+ }
}
return nil
@@ -290,11 +297,10 @@ func (d *Decoder) getExtensionReader() (*bufio.Reader, error) {
return d.extReader, nil
}
-func (d *Decoder) readChecksum(expected []byte, alreadyRead [4]byte) error {
+func (d *Decoder) readChecksum(expected []byte) error {
var h plumbing.Hash
- copy(h[:4], alreadyRead[:])
- if _, err := io.ReadFull(d.r, h[4:]); err != nil {
+ if _, err := io.ReadFull(d.r, h[:]); err != nil {
return err
}
@@ -476,3 +482,22 @@ func (d *endOfIndexEntryDecoder) Decode(e *EndOfIndexEntry) error {
_, err = io.ReadFull(d.r, e.Hash[:])
return err
}
+
+type unknownExtensionDecoder struct {
+ r *bufio.Reader
+}
+
+func (d *unknownExtensionDecoder) Decode() error {
+ var buf [1024]byte
+
+ for {
+ _, err := d.r.Read(buf[:])
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
index fa2d8144..c232e032 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
@@ -3,8 +3,11 @@ package index
import (
"bytes"
"errors"
+ "fmt"
"io"
+ "path"
"sort"
+ "strings"
"time"
"github.com/go-git/go-git/v5/plumbing/hash"
@@ -13,7 +16,7 @@ import (
var (
// EncodeVersionSupported is the range of supported index versions
- EncodeVersionSupported uint32 = 3
+ EncodeVersionSupported uint32 = 4
// ErrInvalidTimestamp is returned by Encode if a Index with a Entry with
// negative timestamp values
@@ -22,20 +25,25 @@ var (
// An Encoder writes an Index to an output stream.
type Encoder struct {
- w io.Writer
- hash hash.Hash
+ w io.Writer
+ hash hash.Hash
+ lastEntry *Entry
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
h := hash.New(hash.CryptoType)
mw := io.MultiWriter(w, h)
- return &Encoder{mw, h}
+ return &Encoder{mw, h, nil}
}
// Encode writes the Index to the stream of the encoder.
func (e *Encoder) Encode(idx *Index) error {
- // TODO: support v4
+ return e.encode(idx, true)
+}
+
+func (e *Encoder) encode(idx *Index, footer bool) error {
+
// TODO: support extensions
if idx.Version > EncodeVersionSupported {
return ErrUnsupportedVersion
@@ -49,7 +57,10 @@ func (e *Encoder) Encode(idx *Index) error {
return err
}
- return e.encodeFooter()
+ if footer {
+ return e.encodeFooter()
+ }
+ return nil
}
func (e *Encoder) encodeHeader(idx *Index) error {
@@ -64,7 +75,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
sort.Sort(byName(idx.Entries))
for _, entry := range idx.Entries {
- if err := e.encodeEntry(entry); err != nil {
+ if err := e.encodeEntry(idx, entry); err != nil {
return err
}
entryLength := entryHeaderLength
@@ -73,7 +84,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
}
wrote := entryLength + len(entry.Name)
- if err := e.padEntry(wrote); err != nil {
+ if err := e.padEntry(idx, wrote); err != nil {
return err
}
}
@@ -81,7 +92,7 @@ func (e *Encoder) encodeEntries(idx *Index) error {
return nil
}
-func (e *Encoder) encodeEntry(entry *Entry) error {
+func (e *Encoder) encodeEntry(idx *Index, entry *Entry) error {
sec, nsec, err := e.timeToUint32(&entry.CreatedAt)
if err != nil {
return err
@@ -132,9 +143,68 @@ func (e *Encoder) encodeEntry(entry *Entry) error {
return err
}
+ switch idx.Version {
+ case 2, 3:
+ err = e.encodeEntryName(entry)
+ case 4:
+ err = e.encodeEntryNameV4(entry)
+ default:
+ err = ErrUnsupportedVersion
+ }
+
+ return err
+}
+
+func (e *Encoder) encodeEntryName(entry *Entry) error {
return binary.Write(e.w, []byte(entry.Name))
}
+func (e *Encoder) encodeEntryNameV4(entry *Entry) error {
+ name := entry.Name
+ l := 0
+ if e.lastEntry != nil {
+ dir := path.Dir(e.lastEntry.Name) + "/"
+ if strings.HasPrefix(entry.Name, dir) {
+ l = len(e.lastEntry.Name) - len(dir)
+ name = strings.TrimPrefix(entry.Name, dir)
+ } else {
+ l = len(e.lastEntry.Name)
+ }
+ }
+
+ e.lastEntry = entry
+
+ err := binary.WriteVariableWidthInt(e.w, int64(l))
+ if err != nil {
+ return err
+ }
+
+ return binary.Write(e.w, []byte(name+string('\x00')))
+}
+
+func (e *Encoder) encodeRawExtension(signature string, data []byte) error {
+ if len(signature) != 4 {
+ return fmt.Errorf("invalid signature length")
+ }
+
+ _, err := e.w.Write([]byte(signature))
+ if err != nil {
+ return err
+ }
+
+ err = binary.WriteUint32(e.w, uint32(len(data)))
+ if err != nil {
+ return err
+ }
+
+ _, err = e.w.Write(data)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
if t.IsZero() {
return 0, 0, nil
@@ -147,7 +217,11 @@ func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
return uint32(t.Unix()), uint32(t.Nanosecond()), nil
}
-func (e *Encoder) padEntry(wrote int) error {
+func (e *Encoder) padEntry(idx *Index, wrote int) error {
+ if idx.Version == 4 {
+ return nil
+ }
+
padLen := 8 - wrote%8
_, err := e.w.Write(bytes.Repeat([]byte{'\x00'}, padLen))
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
index 07a61120..a60ec0b2 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
@@ -32,19 +32,17 @@ func (idx *deltaIndex) findMatch(src, tgt []byte, tgtOffset int) (srcOffset, l i
return 0, -1
}
- if len(tgt) >= tgtOffset+s && len(src) >= blksz {
- h := hashBlock(tgt, tgtOffset)
- tIdx := h & idx.mask
- eIdx := idx.table[tIdx]
- if eIdx != 0 {
- srcOffset = idx.entries[eIdx]
- } else {
- return
- }
-
- l = matchLength(src, tgt, tgtOffset, srcOffset)
+ h := hashBlock(tgt, tgtOffset)
+ tIdx := h & idx.mask
+ eIdx := idx.table[tIdx]
+ if eIdx == 0 {
+ return
}
+ srcOffset = idx.entries[eIdx]
+
+ l = matchLength(src, tgt, tgtOffset, srcOffset)
+
return
}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
index 960769c7..a9c6b9b5 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
@@ -26,6 +26,13 @@ var (
const (
payload = 0x7f // 0111 1111
continuation = 0x80 // 1000 0000
+
+ // maxPatchPreemptionSize defines what is the max size of bytes to be
+ // premptively made available for a patch operation.
+ maxPatchPreemptionSize uint = 65536
+
+ // minDeltaSize defines the smallest size for a delta.
+ minDeltaSize = 4
)
type offset struct {
@@ -86,9 +93,13 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) (err error) {
}
// PatchDelta returns the result of applying the modification deltas in delta to src.
-// An error will be returned if delta is corrupted (ErrDeltaLen) or an action command
+// An error will be returned if delta is corrupted (ErrInvalidDelta) or an action command
// is not copy from source or copy from delta (ErrDeltaCmd).
func PatchDelta(src, delta []byte) ([]byte, error) {
+ if len(src) == 0 || len(delta) < minDeltaSize {
+ return nil, ErrInvalidDelta
+ }
+
b := &bytes.Buffer{}
if err := patchDelta(b, src, delta); err != nil {
return nil, err
@@ -239,7 +250,9 @@ func patchDelta(dst *bytes.Buffer, src, delta []byte) error {
remainingTargetSz := targetSz
var cmd byte
- dst.Grow(int(targetSz))
+
+ growSz := min(targetSz, maxPatchPreemptionSize)
+ dst.Grow(int(growSz))
for {
if len(delta) == 0 {
return ErrInvalidDelta
@@ -403,6 +416,10 @@ func patchDeltaWriter(dst io.Writer, base io.ReaderAt, delta io.Reader,
// This must be called twice on the delta data buffer, first to get the
// expected source buffer size, and again to get the target buffer size.
func decodeLEB128(input []byte) (uint, []byte) {
+ if len(input) == 0 {
+ return 0, input
+ }
+
var num, sz uint
var b byte
for {
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
index fbb137de..706d984e 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
@@ -140,6 +140,8 @@ func asciiHexToByte(b byte) (byte, error) {
return b - '0', nil
case b >= 'a' && b <= 'f':
return b - 'a' + 10, nil
+ case b >= 'A' && b <= 'F':
+ return b - 'A' + 10, nil
default:
return 0, ErrInvalidPktLen
}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go b/vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
index 91cf371f..f9c3d306 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
@@ -19,6 +19,7 @@ var (
// a PKCS#7 (S/MIME) signature.
x509SignatureFormat = signatureFormat{
[]byte("-----BEGIN CERTIFICATE-----"),
+ []byte("-----BEGIN SIGNED MESSAGE-----"),
}
// sshSignatureFormat is the format of an SSH signature.
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go b/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
index 0fd0e513..2e1b7891 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
@@ -295,6 +295,7 @@ func (s TreeEntrySorter) Swap(i, j int) {
}
// Encode transforms a Tree into a plumbing.EncodedObject.
+// The tree entries must be sorted by name.
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
o.SetType(plumbing.TreeObject)
w, err := o.Writer()
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go
new file mode 100644
index 00000000..145fc711
--- /dev/null
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go
@@ -0,0 +1,76 @@
+package packp
+
+import (
+ "errors"
+ "fmt"
+ "github.com/go-git/go-git/v5/plumbing"
+ "net/url"
+ "strings"
+)
+
+var ErrUnsupportedObjectFilterType = errors.New("unsupported object filter type")
+
+// Filter values enable the partial clone capability which causes
+// the server to omit objects that match the filter.
+//
+// See [Git's documentation] for more details.
+//
+// [Git's documentation]: https://github.com/git/git/blob/e02ecfcc534e2021aae29077a958dd11c3897e4c/Documentation/rev-list-options.txt#L948
+type Filter string
+
+type BlobLimitPrefix string
+
+const (
+ BlobLimitPrefixNone BlobLimitPrefix = ""
+ BlobLimitPrefixKibi BlobLimitPrefix = "k"
+ BlobLimitPrefixMebi BlobLimitPrefix = "m"
+ BlobLimitPrefixGibi BlobLimitPrefix = "g"
+)
+
+// FilterBlobNone omits all blobs.
+func FilterBlobNone() Filter {
+ return "blob:none"
+}
+
+// FilterBlobLimit omits blobs of size at least n bytes (when prefix is
+// BlobLimitPrefixNone), n kibibytes (when prefix is BlobLimitPrefixKibi),
+// n mebibytes (when prefix is BlobLimitPrefixMebi) or n gibibytes (when
+// prefix is BlobLimitPrefixGibi). n can be zero, in which case all blobs
+// will be omitted.
+func FilterBlobLimit(n uint64, prefix BlobLimitPrefix) Filter {
+ return Filter(fmt.Sprintf("blob:limit=%d%s", n, prefix))
+}
+
+// FilterTreeDepth omits all blobs and trees whose depth from the root tree
+// is larger or equal to depth.
+func FilterTreeDepth(depth uint64) Filter {
+ return Filter(fmt.Sprintf("tree:%d", depth))
+}
+
+// FilterObjectType omits all objects which are not of the requested type t.
+// Supported types are TagObject, CommitObject, TreeObject and BlobObject.
+func FilterObjectType(t plumbing.ObjectType) (Filter, error) {
+ switch t {
+ case plumbing.TagObject:
+ fallthrough
+ case plumbing.CommitObject:
+ fallthrough
+ case plumbing.TreeObject:
+ fallthrough
+ case plumbing.BlobObject:
+ return Filter(fmt.Sprintf("object:type=%s", t.String())), nil
+ default:
+ return "", fmt.Errorf("%w: %s", ErrUnsupportedObjectFilterType, t.String())
+ }
+}
+
+// FilterCombine combines multiple Filter values together.
+func FilterCombine(filters ...Filter) Filter {
+ var escapedFilters []string
+
+ for _, filter := range filters {
+ escapedFilters = append(escapedFilters, url.QueryEscape(string(filter)))
+ }
+
+ return Filter(fmt.Sprintf("combine:%s", strings.Join(escapedFilters, "+")))
+}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
index 0116f962..01d95a3a 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
@@ -114,7 +114,7 @@ func (d *Demuxer) nextPackData() ([]byte, error) {
size := len(content)
if size == 0 {
- return nil, nil
+ return nil, io.EOF
} else if size > d.max {
return nil, ErrMaxPackedExceeded
}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
index a9ddb538..d760ad66 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
@@ -120,6 +120,9 @@ func (r *ServerResponse) decodeACKLine(line []byte) error {
}
sp := bytes.Index(line, []byte(" "))
+ if sp+41 > len(line) {
+ return fmt.Errorf("malformed ACK %q", line)
+ }
h := plumbing.NewHash(string(line[sp+1 : sp+41]))
r.ACKs = append(r.ACKs, h)
return nil
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
index 344f8c7e..ef4e08a1 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
@@ -17,6 +17,7 @@ type UploadRequest struct {
Wants []plumbing.Hash
Shallows []plumbing.Hash
Depth Depth
+ Filter Filter
}
// Depth values stores the desired depth of the requested packfile: see
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
index c451e231..8b19c0f6 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
@@ -132,6 +132,17 @@ func (e *ulReqEncoder) encodeDepth() stateFn {
return nil
}
+ return e.encodeFilter
+}
+
+func (e *ulReqEncoder) encodeFilter() stateFn {
+ if filter := e.data.Filter; filter != "" {
+ if err := e.pe.Encodef("filter %s\n", filter); err != nil {
+ e.err = fmt.Errorf("encoding filter %s: %s", filter, err)
+ return nil
+ }
+ }
+
return e.encodeFlush
}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/reference.go b/vendor/github.com/go-git/go-git/v5/plumbing/reference.go
index ddba9302..4daa3416 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/reference.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/reference.go
@@ -188,7 +188,7 @@ func (r ReferenceName) Validate() error {
isBranch := r.IsBranch()
isTag := r.IsTag()
- for _, part := range parts {
+ for i, part := range parts {
// rule 6
if len(part) == 0 {
return ErrInvalidReferenceName
@@ -205,7 +205,7 @@ func (r ReferenceName) Validate() error {
return ErrInvalidReferenceName
}
- if (isBranch || isTag) && strings.HasPrefix(part, "-") { // branches & tags can't start with -
+ if (isBranch || isTag) && strings.HasPrefix(part, "-") && (i == 2) { // branches & tags can't start with -
return ErrInvalidReferenceName
}
}
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
index b05437fb..fae1aa98 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
@@ -19,6 +19,7 @@ import (
"fmt"
"io"
"net/url"
+ "path/filepath"
"strconv"
"strings"
@@ -295,7 +296,11 @@ func parseFile(endpoint string) (*Endpoint, bool) {
return nil, false
}
- path := endpoint
+ path, err := filepath.Abs(endpoint)
+ if err != nil {
+ return nil, false
+ }
+
return &Endpoint{
Protocol: "file",
Path: path,
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
index 38714e2a..d921d0a5 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
@@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
+ "runtime"
"strings"
"github.com/go-git/go-git/v5/plumbing/transport"
@@ -95,7 +96,23 @@ func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.Auth
}
}
- return &command{cmd: execabs.Command(cmd, ep.Path)}, nil
+ return &command{cmd: execabs.Command(cmd, adjustPathForWindows(ep.Path))}, nil
+}
+
+func isDriveLetter(c byte) bool {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+}
+
+// On Windows, the path that results from a file: URL has a leading slash. This
+// has to be removed if there's a drive letter
+func adjustPathForWindows(p string) string {
+ if runtime.GOOS != "windows" {
+ return p
+ }
+ if len(p) >= 3 && p[0] == '/' && isDriveLetter(p[1]) && p[2] == ':' {
+ return p[1:]
+ }
+ return p
}
type command struct {
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
index 1c4ceee6..120008db 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
@@ -430,11 +430,11 @@ func NewErr(r *http.Response) error {
switch r.StatusCode {
case http.StatusUnauthorized:
- return transport.ErrAuthenticationRequired
+ return fmt.Errorf("%w: %s", transport.ErrAuthenticationRequired, reason)
case http.StatusForbidden:
- return transport.ErrAuthorizationFailed
+ return fmt.Errorf("%w: %s", transport.ErrAuthorizationFailed, reason)
case http.StatusNotFound:
- return transport.ErrRepositoryNotFound
+ return fmt.Errorf("%w: %s", transport.ErrRepositoryNotFound, reason)
}
return plumbing.NewUnexpectedError(&Err{r, reason})
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
index e7e2b075..f03a91c6 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
@@ -40,8 +40,16 @@ func (l *fsLoader) Load(ep *transport.Endpoint) (storer.Storer, error) {
return nil, err
}
- if _, err := fs.Stat("config"); err != nil {
- return nil, transport.ErrRepositoryNotFound
+ var bare bool
+ if _, err := fs.Stat("config"); err == nil {
+ bare = true
+ }
+
+ if !bare {
+ // do not use git.GitDirName due to import cycle
+ if _, err := fs.Stat(".git"); err != nil {
+ return nil, transport.ErrRepositoryNotFound
+ }
}
return filesystem.NewStorage(fs, cache.NewObjectLRUDefault()), nil
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
index ac4e3583..f9c598e6 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
@@ -230,11 +230,11 @@ func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
// ~/.ssh/known_hosts
// /etc/ssh/ssh_known_hosts
func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) {
- kh, err := newKnownHosts(files...)
- return ssh.HostKeyCallback(kh), err
+ db, err := newKnownHostsDb(files...)
+ return db.HostKeyCallback(), err
}
-func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
+func newKnownHostsDb(files ...string) (*knownhosts.HostKeyDB, error) {
var err error
if len(files) == 0 {
@@ -247,7 +247,7 @@ func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
return nil, err
}
- return knownhosts.New(files...)
+ return knownhosts.NewDB(files...)
}
func getDefaultKnownHostsFiles() ([]string, error) {
@@ -301,11 +301,12 @@ type HostKeyCallbackHelper struct {
// HostKeyCallback is empty a default callback is created using
// NewKnownHostsCallback.
func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
- var err error
if m.HostKeyCallback == nil {
- if m.HostKeyCallback, err = NewKnownHostsCallback(); err != nil {
+ db, err := newKnownHostsDb()
+ if err != nil {
return cfg, err
}
+ m.HostKeyCallback = db.HostKeyCallback()
}
cfg.HostKeyCallback = m.HostKeyCallback
diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
index 05dea448..a37024f0 100644
--- a/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
+++ b/vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
@@ -11,7 +11,6 @@ import (
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
- "github.com/skeema/knownhosts"
"github.com/kevinburke/ssh_config"
"golang.org/x/crypto/ssh"
@@ -127,17 +126,25 @@ func (c *command) connect() error {
}
hostWithPort := c.getHostWithPort()
if config.HostKeyCallback == nil {
- kh, err := newKnownHosts()
+ db, err := newKnownHostsDb()
if err != nil {
return err
}
- config.HostKeyCallback = kh.HostKeyCallback()
- config.HostKeyAlgorithms = kh.HostKeyAlgorithms(hostWithPort)
+
+ config.HostKeyCallback = db.HostKeyCallback()
+ config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort)
} else if len(config.HostKeyAlgorithms) == 0 {
// Set the HostKeyAlgorithms based on HostKeyCallback.
// For background see https://github.com/go-git/go-git/issues/411 as well as
// https://github.com/golang/go/issues/29286 for root cause.
- config.HostKeyAlgorithms = knownhosts.HostKeyAlgorithms(config.HostKeyCallback, hostWithPort)
+ db, err := newKnownHostsDb()
+ if err != nil {
+ return err
+ }
+
+ // Note that the knownhost database is used, as it provides additional functionality
+ // to handle ssh cert-authorities.
+ config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort)
}
overrideConfig(c.config, config)
diff --git a/vendor/github.com/go-git/go-git/v5/remote.go b/vendor/github.com/go-git/go-git/v5/remote.go
index 7cc0db9b..e2c734e7 100644
--- a/vendor/github.com/go-git/go-git/v5/remote.go
+++ b/vendor/github.com/go-git/go-git/v5/remote.go
@@ -9,6 +9,7 @@ import (
"time"
"github.com/go-git/go-billy/v5/osfs"
+
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/internal/url"
"github.com/go-git/go-git/v5/plumbing"
@@ -82,7 +83,7 @@ func (r *Remote) String() string {
var fetch, push string
if len(r.c.URLs) > 0 {
fetch = r.c.URLs[0]
- push = r.c.URLs[0]
+ push = r.c.URLs[len(r.c.URLs)-1]
}
return fmt.Sprintf("%s\t%s (fetch)\n%[1]s\t%[3]s (push)", r.c.Name, fetch, push)
@@ -109,8 +110,8 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name)
}
- if o.RemoteURL == "" {
- o.RemoteURL = r.c.URLs[0]
+ if o.RemoteURL == "" && len(r.c.URLs) > 0 {
+ o.RemoteURL = r.c.URLs[len(r.c.URLs)-1]
}
s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
@@ -491,7 +492,18 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
}
if !updated && !updatedPrune {
- return remoteRefs, NoErrAlreadyUpToDate
+ // No references updated, but may have fetched new objects, check if we now have any of our wants
+ for _, hash := range req.Wants {
+ exists, _ := objectExists(r.s, hash)
+ if exists {
+ updated = true
+ break
+ }
+ }
+
+ if !updated {
+ return remoteRefs, NoErrAlreadyUpToDate
+ }
}
return remoteRefs, nil
@@ -878,17 +890,12 @@ func getHavesFromRef(
return nil
}
- // No need to load the commit if we know the remote already
- // has this hash.
- if remoteRefs[h] {
- haves[h] = true
- return nil
- }
-
commit, err := object.GetCommit(s, h)
if err != nil {
- // Ignore the error if this isn't a commit.
- haves[ref.Hash()] = true
+ if !errors.Is(err, plumbing.ErrObjectNotFound) {
+ // Ignore the error if this isn't a commit.
+ haves[ref.Hash()] = true
+ }
return nil
}
diff --git a/vendor/github.com/go-git/go-git/v5/repository.go b/vendor/github.com/go-git/go-git/v5/repository.go
index a57c7141..200098e7 100644
--- a/vendor/github.com/go-git/go-git/v5/repository.go
+++ b/vendor/github.com/go-git/go-git/v5/repository.go
@@ -956,7 +956,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
}
if o.RecurseSubmodules != NoRecurseSubmodules {
- if err := w.updateSubmodules(&SubmoduleUpdateOptions{
+ if err := w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
RecurseSubmodules: o.RecurseSubmodules,
Depth: func() int {
if o.ShallowSubmodules {
@@ -1037,7 +1037,7 @@ func (r *Repository) setIsBare(isBare bool) error {
return r.Storer.SetConfig(cfg)
}
-func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, head *plumbing.Reference) error {
+func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, _ *plumbing.Reference) error {
if !o.SingleBranch {
return nil
}
diff --git a/vendor/github.com/go-git/go-git/v5/status.go b/vendor/github.com/go-git/go-git/v5/status.go
index 7f18e022..d14f7e65 100644
--- a/vendor/github.com/go-git/go-git/v5/status.go
+++ b/vendor/github.com/go-git/go-git/v5/status.go
@@ -4,6 +4,9 @@ import (
"bytes"
"fmt"
"path/filepath"
+
+ mindex "github.com/go-git/go-git/v5/utils/merkletrie/index"
+ "github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// Status represents the current status of a Worktree.
@@ -77,3 +80,69 @@ const (
Copied StatusCode = 'C'
UpdatedButUnmerged StatusCode = 'U'
)
+
+// StatusStrategy defines the different types of strategies when processing
+// the worktree status.
+type StatusStrategy int
+
+const (
+ // TODO: (V6) Review the default status strategy.
+ // TODO: (V6) Review the type used to represent Status, to enable lazy
+ // processing of statuses going direct to the backing filesystem.
+ defaultStatusStrategy = Empty
+
+ // Empty starts its status map from empty. Missing entries for a given
+ // path means that the file is untracked. This causes a known issue (#119)
+ // whereby unmodified files can be incorrectly reported as untracked.
+ //
+ // This can be used when returning the changed state within a modified Worktree.
+ // For example, to check whether the current worktree is clean.
+ Empty StatusStrategy = 0
+ // Preload goes through all existing nodes from the index and add them to the
+ // status map as unmodified. This is currently the most reliable strategy
+ // although it comes at a performance cost in large repositories.
+ //
+ // This method is recommended when fetching the status of unmodified files.
+ // For example, to confirm the status of a specific file that is either
+ // untracked or unmodified.
+ Preload StatusStrategy = 1
+)
+
+func (s StatusStrategy) new(w *Worktree) (Status, error) {
+ switch s {
+ case Preload:
+ return preloadStatus(w)
+ case Empty:
+ return make(Status), nil
+ }
+ return nil, fmt.Errorf("%w: %+v", ErrUnsupportedStatusStrategy, s)
+}
+
+func preloadStatus(w *Worktree) (Status, error) {
+ idx, err := w.r.Storer.Index()
+ if err != nil {
+ return nil, err
+ }
+
+ idxRoot := mindex.NewRootNode(idx)
+ nodes := []noder.Noder{idxRoot}
+
+ status := make(Status)
+ for len(nodes) > 0 {
+ var node noder.Noder
+ node, nodes = nodes[0], nodes[1:]
+ if node.IsDir() {
+ children, err := node.Children()
+ if err != nil {
+ return nil, err
+ }
+ nodes = append(nodes, children...)
+ continue
+ }
+ fs := status.File(node.Name())
+ fs.Worktree = Unmodified
+ fs.Staging = Unmodified
+ }
+
+ return status, nil
+}
diff --git a/vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go b/vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
index 31c46948..72c9ccfc 100644
--- a/vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
+++ b/vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
@@ -72,6 +72,9 @@ var (
// ErrIsDir is returned when a reference file is attempting to be read,
// but the path specified is a directory.
ErrIsDir = errors.New("reference path is a directory")
+ // ErrEmptyRefFile is returned when a reference file is attempted to be read,
+ // but the file is empty
+ ErrEmptyRefFile = errors.New("ref file is empty")
)
// Options holds configuration for the storage.
@@ -249,7 +252,7 @@ func (d *DotGit) objectPacks() ([]plumbing.Hash, error) {
continue
}
- h := plumbing.NewHash(n[5 : len(n)-5]) //pack-(hash).pack
+ h := plumbing.NewHash(n[5 : len(n)-5]) // pack-(hash).pack
if h.IsZero() {
// Ignore files with badly-formatted names.
continue
@@ -661,18 +664,33 @@ func (d *DotGit) readReferenceFrom(rd io.Reader, name string) (ref *plumbing.Ref
return nil, err
}
+ if len(b) == 0 {
+ return nil, ErrEmptyRefFile
+ }
+
line := strings.TrimSpace(string(b))
return plumbing.NewReferenceFromStrings(name, line), nil
}
+// checkReferenceAndTruncate reads the reference from the given file, or the `pack-refs` file if
+// the file was empty. Then it checks that the old reference matches the stored reference and
+// truncates the file.
func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference) error {
if old == nil {
return nil
}
+
ref, err := d.readReferenceFrom(f, old.Name().String())
+ if errors.Is(err, ErrEmptyRefFile) {
+ // This may happen if the reference is being read from a newly created file.
+ // In that case, try getting the reference from the packed refs file.
+ ref, err = d.packedRef(old.Name())
+ }
+
if err != nil {
return err
}
+
if ref.Hash() != old.Hash() {
return storage.ErrReferenceHasChanged
}
@@ -701,16 +719,16 @@ func (d *DotGit) SetRef(r, old *plumbing.Reference) error {
// Symbolic references are resolved and included in the output.
func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
var refs []*plumbing.Reference
- var seen = make(map[plumbing.ReferenceName]bool)
- if err := d.addRefsFromRefDir(&refs, seen); err != nil {
+ seen := make(map[plumbing.ReferenceName]bool)
+ if err := d.addRefFromHEAD(&refs); err != nil {
return nil, err
}
- if err := d.addRefsFromPackedRefs(&refs, seen); err != nil {
+ if err := d.addRefsFromRefDir(&refs, seen); err != nil {
return nil, err
}
- if err := d.addRefFromHEAD(&refs); err != nil {
+ if err := d.addRefsFromPackedRefs(&refs, seen); err != nil {
return nil, err
}
@@ -815,7 +833,8 @@ func (d *DotGit) addRefsFromPackedRefsFile(refs *[]*plumbing.Reference, f billy.
}
func (d *DotGit) openAndLockPackedRefs(doCreate bool) (
- pr billy.File, err error) {
+ pr billy.File, err error,
+) {
var f billy.File
defer func() {
if err != nil && f != nil {
@@ -1020,7 +1039,7 @@ func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference,
func (d *DotGit) CountLooseRefs() (int, error) {
var refs []*plumbing.Reference
- var seen = make(map[plumbing.ReferenceName]bool)
+ seen := make(map[plumbing.ReferenceName]bool)
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
return 0, err
}
diff --git a/vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go b/vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
index a19176f8..a86ef3e2 100644
--- a/vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
+++ b/vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
@@ -48,7 +48,7 @@ func (s *IndexStorage) Index() (i *index.Index, err error) {
defer ioutil.CheckClose(f, &err)
- d := index.NewDecoder(bufio.NewReader(f))
+ d := index.NewDecoder(f)
err = d.Decode(idx)
return idx, err
}
diff --git a/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go b/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
index e812fe93..91b4acea 100644
--- a/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
+++ b/vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
@@ -431,13 +431,13 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb
defer ioutil.CheckClose(w, &err)
- s.objectCache.Put(obj)
-
bufp := copyBufferPool.Get().(*[]byte)
buf := *bufp
_, err = io.CopyBuffer(w, r, buf)
copyBufferPool.Put(bufp)
+ s.objectCache.Put(obj)
+
return obj, err
}
diff --git a/vendor/github.com/go-git/go-git/v5/submodule.go b/vendor/github.com/go-git/go-git/v5/submodule.go
index 84f020dc..afabb6ac 100644
--- a/vendor/github.com/go-git/go-git/v5/submodule.go
+++ b/vendor/github.com/go-git/go-git/v5/submodule.go
@@ -214,10 +214,10 @@ func (s *Submodule) update(ctx context.Context, o *SubmoduleUpdateOptions, force
return err
}
- return s.doRecursiveUpdate(r, o)
+ return s.doRecursiveUpdate(ctx, r, o)
}
-func (s *Submodule) doRecursiveUpdate(r *Repository, o *SubmoduleUpdateOptions) error {
+func (s *Submodule) doRecursiveUpdate(ctx context.Context, r *Repository, o *SubmoduleUpdateOptions) error {
if o.RecurseSubmodules == NoRecurseSubmodules {
return nil
}
@@ -236,7 +236,7 @@ func (s *Submodule) doRecursiveUpdate(r *Repository, o *SubmoduleUpdateOptions)
*new = *o
new.RecurseSubmodules--
- return l.Update(new)
+ return l.UpdateContext(ctx, new)
}
func (s *Submodule) fetchAndCheckout(
diff --git a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
index cc6dc890..450feb4b 100644
--- a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
+++ b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
@@ -1,12 +1,17 @@
package merkletrie
import (
+ "errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
+var (
+ ErrEmptyFileName = errors.New("empty filename in tree entry")
+)
+
// Action values represent the kind of things a Change can represent:
// insertion, deletions or modifications of files.
type Action int
@@ -121,6 +126,10 @@ func (l *Changes) AddRecursiveDelete(root noder.Path) error {
type noderToChangeFn func(noder.Path) Change // NewInsert or NewDelete
func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error {
+ if root.String() == "" {
+ return ErrEmptyFileName
+ }
+
if !root.IsDir() {
l.Add(ctor(root))
return nil
diff --git a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
index 8090942d..4ef2d990 100644
--- a/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
+++ b/vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
@@ -11,7 +11,7 @@ package merkletrie
// corresponding changes and move the iterators further over both
// trees.
//
-// The table bellow show all the possible comparison results, along
+// The table below shows all the possible comparison results, along
// with what changes should we produce and how to advance the
// iterators.
//
diff --git a/vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go b/vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
index 5009ea80..42f60f7e 100644
--- a/vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
+++ b/vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
@@ -13,7 +13,7 @@ var bufioReader = sync.Pool{
}
// GetBufioReader returns a *bufio.Reader that is managed by a sync.Pool.
-// Returns a bufio.Reader that is resetted with reader and ready for use.
+// Returns a bufio.Reader that is reset with reader and ready for use.
//
// After use, the *bufio.Reader should be put back into the sync.Pool
// by calling PutBufioReader.
diff --git a/vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go b/vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
index dd06fc0b..c67b9783 100644
--- a/vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
+++ b/vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
@@ -35,7 +35,7 @@ func PutByteSlice(buf *[]byte) {
}
// GetBytesBuffer returns a *bytes.Buffer that is managed by a sync.Pool.
-// Returns a buffer that is resetted and ready for use.
+// Returns a buffer that is reset and ready for use.
//
// After use, the *bytes.Buffer should be put back into the sync.Pool
// by calling PutBytesBuffer.
diff --git a/vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go b/vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
index c6138859..edf674d8 100644
--- a/vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
+++ b/vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
@@ -35,7 +35,7 @@ type ZLibReader struct {
}
// GetZlibReader returns a ZLibReader that is managed by a sync.Pool.
-// Returns a ZLibReader that is resetted using a dictionary that is
+// Returns a ZLibReader that is reset using a dictionary that is
// also managed by a sync.Pool.
//
// After use, the ZLibReader should be put back into the sync.Pool
@@ -58,7 +58,7 @@ func PutZlibReader(z ZLibReader) {
}
// GetZlibWriter returns a *zlib.Writer that is managed by a sync.Pool.
-// Returns a writer that is resetted with w and ready for use.
+// Returns a writer that is reset with w and ready for use.
//
// After use, the *zlib.Writer should be put back into the sync.Pool
// by calling PutZlibWriter.
diff --git a/vendor/github.com/go-git/go-git/v5/worktree.go b/vendor/github.com/go-git/go-git/v5/worktree.go
index ab11d42d..8dfa50b1 100644
--- a/vendor/github.com/go-git/go-git/v5/worktree.go
+++ b/vendor/github.com/go-git/go-git/v5/worktree.go
@@ -25,11 +25,12 @@ import (
)
var (
- ErrWorktreeNotClean = errors.New("worktree is not clean")
- ErrSubmoduleNotFound = errors.New("submodule not found")
- ErrUnstagedChanges = errors.New("worktree contains unstaged changes")
- ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink")
- ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
+ ErrWorktreeNotClean = errors.New("worktree is not clean")
+ ErrSubmoduleNotFound = errors.New("submodule not found")
+ ErrUnstagedChanges = errors.New("worktree contains unstaged changes")
+ ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink")
+ ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
+ ErrRestoreWorktreeOnlyNotSupported = errors.New("worktree only is not supported")
)
// Worktree represents a git worktree.
@@ -139,7 +140,7 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
}
if o.RecurseSubmodules != NoRecurseSubmodules {
- return w.updateSubmodules(&SubmoduleUpdateOptions{
+ return w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
RecurseSubmodules: o.RecurseSubmodules,
Auth: o.Auth,
})
@@ -148,13 +149,13 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
return nil
}
-func (w *Worktree) updateSubmodules(o *SubmoduleUpdateOptions) error {
+func (w *Worktree) updateSubmodules(ctx context.Context, o *SubmoduleUpdateOptions) error {
s, err := w.Submodules()
if err != nil {
return err
}
o.Init = true
- return s.Update(o)
+ return s.UpdateContext(ctx, o)
}
// Checkout switch branches or restore working tree files.
@@ -307,13 +308,13 @@ func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error {
}
if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset {
- if err := w.resetIndex(t, dirs); err != nil {
+ if err := w.resetIndex(t, dirs, opts.Files); err != nil {
return err
}
}
if opts.Mode == MergeReset || opts.Mode == HardReset {
- if err := w.resetWorktree(t); err != nil {
+ if err := w.resetWorktree(t, opts.Files); err != nil {
return err
}
}
@@ -321,20 +322,52 @@ func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error {
return nil
}
+// Restore restores specified files in the working tree or stage with contents from
+// a restore source. If a path is tracked but does not exist in the restore,
+// source, it will be removed to match the source.
+//
+// If Staged and Worktree are true, then the restore source will be the index.
+// If only Staged is true, then the restore source will be HEAD.
+// If only Worktree is true or neither Staged nor Worktree are true, will
+// result in ErrRestoreWorktreeOnlyNotSupported because restoring the working
+// tree while leaving the stage untouched is not currently supported.
+//
+// Restore with no files specified will return ErrNoRestorePaths.
+func (w *Worktree) Restore(o *RestoreOptions) error {
+ if err := o.Validate(); err != nil {
+ return err
+ }
+
+ if o.Staged {
+ opts := &ResetOptions{
+ Files: o.Files,
+ }
+
+ if o.Worktree {
+ // If we are doing both Worktree and Staging then it is a hard reset
+ opts.Mode = HardReset
+ } else {
+ // If we are doing just staging then it is a mixed reset
+ opts.Mode = MixedReset
+ }
+
+ return w.Reset(opts)
+ }
+
+ return ErrRestoreWorktreeOnlyNotSupported
+}
+
// Reset the worktree to a specified state.
func (w *Worktree) Reset(opts *ResetOptions) error {
return w.ResetSparsely(opts, nil)
}
-func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
+func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) error {
idx, err := w.r.Storer.Index()
- if len(dirs) > 0 {
- idx.SkipUnless(dirs)
- }
-
if err != nil {
return err
}
+
b := newIndexBuilder(idx)
changes, err := w.diffTreeWithStaging(t, true)
@@ -362,6 +395,13 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
name = ch.From.String()
}
+ if len(files) > 0 {
+ contains := inFiles(files, name)
+ if !contains {
+ continue
+ }
+ }
+
b.Remove(name)
if e == nil {
continue
@@ -376,10 +416,25 @@ func (w *Worktree) resetIndex(t *object.Tree, dirs []string) error {
}
b.Write(idx)
+
+ if len(dirs) > 0 {
+ idx.SkipUnless(dirs)
+ }
+
return w.r.Storer.SetIndex(idx)
}
-func (w *Worktree) resetWorktree(t *object.Tree) error {
+func inFiles(files []string, v string) bool {
+ for _, s := range files {
+ if s == v {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (w *Worktree) resetWorktree(t *object.Tree, files []string) error {
changes, err := w.diffStagingWithWorktree(true, false)
if err != nil {
return err
@@ -395,6 +450,25 @@ func (w *Worktree) resetWorktree(t *object.Tree) error {
if err := w.validChange(ch); err != nil {
return err
}
+
+ if len(files) > 0 {
+ file := ""
+ if ch.From != nil {
+ file = ch.From.String()
+ } else if ch.To != nil {
+ file = ch.To.String()
+ }
+
+ if file == "" {
+ continue
+ }
+
+ contains := inFiles(files, file)
+ if !contains {
+ continue
+ }
+ }
+
if err := w.checkoutChange(ch, t, b); err != nil {
return err
}
@@ -642,7 +716,7 @@ func (w *Worktree) checkoutChangeRegularFile(name string,
return err
}
- return w.addIndexFromFile(name, e.Hash, idx)
+ return w.addIndexFromFile(name, e.Hash, f.Mode, idx)
}
return nil
@@ -725,18 +799,13 @@ func (w *Worktree) addIndexFromTreeEntry(name string, f *object.TreeEntry, idx *
return nil
}
-func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *indexBuilder) error {
+func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, mode filemode.FileMode, idx *indexBuilder) error {
idx.Remove(name)
fi, err := w.Filesystem.Lstat(name)
if err != nil {
return err
}
- mode, err := filemode.NewFromOSFileMode(fi.Mode())
- if err != nil {
- return err
- }
-
e := &index.Entry{
Hash: h,
Name: name,
@@ -1058,7 +1127,7 @@ func rmFileAndDirsIfEmpty(fs billy.Filesystem, name string) error {
dir := filepath.Dir(name)
for {
removed, err := removeDirIfEmpty(fs, dir)
- if err != nil {
+ if err != nil && !os.IsNotExist(err) {
return err
}
diff --git a/vendor/github.com/go-git/go-git/v5/worktree_commit.go b/vendor/github.com/go-git/go-git/v5/worktree_commit.go
index f62054bc..9b1988ae 100644
--- a/vendor/github.com/go-git/go-git/v5/worktree_commit.go
+++ b/vendor/github.com/go-git/go-git/v5/worktree_commit.go
@@ -5,6 +5,7 @@ import (
"errors"
"io"
"path"
+ "regexp"
"sort"
"strings"
@@ -23,6 +24,10 @@ var (
// ErrEmptyCommit occurs when a commit is attempted using a clean
// working tree, with no changes to be committed.
ErrEmptyCommit = errors.New("cannot create empty commit: clean working tree")
+
+ // characters to be removed from user name and/or email before using them to build a commit object
+ // See https://git-scm.com/docs/git-commit#_commit_information
+ invalidCharactersRe = regexp.MustCompile(`[<>\n]`)
)
// Commit stores the current contents of the index in a new commit along with
@@ -38,8 +43,6 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
}
}
- var treeHash plumbing.Hash
-
if opts.Amend {
head, err := w.r.Head()
if err != nil {
@@ -61,16 +64,34 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
return plumbing.ZeroHash, err
}
+ // First handle the case of the first commit in the repository being empty.
+ if len(opts.Parents) == 0 && len(idx.Entries) == 0 && !opts.AllowEmptyCommits {
+ return plumbing.ZeroHash, ErrEmptyCommit
+ }
+
h := &buildTreeHelper{
fs: w.Filesystem,
s: w.r.Storer,
}
- treeHash, err = h.BuildTree(idx, opts)
+ treeHash, err := h.BuildTree(idx, opts)
if err != nil {
return plumbing.ZeroHash, err
}
+ previousTree := plumbing.ZeroHash
+ if len(opts.Parents) > 0 {
+ parentCommit, err := w.r.CommitObject(opts.Parents[0])
+ if err != nil {
+ return plumbing.ZeroHash, err
+ }
+ previousTree = parentCommit.TreeHash
+ }
+
+ if treeHash == previousTree && !opts.AllowEmptyCommits {
+ return plumbing.ZeroHash, ErrEmptyCommit
+ }
+
commit, err := w.buildCommitObject(msg, opts, treeHash)
if err != nil {
return plumbing.ZeroHash, err
@@ -121,8 +142,8 @@ func (w *Worktree) updateHEAD(commit plumbing.Hash) error {
func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) {
commit := &object.Commit{
- Author: *opts.Author,
- Committer: *opts.Committer,
+ Author: w.sanitize(*opts.Author),
+ Committer: w.sanitize(*opts.Committer),
Message: msg,
TreeHash: tree,
ParentHashes: opts.Parents,
@@ -148,6 +169,14 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
return w.r.Storer.SetEncodedObject(obj)
}
+func (w *Worktree) sanitize(signature object.Signature) object.Signature {
+ return object.Signature{
+ Name: invalidCharactersRe.ReplaceAllString(signature.Name, ""),
+ Email: invalidCharactersRe.ReplaceAllString(signature.Email, ""),
+ When: signature.When,
+ }
+}
+
type gpgSigner struct {
key *openpgp.Entity
cfg *packet.Config
@@ -175,10 +204,6 @@ type buildTreeHelper struct {
// BuildTree builds the tree objects and push its to the storer, the hash
// of the root tree is returned.
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
- if len(idx.Entries) == 0 && (opts == nil || !opts.AllowEmptyCommits) {
- return plumbing.ZeroHash, ErrEmptyCommit
- }
-
const rootNode = ""
h.trees = map[string]*object.Tree{rootNode: {}}
h.entries = map[string]*object.TreeEntry{}
diff --git a/vendor/github.com/go-git/go-git/v5/worktree_linux.go b/vendor/github.com/go-git/go-git/v5/worktree_linux.go
index 6fcace2f..f6b85fe3 100644
--- a/vendor/github.com/go-git/go-git/v5/worktree_linux.go
+++ b/vendor/github.com/go-git/go-git/v5/worktree_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package git
@@ -21,6 +22,6 @@ func init() {
}
}
-func isSymlinkWindowsNonAdmin(err error) bool {
+func isSymlinkWindowsNonAdmin(_ error) bool {
return false
}
diff --git a/vendor/github.com/go-git/go-git/v5/worktree_status.go b/vendor/github.com/go-git/go-git/v5/worktree_status.go
index dd9b2439..6e72db97 100644
--- a/vendor/github.com/go-git/go-git/v5/worktree_status.go
+++ b/vendor/github.com/go-git/go-git/v5/worktree_status.go
@@ -29,10 +29,23 @@ var (
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
// files in the worktree.
ErrGlobNoMatches = errors.New("glob pattern did not match any files")
+ // ErrUnsupportedStatusStrategy occurs when an invalid StatusStrategy is used
+ // when processing the Worktree status.
+ ErrUnsupportedStatusStrategy = errors.New("unsupported status strategy")
)
// Status returns the working tree status.
func (w *Worktree) Status() (Status, error) {
+ return w.StatusWithOptions(StatusOptions{Strategy: defaultStatusStrategy})
+}
+
+// StatusOptions defines the options for Worktree.StatusWithOptions().
+type StatusOptions struct {
+ Strategy StatusStrategy
+}
+
+// StatusWithOptions returns the working tree status.
+func (w *Worktree) StatusWithOptions(o StatusOptions) (Status, error) {
var hash plumbing.Hash
ref, err := w.r.Head()
@@ -44,11 +57,14 @@ func (w *Worktree) Status() (Status, error) {
hash = ref.Hash()
}
- return w.status(hash)
+ return w.status(o.Strategy, hash)
}
-func (w *Worktree) status(commit plumbing.Hash) (Status, error) {
- s := make(Status)
+func (w *Worktree) status(ss StatusStrategy, commit plumbing.Hash) (Status, error) {
+ s, err := ss.new(w)
+ if err != nil {
+ return nil, err
+ }
left, err := w.diffCommitWithStaging(commit, false)
if err != nil {
@@ -488,7 +504,7 @@ func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error
return w.r.Storer.SetEncodedObject(obj)
}
-func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.FileInfo) (err error) {
+func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, _ os.FileInfo) (err error) {
src, err := w.Filesystem.Open(path)
if err != nil {
return err
@@ -503,7 +519,7 @@ func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.F
return err
}
-func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, fi os.FileInfo) error {
+func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, _ os.FileInfo) error {
target, err := w.Filesystem.Readlink(path)
if err != nil {
return err
@@ -543,9 +559,11 @@ func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbi
return err
}
- if e.Mode.IsRegular() {
- e.Size = uint32(info.Size())
- }
+ // The entry size must always reflect the current state, otherwise
+ // it will cause go-git's Worktree.Status() to divert from "git status".
+ // The size of a symlink is the length of the path to the target.
+ // The size of Regular and Executable files is the size of the files.
+ e.Size = uint32(info.Size())
fillSystemInfo(e, info.Sys())
return nil
diff --git a/vendor/github.com/skeema/knownhosts/CONTRIBUTING.md b/vendor/github.com/skeema/knownhosts/CONTRIBUTING.md
new file mode 100644
index 00000000..9624f827
--- /dev/null
+++ b/vendor/github.com/skeema/knownhosts/CONTRIBUTING.md
@@ -0,0 +1,36 @@
+# Contributing to skeema/knownhosts
+
+Thank you for your interest in contributing! This document provides guidelines for submitting pull requests.
+
+### Link to an issue
+
+Before starting the pull request process, initial discussion should take place on a GitHub issue first. For bug reports, the issue should track the open bug and confirm it is reproducible. For feature requests, the issue should cover why the feature is necessary.
+
+In the issue comments, discuss your suggested approach for a fix/implementation, and please wait to get feedback before opening a pull request.
+
+### Test coverage
+
+In general, please provide reasonably thorough test coverage. Whenever possible, your PR should aim to match or improve the overall test coverage percentage of the package. You can run tests and check coverage locally using `go test -cover`. We also have CI automation in GitHub Actions which will comment on each pull request with a coverage percentage.
+
+That said, it is fine to submit an initial draft / work-in-progress PR without coverage, if you are waiting on implementation feedback before writing the tests.
+
+We intentionally avoid hard-coding SSH keys or known_hosts files into the test logic. Instead, the tests generate new keys and then use them to generate a known_hosts file, which is then cached/reused for that overall test run, in order to keep performance reasonable.
+
+### Documentation
+
+Exported types require doc comments. The linter CI step will catch this if missing.
+
+### Backwards compatibility
+
+Because this package is imported by [nearly 7000 repos on GitHub](https://github.com/skeema/knownhosts/network/dependents), we must be very strict about backwards compatibility of exported symbols and function signatures.
+
+Backwards compatibility can be very tricky in some situations. In this case, a maintainer may need to add additional commits to your branch to adjust the approach. Please do not take offense if this occurs; it is sometimes simply faster to implement a refactor on our end directly. When the PR/branch is merged, a merge commit will be used, to ensure your commits appear as-is in the repo history and are still properly credited to you.
+
+### Avoid rewriting core x/crypto/ssh/knownhosts logic
+
+skeema/knownhosts is intended to be a relatively thin *wrapper* around x/crypto/ssh/knownhosts, without duplicating or re-implementing the core known_hosts file parsing and host key handling logic. Importers of this package should be confident that it can be used as a nearly-drop-in replacement for x/crypto/ssh/knownhosts without introducing substantial risk, security flaws, parser differentials, or unexpected behavior changes.
+
+To solve shortcomings in x/crypto/ssh/knownhosts, we try to come up with workarounds that still utilize x/crypto/ssh/knownhosts functionality whenever possible.
+
+Some bugs in x/crypto/ssh/knownhosts do require re-reading the known_hosts file here to solve, but we make that *optional* by offering separate constructors/types with and without that behavior.
+
diff --git a/vendor/github.com/skeema/knownhosts/README.md b/vendor/github.com/skeema/knownhosts/README.md
index 36b84761..046bc0ed 100644
--- a/vendor/github.com/skeema/knownhosts/README.md
+++ b/vendor/github.com/skeema/knownhosts/README.md
@@ -1,31 +1,33 @@
# knownhosts: enhanced Golang SSH known_hosts management
[![build status](https://img.shields.io/github/actions/workflow/status/skeema/knownhosts/tests.yml?branch=main)](https://github.com/skeema/knownhosts/actions)
+[![code coverage](https://img.shields.io/coveralls/skeema/knownhosts.svg)](https://coveralls.io/r/skeema/knownhosts)
[![godoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/skeema/knownhosts)
> This repo is brought to you by [Skeema](https://github.com/skeema/skeema), a
> declarative pure-SQL schema management system for MySQL and MariaDB. Our
-> premium products include extensive [SSH tunnel](https://www.skeema.io/docs/options/#ssh)
+> premium products include extensive [SSH tunnel](https://www.skeema.io/docs/features/ssh/)
> functionality, which internally makes use of this package.
Go provides excellent functionality for OpenSSH known_hosts files in its
external package [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts).
-However, that package is somewhat low-level, making it difficult to implement full known_hosts management similar to command-line `ssh`'s behavior for `StrictHostKeyChecking=no` configuration.
+However, that package is somewhat low-level, making it difficult to implement full known_hosts management similar to OpenSSH's command-line behavior. Additionally, [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) has several known issues in edge cases, some of which have remained open for multiple years.
-This repo ([github.com/skeema/knownhosts](https://github.com/skeema/knownhosts)) is a thin wrapper package around [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts), adding the following functionality:
+Package [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) provides a *thin wrapper* around [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts), adding the following improvements and fixes without duplicating its core logic:
* Look up known_hosts public keys for any given host
-* Auto-populate ssh.ClientConfig.HostKeyAlgorithms easily based on known_hosts, providing a solution for [golang/go#29286](https://github.com/golang/go/issues/29286)
+* Auto-populate ssh.ClientConfig.HostKeyAlgorithms easily based on known_hosts, providing a solution for [golang/go#29286](https://github.com/golang/go/issues/29286). (This also properly handles cert algorithms for hosts using CA keys when [using the NewDB constructor](#enhancements-requiring-extra-parsing) added in skeema/knownhosts v1.3.0.)
+* Properly match wildcard hostname known_hosts entries regardless of port number, providing a solution for [golang/go#52056](https://github.com/golang/go/issues/52056). (Added in v1.3.0; requires [using the NewDB constructor](#enhancements-requiring-extra-parsing))
* Write new known_hosts entries to an io.Writer
* Properly format/normalize new known_hosts entries containing ipv6 addresses, providing a solution for [golang/go#53463](https://github.com/golang/go/issues/53463)
-* Determine if an ssh.HostKeyCallback's error corresponds to a host whose key has changed (indicating potential MitM attack) vs a host that just isn't known yet
+* Easily determine if an ssh.HostKeyCallback's error corresponds to a host whose key has changed (indicating potential MitM attack) vs a host that just isn't known yet
## How host key lookup works
Although [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) doesn't directly expose a way to query its known_host map, we use a subtle trick to do so: invoke the HostKeyCallback with a valid host but a bogus key. The resulting KeyError allows us to determine which public keys are actually present for that host.
-By using this technique, [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) doesn't need to duplicate or re-implement any of the actual known_hosts management from [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts).
+By using this technique, [github.com/skeema/knownhosts](https://github.com/skeema/knownhosts) doesn't need to duplicate any of the core known_hosts host-lookup logic from [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts).
## Populating ssh.ClientConfig.HostKeyAlgorithms based on known_hosts
@@ -42,20 +44,33 @@ import (
)
func sshConfigForHost(hostWithPort string) (*ssh.ClientConfig, error) {
- kh, err := knownhosts.New("/home/myuser/.ssh/known_hosts")
+ kh, err := knownhosts.NewDB("/home/myuser/.ssh/known_hosts")
if err != nil {
return nil, err
}
config := &ssh.ClientConfig{
User: "myuser",
Auth: []ssh.AuthMethod{ /* ... */ },
- HostKeyCallback: kh.HostKeyCallback(), // or, equivalently, use ssh.HostKeyCallback(kh)
+ HostKeyCallback: kh.HostKeyCallback(),
HostKeyAlgorithms: kh.HostKeyAlgorithms(hostWithPort),
}
return config, nil
}
```
+## Enhancements requiring extra parsing
+
+Originally, this package did not re-read/re-parse the known_hosts files at all, relying entirely on [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) for all known_hosts file reading and processing. This package only offered a constructor called `New`, returning a host key callback, identical to the call pattern of [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) but with extra methods available on the callback type.
+
+However, a couple shortcomings in [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) cannot possibly be solved without re-reading the known_hosts file. Therefore, as of v1.3.0 of this package, we now offer an alternative constructor `NewDB`, which does an additional read of the known_hosts file (after the one from [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts)), in order to detect:
+
+* @cert-authority lines, so that we can correctly return cert key algorithms instead of normal host key algorithms when appropriate
+* host pattern wildcards, so that we can match OpenSSH's behavior for non-standard port numbers, unlike how [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) normally treats them
+
+Aside from *detecting* these special cases, this package otherwise still directly uses [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts) for host lookups and all other known_hosts file processing. We do **not** fork or re-implement those core behaviors of [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts).
+
+The performance impact of this extra known_hosts read should be minimal, as the file should typically be in the filesystem cache already from the original read by [golang.org/x/crypto/ssh/knownhosts](https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts). That said, users who wish to avoid the extra read can stay with the `New` constructor, which intentionally retains its pre-v1.3.0 behavior as-is. However, the extra fixes for @cert-authority and host pattern wildcards will not be enabled in that case.
+
## Writing new known_hosts entries
If you wish to mimic the behavior of OpenSSH's `StrictHostKeyChecking=no` or `StrictHostKeyChecking=ask`, this package provides a few functions to simplify this task. For example:
@@ -63,7 +78,7 @@ If you wish to mimic the behavior of OpenSSH's `StrictHostKeyChecking=no` or `St
```golang
sshHost := "yourserver.com:22"
khPath := "/home/myuser/.ssh/known_hosts"
-kh, err := knownhosts.New(khPath)
+kh, err := knownhosts.NewDB(khPath)
if err != nil {
log.Fatal("Failed to read known_hosts: ", err)
}
@@ -71,7 +86,8 @@ if err != nil {
// Create a custom permissive hostkey callback which still errors on hosts
// with changed keys, but allows unknown hosts and adds them to known_hosts
cb := ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error {
- err := kh(hostname, remote, key)
+ innerCallback := kh.HostKeyCallback()
+ err := innerCallback(hostname, remote, key)
if knownhosts.IsHostKeyChanged(err) {
return fmt.Errorf("REMOTE HOST IDENTIFICATION HAS CHANGED for host %s! This may indicate a MitM attack.", hostname)
} else if knownhosts.IsHostUnknown(err) {
diff --git a/vendor/github.com/skeema/knownhosts/knownhosts.go b/vendor/github.com/skeema/knownhosts/knownhosts.go
index 4dad7771..2b7536e0 100644
--- a/vendor/github.com/skeema/knownhosts/knownhosts.go
+++ b/vendor/github.com/skeema/knownhosts/knownhosts.go
@@ -3,11 +3,14 @@
package knownhosts
import (
+ "bufio"
+ "bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"net"
+ "os"
"sort"
"strings"
@@ -15,23 +18,133 @@ import (
xknownhosts "golang.org/x/crypto/ssh/knownhosts"
)
-// HostKeyCallback wraps ssh.HostKeyCallback with an additional method to
-// perform host key algorithm lookups from the known_hosts entries.
-type HostKeyCallback ssh.HostKeyCallback
+// HostKeyDB wraps logic in golang.org/x/crypto/ssh/knownhosts with additional
+// behaviors, such as the ability to perform host key/algorithm lookups from
+// known_hosts entries.
+type HostKeyDB struct {
+ callback ssh.HostKeyCallback
+ isCert map[string]bool // keyed by "filename:line"
+ isWildcard map[string]bool // keyed by "filename:line"
+}
-// New creates a host key callback from the given OpenSSH host key files. The
-// returned value may be used in ssh.ClientConfig.HostKeyCallback by casting it
-// to ssh.HostKeyCallback, or using its HostKeyCallback method. Otherwise, it
-// operates the same as the New function in golang.org/x/crypto/ssh/knownhosts.
-func New(files ...string) (HostKeyCallback, error) {
+// NewDB creates a HostKeyDB from the given OpenSSH known_hosts file(s). It
+// reads and parses the provided files one additional time (beyond logic in
+// golang.org/x/crypto/ssh/knownhosts) in order to:
+//
+// - Handle CA lines properly and return ssh.CertAlgo* values when calling the
+// HostKeyAlgorithms method, for use in ssh.ClientConfig.HostKeyAlgorithms
+// - Allow * wildcards in hostnames to match on non-standard ports, providing
+// a workaround for https://github.com/golang/go/issues/52056 in order to
+// align with OpenSSH's wildcard behavior
+//
+// When supplying multiple files, their order does not matter.
+func NewDB(files ...string) (*HostKeyDB, error) {
cb, err := xknownhosts.New(files...)
- return HostKeyCallback(cb), err
+ if err != nil {
+ return nil, err
+ }
+ hkdb := &HostKeyDB{
+ callback: cb,
+ isCert: make(map[string]bool),
+ isWildcard: make(map[string]bool),
+ }
+
+ // Re-read each file a single time, looking for @cert-authority lines. The
+ // logic for reading the file is designed to mimic hostKeyDB.Read from
+ // golang.org/x/crypto/ssh/knownhosts
+ for _, filename := range files {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ scanner := bufio.NewScanner(f)
+ lineNum := 0
+ for scanner.Scan() {
+ lineNum++
+ line := scanner.Bytes()
+ line = bytes.TrimSpace(line)
+ // Does the line start with "@cert-authority" followed by whitespace?
+ if len(line) > 15 && bytes.HasPrefix(line, []byte("@cert-authority")) && (line[15] == ' ' || line[15] == '\t') {
+ mapKey := fmt.Sprintf("%s:%d", filename, lineNum)
+ hkdb.isCert[mapKey] = true
+ line = bytes.TrimSpace(line[16:])
+ }
+ // truncate line to just the host pattern field
+ if i := bytes.IndexAny(line, "\t "); i >= 0 {
+ line = line[:i]
+ }
+ // Does the host pattern contain a * wildcard and no specific port?
+ if i := bytes.IndexRune(line, '*'); i >= 0 && !bytes.Contains(line[i:], []byte("]:")) {
+ mapKey := fmt.Sprintf("%s:%d", filename, lineNum)
+ hkdb.isWildcard[mapKey] = true
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("knownhosts: %s:%d: %w", filename, lineNum, err)
+ }
+ }
+ return hkdb, nil
}
-// HostKeyCallback simply casts the receiver back to ssh.HostKeyCallback, for
-// use in ssh.ClientConfig.HostKeyCallback.
-func (hkcb HostKeyCallback) HostKeyCallback() ssh.HostKeyCallback {
- return ssh.HostKeyCallback(hkcb)
+// HostKeyCallback returns an ssh.HostKeyCallback. This can be used directly in
+// ssh.ClientConfig.HostKeyCallback, as shown in the example for NewDB.
+// Alternatively, you can wrap it with an outer callback to potentially handle
+// appending a new entry to the known_hosts file; see example in WriteKnownHost.
+func (hkdb *HostKeyDB) HostKeyCallback() ssh.HostKeyCallback {
+ // Either NewDB found no wildcard host patterns, or hkdb was created from
+ // HostKeyCallback.ToDB in which case we didn't scan known_hosts for them:
+ // return the callback (which came from x/crypto/ssh/knownhosts) as-is
+ if len(hkdb.isWildcard) == 0 {
+ return hkdb.callback
+ }
+
+ // If we scanned for wildcards and found at least one, return a wrapped
+ // callback with extra behavior: if the host lookup found no matches, and the
+ // host arg had a non-standard port, re-do the lookup on standard port 22. If
+ // that second call returns a *xknownhosts.KeyError, filter down any resulting
+ // Want keys to known wildcard entries.
+ f := func(hostname string, remote net.Addr, key ssh.PublicKey) error {
+ callbackErr := hkdb.callback(hostname, remote, key)
+ if callbackErr == nil || IsHostKeyChanged(callbackErr) { // hostname has known_host entries as-is
+ return callbackErr
+ }
+ justHost, port, splitErr := net.SplitHostPort(hostname)
+ if splitErr != nil || port == "" || port == "22" { // hostname already using standard port
+ return callbackErr
+ }
+ // If we reach here, the port was non-standard and no known_host entries
+ // were found for the non-standard port. Try again with standard port.
+ if tcpAddr, ok := remote.(*net.TCPAddr); ok && tcpAddr.Port != 22 {
+ remote = &net.TCPAddr{
+ IP: tcpAddr.IP,
+ Port: 22,
+ Zone: tcpAddr.Zone,
+ }
+ }
+ callbackErr = hkdb.callback(justHost+":22", remote, key)
+ var keyErr *xknownhosts.KeyError
+ if errors.As(callbackErr, &keyErr) && len(keyErr.Want) > 0 {
+ wildcardKeys := make([]xknownhosts.KnownKey, 0, len(keyErr.Want))
+ for _, wantKey := range keyErr.Want {
+ if hkdb.isWildcard[fmt.Sprintf("%s:%d", wantKey.Filename, wantKey.Line)] {
+ wildcardKeys = append(wildcardKeys, wantKey)
+ }
+ }
+ callbackErr = &xknownhosts.KeyError{
+ Want: wildcardKeys,
+ }
+ }
+ return callbackErr
+ }
+ return ssh.HostKeyCallback(f)
+}
+
+// PublicKey wraps ssh.PublicKey with an additional field, to identify
+// whether the key corresponds to a certificate authority.
+type PublicKey struct {
+ ssh.PublicKey
+ Cert bool
}
// HostKeys returns a slice of known host public keys for the supplied host:port
@@ -39,12 +152,16 @@ func (hkcb HostKeyCallback) HostKeyCallback() ssh.HostKeyCallback {
// already known. For hosts that have multiple known_hosts entries (for
// different key types), the result will be sorted by known_hosts filename and
// line number.
-func (hkcb HostKeyCallback) HostKeys(hostWithPort string) (keys []ssh.PublicKey) {
+// If hkdb was originally created by calling NewDB, the Cert boolean field of
+// each result entry reports whether the key corresponded to a @cert-authority
+// line. If hkdb was NOT obtained from NewDB, then Cert will always be false.
+func (hkdb *HostKeyDB) HostKeys(hostWithPort string) (keys []PublicKey) {
var keyErr *xknownhosts.KeyError
placeholderAddr := &net.TCPAddr{IP: []byte{0, 0, 0, 0}}
placeholderPubKey := &fakePublicKey{}
var kkeys []xknownhosts.KnownKey
- if hkcbErr := hkcb(hostWithPort, placeholderAddr, placeholderPubKey); errors.As(hkcbErr, &keyErr) {
+ callback := hkdb.HostKeyCallback()
+ if hkcbErr := callback(hostWithPort, placeholderAddr, placeholderPubKey); errors.As(hkcbErr, &keyErr) {
kkeys = append(kkeys, keyErr.Want...)
knownKeyLess := func(i, j int) bool {
if kkeys[i].Filename < kkeys[j].Filename {
@@ -53,9 +170,14 @@ func (hkcb HostKeyCallback) HostKeys(hostWithPort string) (keys []ssh.PublicKey)
return (kkeys[i].Filename == kkeys[j].Filename && kkeys[i].Line < kkeys[j].Line)
}
sort.Slice(kkeys, knownKeyLess)
- keys = make([]ssh.PublicKey, len(kkeys))
+ keys = make([]PublicKey, len(kkeys))
for n := range kkeys {
- keys[n] = kkeys[n].Key
+ keys[n] = PublicKey{
+ PublicKey: kkeys[n].Key,
+ }
+ if len(hkdb.isCert) > 0 {
+ keys[n].Cert = hkdb.isCert[fmt.Sprintf("%s:%d", kkeys[n].Filename, kkeys[n].Line)]
+ }
}
}
return keys
@@ -66,17 +188,23 @@ func (hkcb HostKeyCallback) HostKeys(hostWithPort string) (keys []ssh.PublicKey)
// is not already known. The result may be used in ssh.ClientConfig's
// HostKeyAlgorithms field, either as-is or after filtering (if you wish to
// ignore or prefer particular algorithms). For hosts that have multiple
-// known_hosts entries (for different key types), the result will be sorted by
+// known_hosts entries (of different key types), the result will be sorted by
// known_hosts filename and line number.
-func (hkcb HostKeyCallback) HostKeyAlgorithms(hostWithPort string) (algos []string) {
+// If hkdb was originally created by calling NewDB, any @cert-authority lines
+// in the known_hosts file will properly be converted to the corresponding
+// ssh.CertAlgo* values.
+func (hkdb *HostKeyDB) HostKeyAlgorithms(hostWithPort string) (algos []string) {
// We ensure that algos never contains duplicates. This is done for robustness
// even though currently golang.org/x/crypto/ssh/knownhosts never exposes
// multiple keys of the same type. This way our behavior here is unaffected
// even if https://github.com/golang/go/issues/28870 is implemented, for
// example by https://github.com/golang/crypto/pull/254.
- hostKeys := hkcb.HostKeys(hostWithPort)
+ hostKeys := hkdb.HostKeys(hostWithPort)
seen := make(map[string]struct{}, len(hostKeys))
- addAlgo := func(typ string) {
+ addAlgo := func(typ string, cert bool) {
+ if cert {
+ typ = keyTypeToCertAlgo(typ)
+ }
if _, already := seen[typ]; !already {
algos = append(algos, typ)
seen[typ] = struct{}{}
@@ -88,25 +216,143 @@ func (hkcb HostKeyCallback) HostKeyAlgorithms(hostWithPort string) (algos []stri
// 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.
- addAlgo(ssh.KeyAlgoRSASHA512)
- addAlgo(ssh.KeyAlgoRSASHA256)
+ addAlgo(ssh.KeyAlgoRSASHA512, key.Cert)
+ addAlgo(ssh.KeyAlgoRSASHA256, key.Cert)
}
- addAlgo(typ)
+ addAlgo(typ, key.Cert)
}
return algos
}
+func keyTypeToCertAlgo(keyType string) string {
+ switch keyType {
+ case ssh.KeyAlgoRSA:
+ return ssh.CertAlgoRSAv01
+ case ssh.KeyAlgoRSASHA256:
+ return ssh.CertAlgoRSASHA256v01
+ case ssh.KeyAlgoRSASHA512:
+ return ssh.CertAlgoRSASHA512v01
+ case ssh.KeyAlgoDSA:
+ return ssh.CertAlgoDSAv01
+ case ssh.KeyAlgoECDSA256:
+ return ssh.CertAlgoECDSA256v01
+ case ssh.KeyAlgoSKECDSA256:
+ return ssh.CertAlgoSKECDSA256v01
+ case ssh.KeyAlgoECDSA384:
+ return ssh.CertAlgoECDSA384v01
+ case ssh.KeyAlgoECDSA521:
+ return ssh.CertAlgoECDSA521v01
+ case ssh.KeyAlgoED25519:
+ return ssh.CertAlgoED25519v01
+ case ssh.KeyAlgoSKED25519:
+ return ssh.CertAlgoSKED25519v01
+ }
+ return ""
+}
+
+// HostKeyCallback wraps ssh.HostKeyCallback with additional methods to
+// perform host key and algorithm lookups from the known_hosts entries. It is
+// otherwise identical to ssh.HostKeyCallback, and does not introduce any file-
+// parsing behavior beyond what is in golang.org/x/crypto/ssh/knownhosts.
+//
+// In most situations, use HostKeyDB and its constructor NewDB instead of using
+// the HostKeyCallback type. The HostKeyCallback type is only provided for
+// backwards compatibility with older versions of this package, as well as for
+// very strict situations where any extra known_hosts file-parsing is
+// undesirable.
+//
+// Methods of HostKeyCallback do not provide any special treatment for
+// @cert-authority lines, which will (incorrectly) look like normal non-CA host
+// keys. Additionally, HostKeyCallback lacks the fix for applying * wildcard
+// known_host entries to all ports, like OpenSSH's behavior.
+type HostKeyCallback ssh.HostKeyCallback
+
+// New creates a HostKeyCallback from the given OpenSSH known_hosts file(s). The
+// returned value may be used in ssh.ClientConfig.HostKeyCallback by casting it
+// to ssh.HostKeyCallback, or using its HostKeyCallback method. Otherwise, it
+// operates the same as the New function in golang.org/x/crypto/ssh/knownhosts.
+// When supplying multiple files, their order does not matter.
+//
+// In most situations, you should avoid this function, as the returned value
+// lacks several enhanced behaviors. See doc comment for HostKeyCallback for
+// more information. Instead, most callers should use NewDB to create a
+// HostKeyDB, which includes these enhancements.
+func New(files ...string) (HostKeyCallback, error) {
+ cb, err := xknownhosts.New(files...)
+ return HostKeyCallback(cb), err
+}
+
+// HostKeyCallback simply casts the receiver back to ssh.HostKeyCallback, for
+// use in ssh.ClientConfig.HostKeyCallback.
+func (hkcb HostKeyCallback) HostKeyCallback() ssh.HostKeyCallback {
+ return ssh.HostKeyCallback(hkcb)
+}
+
+// ToDB converts the receiver into a HostKeyDB. However, the returned HostKeyDB
+// lacks the enhanced behaviors described in the doc comment for NewDB: proper
+// CA support, and wildcard matching on nonstandard ports.
+//
+// It is generally preferable to create a HostKeyDB by using NewDB. The ToDB
+// method is only provided for situations in which the calling code needs to
+// make the extra NewDB behaviors optional / user-configurable, perhaps for
+// reasons of performance or code trust (since NewDB reads the known_host file
+// an extra time, which may be undesirable in some strict situations). This way,
+// callers can conditionally create a non-enhanced HostKeyDB by using New and
+// ToDB. See code example.
+func (hkcb HostKeyCallback) ToDB() *HostKeyDB {
+ // This intentionally leaves the isCert and isWildcard map fields as nil, as
+ // there is no way to retroactively populate them from just a HostKeyCallback.
+ // Methods of HostKeyDB will skip any related enhanced behaviors accordingly.
+ return &HostKeyDB{callback: ssh.HostKeyCallback(hkcb)}
+}
+
+// HostKeys returns a slice of known host public keys for the supplied host:port
+// found in the known_hosts file(s), or an empty slice if the host is not
+// already known. For hosts that have multiple known_hosts entries (for
+// different key types), the result will be sorted by known_hosts filename and
+// line number.
+// In the returned values, there is no way to distinguish between CA keys
+// (known_hosts lines beginning with @cert-authority) and regular keys. To do
+// so, see NewDB and HostKeyDB.HostKeys instead.
+func (hkcb HostKeyCallback) HostKeys(hostWithPort string) []ssh.PublicKey {
+ annotatedKeys := hkcb.ToDB().HostKeys(hostWithPort)
+ rawKeys := make([]ssh.PublicKey, len(annotatedKeys))
+ for n, ak := range annotatedKeys {
+ rawKeys[n] = ak.PublicKey
+ }
+ return rawKeys
+}
+
+// HostKeyAlgorithms returns a slice of host key algorithms for the supplied
+// host:port found in the known_hosts file(s), or an empty slice if the host
+// is not already known. The result may be used in ssh.ClientConfig's
+// HostKeyAlgorithms field, either as-is or after filtering (if you wish to
+// ignore or prefer particular algorithms). For hosts that have multiple
+// known_hosts entries (for different key types), the result will be sorted by
+// known_hosts filename and line number.
+// The returned values will not include ssh.CertAlgo* values. If any
+// known_hosts lines had @cert-authority prefixes, their original key algo will
+// be returned instead. For proper CA support, see NewDB and
+// HostKeyDB.HostKeyAlgorithms instead.
+func (hkcb HostKeyCallback) HostKeyAlgorithms(hostWithPort string) (algos []string) {
+ return hkcb.ToDB().HostKeyAlgorithms(hostWithPort)
+}
+
// HostKeyAlgorithms is a convenience function for performing host key algorithm
// lookups on an ssh.HostKeyCallback directly. It is intended for use in code
// paths that stay with the New method of golang.org/x/crypto/ssh/knownhosts
-// rather than this package's New method.
+// rather than this package's New or NewDB methods.
+// The returned values will not include ssh.CertAlgo* values. If any
+// known_hosts lines had @cert-authority prefixes, their original key algo will
+// be returned instead. For proper CA support, see NewDB and
+// HostKeyDB.HostKeyAlgorithms instead.
func HostKeyAlgorithms(cb ssh.HostKeyCallback, hostWithPort string) []string {
return HostKeyCallback(cb).HostKeyAlgorithms(hostWithPort)
}
// IsHostKeyChanged returns a boolean indicating whether the error indicates
// the host key has changed. It is intended to be called on the error returned
-// from invoking a HostKeyCallback to check whether an SSH host is known.
+// from invoking a host key callback, to check whether an SSH host is known.
func IsHostKeyChanged(err error) bool {
var keyErr *xknownhosts.KeyError
return errors.As(err, &keyErr) && len(keyErr.Want) > 0
@@ -114,7 +360,7 @@ func IsHostKeyChanged(err error) bool {
// IsHostUnknown returns a boolean indicating whether the error represents an
// unknown host. It is intended to be called on the error returned from invoking
-// a HostKeyCallback to check whether an SSH host is known.
+// a host key callback to check whether an SSH host is known.
func IsHostUnknown(err error) bool {
var keyErr *xknownhosts.KeyError
return errors.As(err, &keyErr) && len(keyErr.Want) == 0
@@ -154,11 +400,12 @@ func Line(addresses []string, key ssh.PublicKey) string {
}, " ")
}
-// WriteKnownHost writes a known_hosts line to writer for the supplied hostname,
+// WriteKnownHost writes a known_hosts line to w for the supplied hostname,
// remote, and key. This is useful when writing a custom hostkey callback which
-// wraps a callback obtained from knownhosts.New to provide additional
-// known_hosts management functionality. The hostname, remote, and key typically
-// correspond to the callback's args.
+// wraps a callback obtained from this package to provide additional known_hosts
+// management functionality. The hostname, remote, and key typically correspond
+// to the callback's args. This function does not support writing
+// @cert-authority lines.
func WriteKnownHost(w io.Writer, hostname string, remote net.Addr, key ssh.PublicKey) error {
// Always include hostname; only also include remote if it isn't a zero value
// and doesn't normalize to the same string as hostname.
@@ -177,6 +424,14 @@ func WriteKnownHost(w io.Writer, hostname string, remote net.Addr, key ssh.Publi
return err
}
+// WriteKnownHostCA writes a @cert-authority line to w for the supplied host
+// name/pattern and key.
+func WriteKnownHostCA(w io.Writer, hostPattern string, key ssh.PublicKey) error {
+ encodedKey := base64.StdEncoding.EncodeToString(key.Marshal())
+ _, err := fmt.Fprintf(w, "@cert-authority %s %s %s\n", hostPattern, key.Type(), encodedKey)
+ return err
+}
+
// fakePublicKey is used as part of the work-around for
// https://github.com/golang/go/issues/29286
type fakePublicKey struct{}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
index 4d4b4aad..7e19eba0 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
@@ -7,10 +7,13 @@ import (
"time"
)
-type CompareType int
+// Deprecated: CompareType has only ever been for internal use and has accidentally been published since v1.6.0. Do not use it.
+type CompareType = compareResult
+
+type compareResult int
const (
- compareLess CompareType = iota - 1
+ compareLess compareResult = iota - 1
compareEqual
compareGreater
)
@@ -39,7 +42,7 @@ var (
bytesType = reflect.TypeOf([]byte{})
)
-func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
+func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) {
obj1Value := reflect.ValueOf(obj1)
obj2Value := reflect.ValueOf(obj2)
@@ -325,7 +328,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
}
- return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
+ if timeObj1.Before(timeObj2) {
+ return compareLess, true
+ }
+ if timeObj1.Equal(timeObj2) {
+ return compareEqual, true
+ }
+ return compareGreater, true
}
case reflect.Slice:
{
@@ -345,7 +354,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
}
- return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
+ return compareResult(bytes.Compare(bytesObj1, bytesObj2)), true
}
case reflect.Uintptr:
{
@@ -381,7 +390,7 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
if h, ok := t.(tHelper); ok {
h.Helper()
}
- return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
+ return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
}
// GreaterOrEqual asserts that the first element is greater than or equal to the second
@@ -394,7 +403,7 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
if h, ok := t.(tHelper); ok {
h.Helper()
}
- return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
+ return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
}
// Less asserts that the first element is less than the second
@@ -406,7 +415,7 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
if h, ok := t.(tHelper); ok {
h.Helper()
}
- return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
+ return compareTwoValues(t, e1, e2, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
}
// LessOrEqual asserts that the first element is less than or equal to the second
@@ -419,7 +428,7 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
if h, ok := t.(tHelper); ok {
h.Helper()
}
- return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
+ return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
}
// Positive asserts that the specified element is positive
@@ -431,7 +440,7 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
h.Helper()
}
zero := reflect.Zero(reflect.TypeOf(e))
- return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
+ return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
}
// Negative asserts that the specified element is negative
@@ -443,10 +452,10 @@ func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
h.Helper()
}
zero := reflect.Zero(reflect.TypeOf(e))
- return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
+ return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, "\"%v\" is not negative", msgAndArgs...)
}
-func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
+func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
@@ -469,7 +478,7 @@ func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedCompare
return true
}
-func containsValue(values []CompareType, value CompareType) bool {
+func containsValue(values []compareResult, value compareResult) bool {
for _, v := range values {
if v == value {
return true
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
index 3ddab109..19063416 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_format.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -104,8 +104,8 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{},
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
}
-// EqualValuesf asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValuesf asserts that two objects are equal or convertible to the larger
+// type and equal.
//
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
@@ -186,7 +186,7 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -568,6 +568,23 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
}
+// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
+//
+// assert.NotElementsMatchf(t, [1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
+//
+// assert.NotElementsMatchf(t, [1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
+func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
+}
+
// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
@@ -604,7 +621,16 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
}
-// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// NotErrorAsf asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func NotErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
+}
+
+// NotErrorIsf asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
index a84e09bd..21629087 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -186,8 +186,8 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface
return EqualExportedValuesf(a.t, expected, actual, msg, args...)
}
-// EqualValues asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValues asserts that two objects are equal or convertible to the larger
+// type and equal.
//
// a.EqualValues(uint32(123), int32(123))
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
@@ -197,8 +197,8 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
return EqualValues(a.t, expected, actual, msgAndArgs...)
}
-// EqualValuesf asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValuesf asserts that two objects are equal or convertible to the larger
+// type and equal.
//
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
@@ -336,7 +336,7 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
// a.EventuallyWithT(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -361,7 +361,7 @@ func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1128,6 +1128,40 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
return NotContainsf(a.t, s, contains, msg, args...)
}
+// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// a.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false
+//
+// a.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true
+//
+// a.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true
+func (a *Assertions) NotElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotElementsMatch(a.t, listA, listB, msgAndArgs...)
+}
+
+// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// a.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
+//
+// a.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
+//
+// a.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
+func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotElementsMatchf(a.t, listA, listB, msg, args...)
+}
+
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
@@ -1200,7 +1234,25 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
return NotEqualf(a.t, expected, actual, msg, args...)
}
-// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// NotErrorAs asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorAs(a.t, err, target, msgAndArgs...)
+}
+
+// NotErrorAsf asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func (a *Assertions) NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotErrorAsf(a.t, err, target, msg, args...)
+}
+
+// NotErrorIs asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
@@ -1209,7 +1261,7 @@ func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface
return NotErrorIs(a.t, err, target, msgAndArgs...)
}
-// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// NotErrorIsf asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go
index 00df62a0..1d2f7182 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_order.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go
@@ -6,7 +6,7 @@ import (
)
// isOrdered checks that collection contains orderable elements.
-func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
+func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool {
objKind := reflect.TypeOf(object).Kind()
if objKind != reflect.Slice && objKind != reflect.Array {
return false
@@ -50,7 +50,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareT
// assert.IsIncreasing(t, []float{1, 2})
// assert.IsIncreasing(t, []string{"a", "b"})
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
+ return isOrdered(t, object, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
}
// IsNonIncreasing asserts that the collection is not increasing
@@ -59,7 +59,7 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
// assert.IsNonIncreasing(t, []float{2, 1})
// assert.IsNonIncreasing(t, []string{"b", "a"})
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
+ return isOrdered(t, object, []compareResult{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
}
// IsDecreasing asserts that the collection is decreasing
@@ -68,7 +68,7 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{})
// assert.IsDecreasing(t, []float{2, 1})
// assert.IsDecreasing(t, []string{"b", "a"})
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
+ return isOrdered(t, object, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
}
// IsNonDecreasing asserts that the collection is not decreasing
@@ -77,5 +77,5 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
// assert.IsNonDecreasing(t, []float{1, 2})
// assert.IsNonDecreasing(t, []string{"a", "b"})
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
+ return isOrdered(t, object, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
index 0b7570f2..4e91332b 100644
--- a/vendor/github.com/stretchr/testify/assert/assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -19,7 +19,9 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/pmezard/go-difflib/difflib"
- "gopkg.in/yaml.v3"
+
+ // Wrapper around gopkg.in/yaml.v3
+ "github.com/stretchr/testify/assert/yaml"
)
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
@@ -45,6 +47,10 @@ type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
// for table driven tests.
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
+// PanicAssertionFunc is a common function prototype when validating a panic value. Can be useful
+// for table driven tests.
+type PanicAssertionFunc = func(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool
+
// Comparison is a custom function that returns true on success and false on failure
type Comparison func() (success bool)
@@ -496,7 +502,13 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
h.Helper()
}
- if !samePointers(expected, actual) {
+ same, ok := samePointers(expected, actual)
+ if !ok {
+ return Fail(t, "Both arguments must be pointers", msgAndArgs...)
+ }
+
+ if !same {
+ // both are pointers but not the same type & pointing to the same address
return Fail(t, fmt.Sprintf("Not same: \n"+
"expected: %p %#v\n"+
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
@@ -516,7 +528,13 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
h.Helper()
}
- if samePointers(expected, actual) {
+ same, ok := samePointers(expected, actual)
+ if !ok {
+ //fails when the arguments are not pointers
+ return !(Fail(t, "Both arguments must be pointers", msgAndArgs...))
+ }
+
+ if same {
return Fail(t, fmt.Sprintf(
"Expected and actual point to the same object: %p %#v",
expected, expected), msgAndArgs...)
@@ -524,21 +542,23 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
return true
}
-// samePointers compares two generic interface objects and returns whether
-// they point to the same object
-func samePointers(first, second interface{}) bool {
+// samePointers checks if two generic interface objects are pointers of the same
+// type pointing to the same object. It returns two values: same indicating if
+// they are the same type and point to the same object, and ok indicating that
+// both inputs are pointers.
+func samePointers(first, second interface{}) (same bool, ok bool) {
firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
- return false
+ return false, false //not both are pointers
}
firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
if firstType != secondType {
- return false
+ return false, true // both are pointers, but of different types
}
// compare pointer addresses
- return first == second
+ return first == second, true
}
// formatUnequalValues takes two values of arbitrary types and returns string
@@ -572,8 +592,8 @@ func truncatingFormat(data interface{}) string {
return value
}
-// EqualValues asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValues asserts that two objects are equal or convertible to the larger
+// type and equal.
//
// assert.EqualValues(t, uint32(123), int32(123))
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
@@ -615,21 +635,6 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ..
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
}
- if aType.Kind() == reflect.Ptr {
- aType = aType.Elem()
- }
- if bType.Kind() == reflect.Ptr {
- bType = bType.Elem()
- }
-
- if aType.Kind() != reflect.Struct {
- return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
- }
-
- if bType.Kind() != reflect.Struct {
- return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
- }
-
expected = copyExportedFields(expected)
actual = copyExportedFields(actual)
@@ -1170,6 +1175,39 @@ func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) stri
return msg.String()
}
+// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 1, 2, 3]) -> false
+//
+// assert.NotElementsMatch(t, [1, 1, 2, 3], [1, 2, 3]) -> true
+//
+// assert.NotElementsMatch(t, [1, 2, 3], [1, 2, 4]) -> true
+func NotElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if isEmpty(listA) && isEmpty(listB) {
+ return Fail(t, "listA and listB contain the same elements", msgAndArgs)
+ }
+
+ if !isList(t, listA, msgAndArgs...) {
+ return Fail(t, "listA is not a list type", msgAndArgs...)
+ }
+ if !isList(t, listB, msgAndArgs...) {
+ return Fail(t, "listB is not a list type", msgAndArgs...)
+ }
+
+ extraA, extraB := diffLists(listA, listB)
+ if len(extraA) == 0 && len(extraB) == 0 {
+ return Fail(t, "listA and listB contain the same elements", msgAndArgs)
+ }
+
+ return true
+}
+
// Condition uses a Comparison to assert a complex condition.
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
@@ -1488,6 +1526,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
if err != nil {
return Fail(t, err.Error(), msgAndArgs...)
}
+ if math.IsNaN(actualEpsilon) {
+ return Fail(t, "relative error is NaN", msgAndArgs...)
+ }
if actualEpsilon > epsilon {
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
" < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
@@ -1611,7 +1652,6 @@ func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...in
// matchRegexp return true if a specified regexp matches a string.
func matchRegexp(rx interface{}, str interface{}) bool {
-
var r *regexp.Regexp
if rr, ok := rx.(*regexp.Regexp); ok {
r = rr
@@ -1619,7 +1659,14 @@ func matchRegexp(rx interface{}, str interface{}) bool {
r = regexp.MustCompile(fmt.Sprint(rx))
}
- return (r.FindStringIndex(fmt.Sprint(str)) != nil)
+ switch v := str.(type) {
+ case []byte:
+ return r.Match(v)
+ case string:
+ return r.MatchString(v)
+ default:
+ return r.MatchString(fmt.Sprint(v))
+ }
}
@@ -1872,7 +1919,7 @@ var spewConfigStringerEnabled = spew.ConfigState{
MaxDepth: 10,
}
-type tHelper interface {
+type tHelper = interface {
Helper()
}
@@ -1911,6 +1958,9 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
// CollectT implements the TestingT interface and collects all errors.
type CollectT struct {
+ // A slice of errors. Non-nil slice denotes a failure.
+ // If it's non-nil but len(c.errors) == 0, this is also a failure
+ // obtained by direct c.FailNow() call.
errors []error
}
@@ -1919,9 +1969,10 @@ func (c *CollectT) Errorf(format string, args ...interface{}) {
c.errors = append(c.errors, fmt.Errorf(format, args...))
}
-// FailNow panics.
-func (*CollectT) FailNow() {
- panic("Assertion failed")
+// FailNow stops execution by calling runtime.Goexit.
+func (c *CollectT) FailNow() {
+ c.fail()
+ runtime.Goexit()
}
// Deprecated: That was a method for internal usage that should not have been published. Now just panics.
@@ -1934,6 +1985,16 @@ func (*CollectT) Copy(TestingT) {
panic("Copy() is deprecated")
}
+func (c *CollectT) fail() {
+ if !c.failed() {
+ c.errors = []error{} // Make it non-nil to mark a failure.
+ }
+}
+
+func (c *CollectT) failed() bool {
+ return c.errors != nil
+}
+
// EventuallyWithT asserts that given condition will be met in waitFor time,
// periodically checking target function each tick. In contrast to Eventually,
// it supplies a CollectT to the condition function, so that the condition
@@ -1951,14 +2012,14 @@ func (*CollectT) Copy(TestingT) {
// assert.EventuallyWithT(t, func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
var lastFinishedTickErrs []error
- ch := make(chan []error, 1)
+ ch := make(chan *CollectT, 1)
timer := time.NewTimer(waitFor)
defer timer.Stop()
@@ -1978,16 +2039,16 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
go func() {
collect := new(CollectT)
defer func() {
- ch <- collect.errors
+ ch <- collect
}()
condition(collect)
}()
- case errs := <-ch:
- if len(errs) == 0 {
+ case collect := <-ch:
+ if !collect.failed() {
return true
}
// Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
- lastFinishedTickErrs = errs
+ lastFinishedTickErrs = collect.errors
tick = ticker.C
}
}
@@ -2049,7 +2110,7 @@ func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
), msgAndArgs...)
}
-// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// NotErrorIs asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
@@ -2090,6 +2151,24 @@ func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{
), msgAndArgs...)
}
+// NotErrorAs asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if !errors.As(err, target) {
+ return true
+ }
+
+ chain := buildErrorChainString(err)
+
+ return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+
+ "found: %q\n"+
+ "in chain: %s", target, chain,
+ ), msgAndArgs...)
+}
+
func buildErrorChainString(err error) string {
if err == nil {
return ""
diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go
new file mode 100644
index 00000000..baa0cc7d
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go
@@ -0,0 +1,25 @@
+//go:build testify_yaml_custom && !testify_yaml_fail && !testify_yaml_default
+// +build testify_yaml_custom,!testify_yaml_fail,!testify_yaml_default
+
+// Package yaml is an implementation of YAML functions that calls a pluggable implementation.
+//
+// This implementation is selected with the testify_yaml_custom build tag.
+//
+// go test -tags testify_yaml_custom
+//
+// This implementation can be used at build time to replace the default implementation
+// to avoid linking with [gopkg.in/yaml.v3].
+//
+// In your test package:
+//
+// import assertYaml "github.com/stretchr/testify/assert/yaml"
+//
+// func init() {
+// assertYaml.Unmarshal = func (in []byte, out interface{}) error {
+// // ...
+// return nil
+// }
+// }
+package yaml
+
+var Unmarshal func(in []byte, out interface{}) error
diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
new file mode 100644
index 00000000..b83c6cf6
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
@@ -0,0 +1,37 @@
+//go:build !testify_yaml_fail && !testify_yaml_custom
+// +build !testify_yaml_fail,!testify_yaml_custom
+
+// Package yaml is just an indirection to handle YAML deserialization.
+//
+// This package is just an indirection that allows the builder to override the
+// indirection with an alternative implementation of this package that uses
+// another implementation of YAML deserialization. This allows to not either not
+// use YAML deserialization at all, or to use another implementation than
+// [gopkg.in/yaml.v3] (for example for license compatibility reasons, see [PR #1120]).
+//
+// Alternative implementations are selected using build tags:
+//
+// - testify_yaml_fail: [Unmarshal] always fails with an error
+// - testify_yaml_custom: [Unmarshal] is a variable. Caller must initialize it
+// before calling any of [github.com/stretchr/testify/assert.YAMLEq] or
+// [github.com/stretchr/testify/assert.YAMLEqf].
+//
+// Usage:
+//
+// go test -tags testify_yaml_fail
+//
+// You can check with "go list" which implementation is linked:
+//
+// go list -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
+// go list -tags testify_yaml_fail -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
+// go list -tags testify_yaml_custom -f '{{.Imports}}' github.com/stretchr/testify/assert/yaml
+//
+// [PR #1120]: https://github.com/stretchr/testify/pull/1120
+package yaml
+
+import goyaml "gopkg.in/yaml.v3"
+
+// Unmarshal is just a wrapper of [gopkg.in/yaml.v3.Unmarshal].
+func Unmarshal(in []byte, out interface{}) error {
+ return goyaml.Unmarshal(in, out)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go b/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
new file mode 100644
index 00000000..e78f7dfe
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
@@ -0,0 +1,18 @@
+//go:build testify_yaml_fail && !testify_yaml_custom && !testify_yaml_default
+// +build testify_yaml_fail,!testify_yaml_custom,!testify_yaml_default
+
+// Package yaml is an implementation of YAML functions that always fail.
+//
+// This implementation can be used at build time to replace the default implementation
+// to avoid linking with [gopkg.in/yaml.v3]:
+//
+// go test -tags testify_yaml_fail
+package yaml
+
+import "errors"
+
+var errNotImplemented = errors.New("YAML functions are not available (see https://pkg.go.dev/github.com/stretchr/testify/assert/yaml)")
+
+func Unmarshal([]byte, interface{}) error {
+ return errNotImplemented
+}
diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go
index 506a82f8..d8921950 100644
--- a/vendor/github.com/stretchr/testify/require/require.go
+++ b/vendor/github.com/stretchr/testify/require/require.go
@@ -34,9 +34,9 @@ func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interfac
// Contains asserts that the specified string, list(array, slice...) or map contains the
// specified substring or element.
//
-// assert.Contains(t, "Hello World", "World")
-// assert.Contains(t, ["Hello", "World"], "World")
-// assert.Contains(t, {"Hello": "World"}, "Hello")
+// require.Contains(t, "Hello World", "World")
+// require.Contains(t, ["Hello", "World"], "World")
+// require.Contains(t, {"Hello": "World"}, "Hello")
func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -50,9 +50,9 @@ func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...int
// Containsf asserts that the specified string, list(array, slice...) or map contains the
// specified substring or element.
//
-// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
-// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
-// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
+// require.Containsf(t, "Hello World", "World", "error message %s", "formatted")
+// require.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
+// require.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -91,7 +91,7 @@ func DirExistsf(t TestingT, path string, msg string, args ...interface{}) {
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
// the number of appearances of each of them in both lists should match.
//
-// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
+// require.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -106,7 +106,7 @@ func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
// the number of appearances of each of them in both lists should match.
//
-// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+// require.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -120,7 +120,7 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
-// assert.Empty(t, obj)
+// require.Empty(t, obj)
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -134,7 +134,7 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
-// assert.Emptyf(t, obj, "error message %s", "formatted")
+// require.Emptyf(t, obj, "error message %s", "formatted")
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -147,7 +147,7 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) {
// Equal asserts that two objects are equal.
//
-// assert.Equal(t, 123, 123)
+// require.Equal(t, 123, 123)
//
// Pointer variable equality is determined based on the equality of the
// referenced values (as opposed to the memory addresses). Function equality
@@ -166,7 +166,7 @@ func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...i
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
-// assert.EqualError(t, err, expectedErrorString)
+// require.EqualError(t, err, expectedErrorString)
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -181,7 +181,7 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
-// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
+// require.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -200,8 +200,8 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
// Exported int
// notExported int
// }
-// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
-// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
+// require.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true
+// require.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false
func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -220,8 +220,8 @@ func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, m
// Exported int
// notExported int
// }
-// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
-// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
+// require.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true
+// require.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false
func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -232,10 +232,10 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{},
t.FailNow()
}
-// EqualValues asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValues asserts that two objects are equal or convertible to the larger
+// type and equal.
//
-// assert.EqualValues(t, uint32(123), int32(123))
+// require.EqualValues(t, uint32(123), int32(123))
func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -246,10 +246,10 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg
t.FailNow()
}
-// EqualValuesf asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValuesf asserts that two objects are equal or convertible to the larger
+// type and equal.
//
-// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
+// require.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -262,7 +262,7 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri
// Equalf asserts that two objects are equal.
//
-// assert.Equalf(t, 123, 123, "error message %s", "formatted")
+// require.Equalf(t, 123, 123, "error message %s", "formatted")
//
// Pointer variable equality is determined based on the equality of the
// referenced values (as opposed to the memory addresses). Function equality
@@ -280,8 +280,8 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
// Error asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
-// if assert.Error(t, err) {
-// assert.Equal(t, expectedError, err)
+// if require.Error(t, err) {
+// require.Equal(t, expectedError, err)
// }
func Error(t TestingT, err error, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -321,7 +321,7 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int
// and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
-// assert.ErrorContains(t, err, expectedErrorSubString)
+// require.ErrorContains(t, err, expectedErrorSubString)
func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -336,7 +336,7 @@ func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...in
// and that the error contains the specified substring.
//
// actualObj, err := SomeFunction()
-// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
+// require.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -374,8 +374,8 @@ func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface
// Errorf asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
-// if assert.Errorf(t, err, "error message %s", "formatted") {
-// assert.Equal(t, expectedErrorf, err)
+// if require.Errorf(t, err, "error message %s", "formatted") {
+// require.Equal(t, expectedErrorf, err)
// }
func Errorf(t TestingT, err error, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -390,7 +390,7 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) {
// Eventually asserts that given condition will be met in waitFor time,
// periodically checking target function each tick.
//
-// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
+// require.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -415,10 +415,10 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
// time.Sleep(8*time.Second)
// externalValue = true
// }()
-// assert.EventuallyWithT(t, func(c *assert.CollectT) {
+// require.EventuallyWithT(t, func(c *require.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
-// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// require.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -443,10 +443,10 @@ func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitF
// time.Sleep(8*time.Second)
// externalValue = true
// }()
-// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") {
+// require.EventuallyWithTf(t, func(c *require.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
-// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// require.True(c, externalValue, "expected 'externalValue' to be true")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -460,7 +460,7 @@ func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), wait
// Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick.
//
-// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+// require.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -473,7 +473,7 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
// Exactly asserts that two objects are equal in value and type.
//
-// assert.Exactly(t, int32(123), int64(123))
+// require.Exactly(t, int32(123), int64(123))
func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -486,7 +486,7 @@ func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ..
// Exactlyf asserts that two objects are equal in value and type.
//
-// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
+// require.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -543,7 +543,7 @@ func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) {
// False asserts that the specified value is false.
//
-// assert.False(t, myBool)
+// require.False(t, myBool)
func False(t TestingT, value bool, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -556,7 +556,7 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) {
// Falsef asserts that the specified value is false.
//
-// assert.Falsef(t, myBool, "error message %s", "formatted")
+// require.Falsef(t, myBool, "error message %s", "formatted")
func Falsef(t TestingT, value bool, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -593,9 +593,9 @@ func FileExistsf(t TestingT, path string, msg string, args ...interface{}) {
// Greater asserts that the first element is greater than the second
//
-// assert.Greater(t, 2, 1)
-// assert.Greater(t, float64(2), float64(1))
-// assert.Greater(t, "b", "a")
+// require.Greater(t, 2, 1)
+// require.Greater(t, float64(2), float64(1))
+// require.Greater(t, "b", "a")
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -608,10 +608,10 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
// GreaterOrEqual asserts that the first element is greater than or equal to the second
//
-// assert.GreaterOrEqual(t, 2, 1)
-// assert.GreaterOrEqual(t, 2, 2)
-// assert.GreaterOrEqual(t, "b", "a")
-// assert.GreaterOrEqual(t, "b", "b")
+// require.GreaterOrEqual(t, 2, 1)
+// require.GreaterOrEqual(t, 2, 2)
+// require.GreaterOrEqual(t, "b", "a")
+// require.GreaterOrEqual(t, "b", "b")
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -624,10 +624,10 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
// GreaterOrEqualf asserts that the first element is greater than or equal to the second
//
-// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
-// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
-// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
-// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
+// require.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
+// require.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
+// require.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
+// require.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -640,9 +640,9 @@ func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, arg
// Greaterf asserts that the first element is greater than the second
//
-// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
-// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
-// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
+// require.Greaterf(t, 2, 1, "error message %s", "formatted")
+// require.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
+// require.Greaterf(t, "b", "a", "error message %s", "formatted")
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -656,7 +656,7 @@ func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...in
// HTTPBodyContains asserts that a specified handler returns a
// body that contains a string.
//
-// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+// require.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
@@ -672,7 +672,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url s
// HTTPBodyContainsf asserts that a specified handler returns a
// body that contains a string.
//
-// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+// require.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
@@ -688,7 +688,7 @@ func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url
// HTTPBodyNotContains asserts that a specified handler returns a
// body that does not contain a string.
//
-// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
+// require.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) {
@@ -704,7 +704,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, ur
// HTTPBodyNotContainsf asserts that a specified handler returns a
// body that does not contain a string.
//
-// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+// require.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) {
@@ -719,7 +719,7 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u
// HTTPError asserts that a specified handler returns an error status code.
//
-// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+// require.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
@@ -734,7 +734,7 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string,
// HTTPErrorf asserts that a specified handler returns an error status code.
//
-// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+// require.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
@@ -749,7 +749,7 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string,
// HTTPRedirect asserts that a specified handler returns a redirect status code.
//
-// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+// require.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
@@ -764,7 +764,7 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url strin
// HTTPRedirectf asserts that a specified handler returns a redirect status code.
//
-// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+// require.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
@@ -779,7 +779,7 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
// HTTPStatusCode asserts that a specified handler returns a specified status code.
//
-// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
+// require.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
@@ -794,7 +794,7 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url str
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
//
-// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
+// require.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
@@ -809,7 +809,7 @@ func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url st
// HTTPSuccess asserts that a specified handler returns a success status code.
//
-// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
+// require.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) {
@@ -824,7 +824,7 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string
// HTTPSuccessf asserts that a specified handler returns a success status code.
//
-// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+// require.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
@@ -839,7 +839,7 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin
// Implements asserts that an object is implemented by the specified interface.
//
-// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
+// require.Implements(t, (*MyInterface)(nil), new(MyObject))
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -852,7 +852,7 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
// Implementsf asserts that an object is implemented by the specified interface.
//
-// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+// require.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -865,7 +865,7 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms
// InDelta asserts that the two numerals are within delta of each other.
//
-// assert.InDelta(t, math.Pi, 22/7.0, 0.01)
+// require.InDelta(t, math.Pi, 22/7.0, 0.01)
func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -922,7 +922,7 @@ func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta f
// InDeltaf asserts that the two numerals are within delta of each other.
//
-// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
+// require.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -979,9 +979,9 @@ func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon fl
// IsDecreasing asserts that the collection is decreasing
//
-// assert.IsDecreasing(t, []int{2, 1, 0})
-// assert.IsDecreasing(t, []float{2, 1})
-// assert.IsDecreasing(t, []string{"b", "a"})
+// require.IsDecreasing(t, []int{2, 1, 0})
+// require.IsDecreasing(t, []float{2, 1})
+// require.IsDecreasing(t, []string{"b", "a"})
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -994,9 +994,9 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
// IsDecreasingf asserts that the collection is decreasing
//
-// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
-// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
-// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+// require.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted")
+// require.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// require.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1009,9 +1009,9 @@ func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface
// IsIncreasing asserts that the collection is increasing
//
-// assert.IsIncreasing(t, []int{1, 2, 3})
-// assert.IsIncreasing(t, []float{1, 2})
-// assert.IsIncreasing(t, []string{"a", "b"})
+// require.IsIncreasing(t, []int{1, 2, 3})
+// require.IsIncreasing(t, []float{1, 2})
+// require.IsIncreasing(t, []string{"a", "b"})
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1024,9 +1024,9 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
// IsIncreasingf asserts that the collection is increasing
//
-// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
-// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
-// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+// require.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted")
+// require.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// require.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1039,9 +1039,9 @@ func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface
// IsNonDecreasing asserts that the collection is not decreasing
//
-// assert.IsNonDecreasing(t, []int{1, 1, 2})
-// assert.IsNonDecreasing(t, []float{1, 2})
-// assert.IsNonDecreasing(t, []string{"a", "b"})
+// require.IsNonDecreasing(t, []int{1, 1, 2})
+// require.IsNonDecreasing(t, []float{1, 2})
+// require.IsNonDecreasing(t, []string{"a", "b"})
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1054,9 +1054,9 @@ func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{})
// IsNonDecreasingf asserts that the collection is not decreasing
//
-// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
-// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
-// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
+// require.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted")
+// require.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted")
+// require.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted")
func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1069,9 +1069,9 @@ func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interf
// IsNonIncreasing asserts that the collection is not increasing
//
-// assert.IsNonIncreasing(t, []int{2, 1, 1})
-// assert.IsNonIncreasing(t, []float{2, 1})
-// assert.IsNonIncreasing(t, []string{"b", "a"})
+// require.IsNonIncreasing(t, []int{2, 1, 1})
+// require.IsNonIncreasing(t, []float{2, 1})
+// require.IsNonIncreasing(t, []string{"b", "a"})
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1084,9 +1084,9 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{})
// IsNonIncreasingf asserts that the collection is not increasing
//
-// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
-// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
-// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
+// require.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted")
+// require.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted")
+// require.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted")
func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1121,7 +1121,7 @@ func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg strin
// JSONEq asserts that two JSON strings are equivalent.
//
-// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+// require.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1134,7 +1134,7 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{
// JSONEqf asserts that two JSON strings are equivalent.
//
-// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+// require.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1148,7 +1148,7 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
// Len asserts that the specified object has specific length.
// Len also fails if the object has a type that len() not accept.
//
-// assert.Len(t, mySlice, 3)
+// require.Len(t, mySlice, 3)
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1162,7 +1162,7 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
// Lenf asserts that the specified object has specific length.
// Lenf also fails if the object has a type that len() not accept.
//
-// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
+// require.Lenf(t, mySlice, 3, "error message %s", "formatted")
func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1175,9 +1175,9 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf
// Less asserts that the first element is less than the second
//
-// assert.Less(t, 1, 2)
-// assert.Less(t, float64(1), float64(2))
-// assert.Less(t, "a", "b")
+// require.Less(t, 1, 2)
+// require.Less(t, float64(1), float64(2))
+// require.Less(t, "a", "b")
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1190,10 +1190,10 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
// LessOrEqual asserts that the first element is less than or equal to the second
//
-// assert.LessOrEqual(t, 1, 2)
-// assert.LessOrEqual(t, 2, 2)
-// assert.LessOrEqual(t, "a", "b")
-// assert.LessOrEqual(t, "b", "b")
+// require.LessOrEqual(t, 1, 2)
+// require.LessOrEqual(t, 2, 2)
+// require.LessOrEqual(t, "a", "b")
+// require.LessOrEqual(t, "b", "b")
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1206,10 +1206,10 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
// LessOrEqualf asserts that the first element is less than or equal to the second
//
-// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
-// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
-// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
-// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
+// require.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
+// require.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
+// require.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
+// require.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1222,9 +1222,9 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args .
// Lessf asserts that the first element is less than the second
//
-// assert.Lessf(t, 1, 2, "error message %s", "formatted")
-// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
-// assert.Lessf(t, "a", "b", "error message %s", "formatted")
+// require.Lessf(t, 1, 2, "error message %s", "formatted")
+// require.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
+// require.Lessf(t, "a", "b", "error message %s", "formatted")
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1237,8 +1237,8 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter
// Negative asserts that the specified element is negative
//
-// assert.Negative(t, -1)
-// assert.Negative(t, -1.23)
+// require.Negative(t, -1)
+// require.Negative(t, -1.23)
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1251,8 +1251,8 @@ func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) {
// Negativef asserts that the specified element is negative
//
-// assert.Negativef(t, -1, "error message %s", "formatted")
-// assert.Negativef(t, -1.23, "error message %s", "formatted")
+// require.Negativef(t, -1, "error message %s", "formatted")
+// require.Negativef(t, -1.23, "error message %s", "formatted")
func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1266,7 +1266,7 @@ func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) {
// Never asserts that the given condition doesn't satisfy in waitFor time,
// periodically checking the target function each tick.
//
-// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond)
+// require.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond)
func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1280,7 +1280,7 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D
// Neverf asserts that the given condition doesn't satisfy in waitFor time,
// periodically checking the target function each tick.
//
-// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+// require.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1293,7 +1293,7 @@ func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.
// Nil asserts that the specified object is nil.
//
-// assert.Nil(t, err)
+// require.Nil(t, err)
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1306,7 +1306,7 @@ func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
// Nilf asserts that the specified object is nil.
//
-// assert.Nilf(t, err, "error message %s", "formatted")
+// require.Nilf(t, err, "error message %s", "formatted")
func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1344,8 +1344,8 @@ func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) {
// NoError asserts that a function returned no error (i.e. `nil`).
//
// actualObj, err := SomeFunction()
-// if assert.NoError(t, err) {
-// assert.Equal(t, expectedObj, actualObj)
+// if require.NoError(t, err) {
+// require.Equal(t, expectedObj, actualObj)
// }
func NoError(t TestingT, err error, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -1360,8 +1360,8 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) {
// NoErrorf asserts that a function returned no error (i.e. `nil`).
//
// actualObj, err := SomeFunction()
-// if assert.NoErrorf(t, err, "error message %s", "formatted") {
-// assert.Equal(t, expectedObj, actualObj)
+// if require.NoErrorf(t, err, "error message %s", "formatted") {
+// require.Equal(t, expectedObj, actualObj)
// }
func NoErrorf(t TestingT, err error, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -1400,9 +1400,9 @@ func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) {
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
-// assert.NotContains(t, "Hello World", "Earth")
-// assert.NotContains(t, ["Hello", "World"], "Earth")
-// assert.NotContains(t, {"Hello": "World"}, "Earth")
+// require.NotContains(t, "Hello World", "Earth")
+// require.NotContains(t, ["Hello", "World"], "Earth")
+// require.NotContains(t, {"Hello": "World"}, "Earth")
func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1416,9 +1416,9 @@ func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...
// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
-// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
-// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
-// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
+// require.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
+// require.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
+// require.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1429,11 +1429,51 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
t.FailNow()
}
+// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// require.NotElementsMatch(t, [1, 1, 2, 3], [1, 1, 2, 3]) -> false
+//
+// require.NotElementsMatch(t, [1, 1, 2, 3], [1, 2, 3]) -> true
+//
+// require.NotElementsMatch(t, [1, 2, 3], [1, 2, 4]) -> true
+func NotElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotElementsMatch(t, listA, listB, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// require.NotElementsMatchf(t, [1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
+//
+// require.NotElementsMatchf(t, [1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
+//
+// require.NotElementsMatchf(t, [1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
+func NotElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotElementsMatchf(t, listA, listB, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
-// if assert.NotEmpty(t, obj) {
-// assert.Equal(t, "two", obj[1])
+// if require.NotEmpty(t, obj) {
+// require.Equal(t, "two", obj[1])
// }
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -1448,8 +1488,8 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
-// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
-// assert.Equal(t, "two", obj[1])
+// if require.NotEmptyf(t, obj, "error message %s", "formatted") {
+// require.Equal(t, "two", obj[1])
// }
func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -1463,7 +1503,7 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{})
// NotEqual asserts that the specified values are NOT equal.
//
-// assert.NotEqual(t, obj1, obj2)
+// require.NotEqual(t, obj1, obj2)
//
// Pointer variable equality is determined based on the equality of the
// referenced values (as opposed to the memory addresses).
@@ -1479,7 +1519,7 @@ func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs .
// NotEqualValues asserts that two objects are not equal even when converted to the same type
//
-// assert.NotEqualValues(t, obj1, obj2)
+// require.NotEqualValues(t, obj1, obj2)
func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1492,7 +1532,7 @@ func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAnd
// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
//
-// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
+// require.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1505,7 +1545,7 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s
// NotEqualf asserts that the specified values are NOT equal.
//
-// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
+// require.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
//
// Pointer variable equality is determined based on the equality of the
// referenced values (as opposed to the memory addresses).
@@ -1519,7 +1559,31 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string,
t.FailNow()
}
-// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// NotErrorAs asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotErrorAs(t, err, target, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotErrorAsf asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func NotErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotErrorAsf(t, err, target, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotErrorIs asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -1531,7 +1595,7 @@ func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{})
t.FailNow()
}
-// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// NotErrorIsf asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
@@ -1545,7 +1609,7 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
// NotImplements asserts that an object does not implement the specified interface.
//
-// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject))
+// require.NotImplements(t, (*MyInterface)(nil), new(MyObject))
func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1558,7 +1622,7 @@ func NotImplements(t TestingT, interfaceObject interface{}, object interface{},
// NotImplementsf asserts that an object does not implement the specified interface.
//
-// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
+// require.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1571,7 +1635,7 @@ func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{},
// NotNil asserts that the specified object is not nil.
//
-// assert.NotNil(t, err)
+// require.NotNil(t, err)
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1584,7 +1648,7 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
// NotNilf asserts that the specified object is not nil.
//
-// assert.NotNilf(t, err, "error message %s", "formatted")
+// require.NotNilf(t, err, "error message %s", "formatted")
func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1597,7 +1661,7 @@ func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) {
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
//
-// assert.NotPanics(t, func(){ RemainCalm() })
+// require.NotPanics(t, func(){ RemainCalm() })
func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1610,7 +1674,7 @@ func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
//
-// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
+// require.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1623,8 +1687,8 @@ func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interfac
// NotRegexp asserts that a specified regexp does not match a string.
//
-// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
-// assert.NotRegexp(t, "^start", "it's not starting")
+// require.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// require.NotRegexp(t, "^start", "it's not starting")
func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1637,8 +1701,8 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
// NotRegexpf asserts that a specified regexp does not match a string.
//
-// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
-// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
+// require.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
+// require.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1651,7 +1715,7 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ..
// NotSame asserts that two pointers do not reference the same object.
//
-// assert.NotSame(t, ptr1, ptr2)
+// require.NotSame(t, ptr1, ptr2)
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
@@ -1667,7 +1731,7 @@ func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs ..
// NotSamef asserts that two pointers do not reference the same object.
//
-// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
+// require.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
@@ -1685,8 +1749,8 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
// contain all elements given in the specified subset list(array, slice...) or
// map.
//
-// assert.NotSubset(t, [1, 3, 4], [1, 2])
-// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
+// require.NotSubset(t, [1, 3, 4], [1, 2])
+// require.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1701,8 +1765,8 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i
// contain all elements given in the specified subset list(array, slice...) or
// map.
//
-// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
-// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
+// require.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
+// require.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1737,7 +1801,7 @@ func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) {
// Panics asserts that the code inside the specified PanicTestFunc panics.
//
-// assert.Panics(t, func(){ GoCrazy() })
+// require.Panics(t, func(){ GoCrazy() })
func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1752,7 +1816,7 @@ func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
// panics, and that the recovered panic value is an error that satisfies the
// EqualError comparison.
//
-// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() })
+// require.PanicsWithError(t, "crazy error", func(){ GoCrazy() })
func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1767,7 +1831,7 @@ func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAn
// panics, and that the recovered panic value is an error that satisfies the
// EqualError comparison.
//
-// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+// require.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1781,7 +1845,7 @@ func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg
// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
// the recovered panic value equals the expected panic value.
//
-// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
+// require.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1795,7 +1859,7 @@ func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, m
// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
// the recovered panic value equals the expected panic value.
//
-// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+// require.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1808,7 +1872,7 @@ func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc,
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
//
-// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
+// require.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1821,8 +1885,8 @@ func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}
// Positive asserts that the specified element is positive
//
-// assert.Positive(t, 1)
-// assert.Positive(t, 1.23)
+// require.Positive(t, 1)
+// require.Positive(t, 1.23)
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1835,8 +1899,8 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) {
// Positivef asserts that the specified element is positive
//
-// assert.Positivef(t, 1, "error message %s", "formatted")
-// assert.Positivef(t, 1.23, "error message %s", "formatted")
+// require.Positivef(t, 1, "error message %s", "formatted")
+// require.Positivef(t, 1.23, "error message %s", "formatted")
func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1849,8 +1913,8 @@ func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) {
// Regexp asserts that a specified regexp matches a string.
//
-// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
-// assert.Regexp(t, "start...$", "it's not starting")
+// require.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// require.Regexp(t, "start...$", "it's not starting")
func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1863,8 +1927,8 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface
// Regexpf asserts that a specified regexp matches a string.
//
-// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
-// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
+// require.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
+// require.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1877,7 +1941,7 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in
// Same asserts that two pointers reference the same object.
//
-// assert.Same(t, ptr1, ptr2)
+// require.Same(t, ptr1, ptr2)
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
@@ -1893,7 +1957,7 @@ func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...in
// Samef asserts that two pointers reference the same object.
//
-// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
+// require.Samef(t, ptr1, ptr2, "error message %s", "formatted")
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
@@ -1910,8 +1974,8 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
// Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
//
-// assert.Subset(t, [1, 2, 3], [1, 2])
-// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1})
+// require.Subset(t, [1, 2, 3], [1, 2])
+// require.Subset(t, {"x": 1, "y": 2}, {"x": 1})
func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1925,8 +1989,8 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte
// Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset list(array, slice...) or map.
//
-// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
-// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
+// require.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
+// require.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1939,7 +2003,7 @@ func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args
// True asserts that the specified value is true.
//
-// assert.True(t, myBool)
+// require.True(t, myBool)
func True(t TestingT, value bool, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1952,7 +2016,7 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) {
// Truef asserts that the specified value is true.
//
-// assert.Truef(t, myBool, "error message %s", "formatted")
+// require.Truef(t, myBool, "error message %s", "formatted")
func Truef(t TestingT, value bool, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1965,7 +2029,7 @@ func Truef(t TestingT, value bool, msg string, args ...interface{}) {
// WithinDuration asserts that the two times are within duration delta of each other.
//
-// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
+// require.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1978,7 +2042,7 @@ func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time
// WithinDurationf asserts that the two times are within duration delta of each other.
//
-// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+// require.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1991,7 +2055,7 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
// WithinRange asserts that a time is within a time range (inclusive).
//
-// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
+// require.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -2004,7 +2068,7 @@ func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, m
// WithinRangef asserts that a time is within a time range (inclusive).
//
-// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
+// require.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
diff --git a/vendor/github.com/stretchr/testify/require/require.go.tmpl b/vendor/github.com/stretchr/testify/require/require.go.tmpl
index 55e42dde..8b328368 100644
--- a/vendor/github.com/stretchr/testify/require/require.go.tmpl
+++ b/vendor/github.com/stretchr/testify/require/require.go.tmpl
@@ -1,4 +1,4 @@
-{{.Comment}}
+{{ replace .Comment "assert." "require."}}
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
if h, ok := t.(tHelper); ok { h.Helper() }
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go
index eee8310a..1bd87304 100644
--- a/vendor/github.com/stretchr/testify/require/require_forward.go
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go
@@ -187,8 +187,8 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface
EqualExportedValuesf(a.t, expected, actual, msg, args...)
}
-// EqualValues asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValues asserts that two objects are equal or convertible to the larger
+// type and equal.
//
// a.EqualValues(uint32(123), int32(123))
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
@@ -198,8 +198,8 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
EqualValues(a.t, expected, actual, msgAndArgs...)
}
-// EqualValuesf asserts that two objects are equal or convertible to the same types
-// and equal.
+// EqualValuesf asserts that two objects are equal or convertible to the larger
+// type and equal.
//
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
@@ -337,7 +337,7 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti
// a.EventuallyWithT(func(c *assert.CollectT) {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -362,7 +362,7 @@ func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), w
// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") {
// // add assertions as needed; any assertion failure will fail the current tick
// assert.True(c, externalValue, "expected 'externalValue' to be true")
-// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false")
+// }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false")
func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -1129,6 +1129,40 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
NotContainsf(a.t, s, contains, msg, args...)
}
+// NotElementsMatch asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// a.NotElementsMatch([1, 1, 2, 3], [1, 1, 2, 3]) -> false
+//
+// a.NotElementsMatch([1, 1, 2, 3], [1, 2, 3]) -> true
+//
+// a.NotElementsMatch([1, 2, 3], [1, 2, 4]) -> true
+func (a *Assertions) NotElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotElementsMatch(a.t, listA, listB, msgAndArgs...)
+}
+
+// NotElementsMatchf asserts that the specified listA(array, slice...) is NOT equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should not match.
+// This is an inverse of ElementsMatch.
+//
+// a.NotElementsMatchf([1, 1, 2, 3], [1, 1, 2, 3], "error message %s", "formatted") -> false
+//
+// a.NotElementsMatchf([1, 1, 2, 3], [1, 2, 3], "error message %s", "formatted") -> true
+//
+// a.NotElementsMatchf([1, 2, 3], [1, 2, 4], "error message %s", "formatted") -> true
+func (a *Assertions) NotElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotElementsMatchf(a.t, listA, listB, msg, args...)
+}
+
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
// a slice or a channel with len == 0.
//
@@ -1201,7 +1235,25 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
NotEqualf(a.t, expected, actual, msg, args...)
}
-// NotErrorIs asserts that at none of the errors in err's chain matches target.
+// NotErrorAs asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotErrorAs(a.t, err, target, msgAndArgs...)
+}
+
+// NotErrorAsf asserts that none of the errors in err's chain matches target,
+// but if so, sets target to that error value.
+func (a *Assertions) NotErrorAsf(err error, target interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotErrorAsf(a.t, err, target, msg, args...)
+}
+
+// NotErrorIs asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
@@ -1210,7 +1262,7 @@ func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface
NotErrorIs(a.t, err, target, msgAndArgs...)
}
-// NotErrorIsf asserts that at none of the errors in err's chain matches target.
+// NotErrorIsf asserts that none of the errors in err's chain matches target.
// This is a wrapper for errors.Is.
func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go
index 91772dfe..6b7ce929 100644
--- a/vendor/github.com/stretchr/testify/require/requirements.go
+++ b/vendor/github.com/stretchr/testify/require/requirements.go
@@ -6,7 +6,7 @@ type TestingT interface {
FailNow()
}
-type tHelper interface {
+type tHelper = interface {
Helper()
}
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
index db42e667..c709b728 100644
--- a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (!arm64 && !s390x && !ppc64le) || !gc || purego
+//go:build (!arm64 && !s390x && !ppc64 && !ppc64le) || !gc || purego
package chacha20
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go
similarity index 89%
rename from vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
rename to vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go
index 3a4287f9..bd183d9b 100644
--- a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build gc && !purego
+//go:build gc && !purego && (ppc64 || ppc64le)
package chacha20
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s
similarity index 76%
rename from vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
rename to vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s
index c672ccf6..a660b411 100644
--- a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s
@@ -19,7 +19,7 @@
// The differences in this and the original implementation are
// due to the calling conventions and initialization of constants.
-//go:build gc && !purego
+//go:build gc && !purego && (ppc64 || ppc64le)
#include "textflag.h"
@@ -36,32 +36,68 @@
// for VPERMXOR
#define MASK R18
-DATA consts<>+0x00(SB)/8, $0x3320646e61707865
-DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
-DATA consts<>+0x10(SB)/8, $0x0000000000000001
-DATA consts<>+0x18(SB)/8, $0x0000000000000000
-DATA consts<>+0x20(SB)/8, $0x0000000000000004
-DATA consts<>+0x28(SB)/8, $0x0000000000000000
-DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d
-DATA consts<>+0x38(SB)/8, $0x0203000106070405
-DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c
-DATA consts<>+0x48(SB)/8, $0x0102030005060704
-DATA consts<>+0x50(SB)/8, $0x6170786561707865
-DATA consts<>+0x58(SB)/8, $0x6170786561707865
-DATA consts<>+0x60(SB)/8, $0x3320646e3320646e
-DATA consts<>+0x68(SB)/8, $0x3320646e3320646e
-DATA consts<>+0x70(SB)/8, $0x79622d3279622d32
-DATA consts<>+0x78(SB)/8, $0x79622d3279622d32
-DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
-DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
-DATA consts<>+0x90(SB)/8, $0x0000000100000000
-DATA consts<>+0x98(SB)/8, $0x0000000300000002
-DATA consts<>+0xa0(SB)/8, $0x5566774411223300
-DATA consts<>+0xa8(SB)/8, $0xddeeffcc99aabb88
-DATA consts<>+0xb0(SB)/8, $0x6677445522330011
-DATA consts<>+0xb8(SB)/8, $0xeeffccddaabb8899
+DATA consts<>+0x00(SB)/4, $0x61707865
+DATA consts<>+0x04(SB)/4, $0x3320646e
+DATA consts<>+0x08(SB)/4, $0x79622d32
+DATA consts<>+0x0c(SB)/4, $0x6b206574
+DATA consts<>+0x10(SB)/4, $0x00000001
+DATA consts<>+0x14(SB)/4, $0x00000000
+DATA consts<>+0x18(SB)/4, $0x00000000
+DATA consts<>+0x1c(SB)/4, $0x00000000
+DATA consts<>+0x20(SB)/4, $0x00000004
+DATA consts<>+0x24(SB)/4, $0x00000000
+DATA consts<>+0x28(SB)/4, $0x00000000
+DATA consts<>+0x2c(SB)/4, $0x00000000
+DATA consts<>+0x30(SB)/4, $0x0e0f0c0d
+DATA consts<>+0x34(SB)/4, $0x0a0b0809
+DATA consts<>+0x38(SB)/4, $0x06070405
+DATA consts<>+0x3c(SB)/4, $0x02030001
+DATA consts<>+0x40(SB)/4, $0x0d0e0f0c
+DATA consts<>+0x44(SB)/4, $0x090a0b08
+DATA consts<>+0x48(SB)/4, $0x05060704
+DATA consts<>+0x4c(SB)/4, $0x01020300
+DATA consts<>+0x50(SB)/4, $0x61707865
+DATA consts<>+0x54(SB)/4, $0x61707865
+DATA consts<>+0x58(SB)/4, $0x61707865
+DATA consts<>+0x5c(SB)/4, $0x61707865
+DATA consts<>+0x60(SB)/4, $0x3320646e
+DATA consts<>+0x64(SB)/4, $0x3320646e
+DATA consts<>+0x68(SB)/4, $0x3320646e
+DATA consts<>+0x6c(SB)/4, $0x3320646e
+DATA consts<>+0x70(SB)/4, $0x79622d32
+DATA consts<>+0x74(SB)/4, $0x79622d32
+DATA consts<>+0x78(SB)/4, $0x79622d32
+DATA consts<>+0x7c(SB)/4, $0x79622d32
+DATA consts<>+0x80(SB)/4, $0x6b206574
+DATA consts<>+0x84(SB)/4, $0x6b206574
+DATA consts<>+0x88(SB)/4, $0x6b206574
+DATA consts<>+0x8c(SB)/4, $0x6b206574
+DATA consts<>+0x90(SB)/4, $0x00000000
+DATA consts<>+0x94(SB)/4, $0x00000001
+DATA consts<>+0x98(SB)/4, $0x00000002
+DATA consts<>+0x9c(SB)/4, $0x00000003
+DATA consts<>+0xa0(SB)/4, $0x11223300
+DATA consts<>+0xa4(SB)/4, $0x55667744
+DATA consts<>+0xa8(SB)/4, $0x99aabb88
+DATA consts<>+0xac(SB)/4, $0xddeeffcc
+DATA consts<>+0xb0(SB)/4, $0x22330011
+DATA consts<>+0xb4(SB)/4, $0x66774455
+DATA consts<>+0xb8(SB)/4, $0xaabb8899
+DATA consts<>+0xbc(SB)/4, $0xeeffccdd
GLOBL consts<>(SB), RODATA, $0xc0
+#ifdef GOARCH_ppc64
+#define BE_XXBRW_INIT() \
+ LVSL (R0)(R0), V24 \
+ VSPLTISB $3, V25 \
+ VXOR V24, V25, V24 \
+
+#define BE_XXBRW(vr) VPERM vr, vr, V24, vr
+#else
+#define BE_XXBRW_INIT()
+#define BE_XXBRW(vr)
+#endif
+
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
MOVD out+0(FP), OUT
@@ -94,6 +130,8 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
// Clear V27
VXOR V27, V27, V27
+ BE_XXBRW_INIT()
+
// V28
LXVW4X (CONSTBASE)(R11), VS60
@@ -299,6 +337,11 @@ loop_vsx:
VADDUWM V8, V18, V8
VADDUWM V12, V19, V12
+ BE_XXBRW(V0)
+ BE_XXBRW(V4)
+ BE_XXBRW(V8)
+ BE_XXBRW(V12)
+
CMPU LEN, $64
BLT tail_vsx
@@ -327,6 +370,11 @@ loop_vsx:
VADDUWM V9, V18, V8
VADDUWM V13, V19, V12
+ BE_XXBRW(V0)
+ BE_XXBRW(V4)
+ BE_XXBRW(V8)
+ BE_XXBRW(V12)
+
CMPU LEN, $64
BLT tail_vsx
@@ -334,8 +382,8 @@ loop_vsx:
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
- VXOR V27, V0, V27
+ VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
@@ -354,6 +402,11 @@ loop_vsx:
VADDUWM V10, V18, V8
VADDUWM V14, V19, V12
+ BE_XXBRW(V0)
+ BE_XXBRW(V4)
+ BE_XXBRW(V8)
+ BE_XXBRW(V12)
+
CMPU LEN, $64
BLT tail_vsx
@@ -381,6 +434,11 @@ loop_vsx:
VADDUWM V11, V18, V8
VADDUWM V15, V19, V12
+ BE_XXBRW(V0)
+ BE_XXBRW(V4)
+ BE_XXBRW(V8)
+ BE_XXBRW(V12)
+
CMPU LEN, $64
BLT tail_vsx
@@ -408,9 +466,9 @@ loop_vsx:
done_vsx:
// Increment counter by number of 64 byte blocks
- MOVD (CNT), R14
+ MOVWZ (CNT), R14
ADD BLOCKS, R14
- MOVD R14, (CNT)
+ MOVWZ R14, (CNT)
RET
tail_vsx:
diff --git a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go
index 333da285..bd896bdc 100644
--- a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go
+++ b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego
+//go:build (!amd64 && !ppc64le && !ppc64 && !s390x) || !gc || purego
package poly1305
diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go
similarity index 95%
rename from vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go
rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go
index 4aec4874..1a1679aa 100644
--- a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go
+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build gc && !purego
+//go:build gc && !purego && (ppc64 || ppc64le)
package poly1305
diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s
similarity index 89%
rename from vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s
rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s
index b3c1699b..6899a1da 100644
--- a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s
+++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s
@@ -2,15 +2,25 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build gc && !purego
+//go:build gc && !purego && (ppc64 || ppc64le)
#include "textflag.h"
// This was ported from the amd64 implementation.
+#ifdef GOARCH_ppc64le
+#define LE_MOVD MOVD
+#define LE_MOVWZ MOVWZ
+#define LE_MOVHZ MOVHZ
+#else
+#define LE_MOVD MOVDBR
+#define LE_MOVWZ MOVWBR
+#define LE_MOVHZ MOVHBR
+#endif
+
#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \
- MOVD (msg), t0; \
- MOVD 8(msg), t1; \
+ LE_MOVD (msg)( R0), t0; \
+ LE_MOVD (msg)(R24), t1; \
MOVD $1, t2; \
ADDC t0, h0, h0; \
ADDE t1, h1, h1; \
@@ -50,10 +60,6 @@
ADDE t3, h1, h1; \
ADDZE h2
-DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
-DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
-GLOBL ·poly1305Mask<>(SB), RODATA, $16
-
// func update(state *[7]uint64, msg []byte)
TEXT ·update(SB), $0-32
MOVD state+0(FP), R3
@@ -66,6 +72,8 @@ TEXT ·update(SB), $0-32
MOVD 24(R3), R11 // r0
MOVD 32(R3), R12 // r1
+ MOVD $8, R24
+
CMP R5, $16
BLT bytes_between_0_and_15
@@ -94,7 +102,7 @@ flush_buffer:
// Greater than 8 -- load the rightmost remaining bytes in msg
// and put into R17 (h1)
- MOVD (R4)(R21), R17
+ LE_MOVD (R4)(R21), R17
MOVD $16, R22
// Find the offset to those bytes
@@ -118,7 +126,7 @@ just1:
BLT less8
// Exactly 8
- MOVD (R4), R16
+ LE_MOVD (R4), R16
CMP R17, $0
@@ -133,7 +141,7 @@ less8:
MOVD $0, R22 // shift count
CMP R5, $4
BLT less4
- MOVWZ (R4), R16
+ LE_MOVWZ (R4), R16
ADD $4, R4
ADD $-4, R5
MOVD $32, R22
@@ -141,7 +149,7 @@ less8:
less4:
CMP R5, $2
BLT less2
- MOVHZ (R4), R21
+ LE_MOVHZ (R4), R21
SLD R22, R21, R21
OR R16, R21, R16
ADD $16, R22
diff --git a/vendor/golang.org/x/crypto/sha3/doc.go b/vendor/golang.org/x/crypto/sha3/doc.go
index 7e023090..bbf391fe 100644
--- a/vendor/golang.org/x/crypto/sha3/doc.go
+++ b/vendor/golang.org/x/crypto/sha3/doc.go
@@ -5,6 +5,10 @@
// Package sha3 implements the SHA-3 fixed-output-length hash functions and
// the SHAKE variable-output-length hash functions defined by FIPS-202.
//
+// All types in this package also implement [encoding.BinaryMarshaler],
+// [encoding.BinaryAppender] and [encoding.BinaryUnmarshaler] to marshal and
+// unmarshal the internal state of the hash.
+//
// Both types of hash function use the "sponge" construction and the Keccak
// permutation. For a detailed specification see http://keccak.noekeon.org/
//
diff --git a/vendor/golang.org/x/crypto/sha3/hashes.go b/vendor/golang.org/x/crypto/sha3/hashes.go
index c544b29e..31fffbe0 100644
--- a/vendor/golang.org/x/crypto/sha3/hashes.go
+++ b/vendor/golang.org/x/crypto/sha3/hashes.go
@@ -48,33 +48,52 @@ func init() {
crypto.RegisterHash(crypto.SHA3_512, New512)
}
+const (
+ dsbyteSHA3 = 0b00000110
+ dsbyteKeccak = 0b00000001
+ dsbyteShake = 0b00011111
+ dsbyteCShake = 0b00000100
+
+ // rateK[c] is the rate in bytes for Keccak[c] where c is the capacity in
+ // bits. Given the sponge size is 1600 bits, the rate is 1600 - c bits.
+ rateK256 = (1600 - 256) / 8
+ rateK448 = (1600 - 448) / 8
+ rateK512 = (1600 - 512) / 8
+ rateK768 = (1600 - 768) / 8
+ rateK1024 = (1600 - 1024) / 8
+)
+
func new224Generic() *state {
- return &state{rate: 144, outputLen: 28, dsbyte: 0x06}
+ return &state{rate: rateK448, outputLen: 28, dsbyte: dsbyteSHA3}
}
func new256Generic() *state {
- return &state{rate: 136, outputLen: 32, dsbyte: 0x06}
+ return &state{rate: rateK512, outputLen: 32, dsbyte: dsbyteSHA3}
}
func new384Generic() *state {
- return &state{rate: 104, outputLen: 48, dsbyte: 0x06}
+ return &state{rate: rateK768, outputLen: 48, dsbyte: dsbyteSHA3}
}
func new512Generic() *state {
- return &state{rate: 72, outputLen: 64, dsbyte: 0x06}
+ return &state{rate: rateK1024, outputLen: 64, dsbyte: dsbyteSHA3}
}
// 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} }
+func NewLegacyKeccak256() hash.Hash {
+ return &state{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak}
+}
// 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} }
+func NewLegacyKeccak512() hash.Hash {
+ return &state{rate: rateK1024, outputLen: 64, dsbyte: dsbyteKeccak}
+}
// Sum224 returns the SHA3-224 digest of the data.
func Sum224(data []byte) (digest [28]byte) {
diff --git a/vendor/golang.org/x/crypto/sha3/sha3.go b/vendor/golang.org/x/crypto/sha3/sha3.go
index afedde5a..6658c444 100644
--- a/vendor/golang.org/x/crypto/sha3/sha3.go
+++ b/vendor/golang.org/x/crypto/sha3/sha3.go
@@ -4,6 +4,15 @@
package sha3
+import (
+ "crypto/subtle"
+ "encoding/binary"
+ "errors"
+ "unsafe"
+
+ "golang.org/x/sys/cpu"
+)
+
// spongeDirection indicates the direction bytes are flowing through the sponge.
type spongeDirection int
@@ -14,16 +23,13 @@ const (
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
- rate int // the number of bytes of state to use
+ a [1600 / 8]byte // main state of the hash
+
+ // a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR
+ // into before running the permutation. If squeezing, it's the remaining
+ // output to produce before running the permutation.
+ n, rate int
// 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
@@ -39,10 +45,6 @@ type state struct {
// Extendable-Output Functions (May 2014)"
dsbyte byte
- i, n int // storage[i:n] is the buffer, i is only used while squeezing
- storage [maxRate]byte
-
- // Specific to SHA-3 and SHAKE.
outputLen int // the default output size in bytes
state spongeDirection // whether the sponge is absorbing or squeezing
}
@@ -61,7 +63,7 @@ func (d *state) Reset() {
d.a[i] = 0
}
d.state = spongeAbsorbing
- d.i, d.n = 0, 0
+ d.n = 0
}
func (d *state) clone() *state {
@@ -69,22 +71,25 @@ func (d *state) clone() *state {
return &ret
}
-// permute applies the KeccakF-1600 permutation. It handles
-// any input-output buffering.
+// permute applies the KeccakF-1600 permutation.
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.storage[:d.rate])
- d.n = 0
- keccakF1600(&d.a)
- case spongeSqueezing:
- // If we're squeezing, we need to apply the permutation before
- // copying more output.
- keccakF1600(&d.a)
- d.i = 0
- copyOut(d, d.storage[:d.rate])
+ var a *[25]uint64
+ if cpu.IsBigEndian {
+ a = new([25]uint64)
+ for i := range a {
+ a[i] = binary.LittleEndian.Uint64(d.a[i*8:])
+ }
+ } else {
+ a = (*[25]uint64)(unsafe.Pointer(&d.a))
+ }
+
+ keccakF1600(a)
+ d.n = 0
+
+ if cpu.IsBigEndian {
+ for i := range a {
+ binary.LittleEndian.PutUint64(d.a[i*8:], a[i])
+ }
}
}
@@ -92,53 +97,36 @@ func (d *state) permute() {
// the multi-bitrate 10..1 padding rule, and permutes the state.
func (d *state) padAndPermute() {
// 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,
+ // at least one byte of space in the sponge 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.storage[d.n] = d.dsbyte
- d.n++
- for d.n < d.rate {
- d.storage[d.n] = 0
- d.n++
- }
+ d.a[d.n] ^= d.dsbyte
// 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.storage[d.rate-1] ^= 0x80
+ d.a[d.rate-1] ^= 0x80
// Apply the permutation
d.permute()
d.state = spongeSqueezing
- d.n = d.rate
- copyOut(d, d.storage[:d.rate])
}
// Write absorbs more data into the hash's state. It panics if any
// output has already been read.
-func (d *state) Write(p []byte) (written int, err error) {
+func (d *state) Write(p []byte) (n int, err error) {
if d.state != spongeAbsorbing {
panic("sha3: Write after Read")
}
- written = len(p)
+
+ n = len(p)
for len(p) > 0 {
- if d.n == 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 - d.n
- if todo > len(p) {
- todo = len(p)
- }
- d.n += copy(d.storage[d.n:], p[:todo])
- p = p[todo:]
-
- // If the sponge is full, apply the permutation.
- if d.n == d.rate {
- d.permute()
- }
+ x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
+ d.n += x
+ p = p[x:]
+
+ // If the sponge is full, apply the permutation.
+ if d.n == d.rate {
+ d.permute()
}
}
@@ -156,14 +144,14 @@ func (d *state) Read(out []byte) (n int, err error) {
// Now, do the squeezing.
for len(out) > 0 {
- n := copy(out, d.storage[d.i:d.n])
- d.i += n
- out = out[n:]
-
// Apply the permutation if we've squeezed the sponge dry.
- if d.i == d.rate {
+ if d.n == d.rate {
d.permute()
}
+
+ x := copy(out, d.a[d.n:d.rate])
+ d.n += x
+ out = out[x:]
}
return
@@ -183,3 +171,74 @@ func (d *state) Sum(in []byte) []byte {
dup.Read(hash)
return append(in, hash...)
}
+
+const (
+ magicSHA3 = "sha\x08"
+ magicShake = "sha\x09"
+ magicCShake = "sha\x0a"
+ magicKeccak = "sha\x0b"
+ // magic || rate || main state || n || sponge direction
+ marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
+)
+
+func (d *state) MarshalBinary() ([]byte, error) {
+ return d.AppendBinary(make([]byte, 0, marshaledSize))
+}
+
+func (d *state) AppendBinary(b []byte) ([]byte, error) {
+ switch d.dsbyte {
+ case dsbyteSHA3:
+ b = append(b, magicSHA3...)
+ case dsbyteShake:
+ b = append(b, magicShake...)
+ case dsbyteCShake:
+ b = append(b, magicCShake...)
+ case dsbyteKeccak:
+ b = append(b, magicKeccak...)
+ default:
+ panic("unknown dsbyte")
+ }
+ // rate is at most 168, and n is at most rate.
+ b = append(b, byte(d.rate))
+ b = append(b, d.a[:]...)
+ b = append(b, byte(d.n), byte(d.state))
+ return b, nil
+}
+
+func (d *state) UnmarshalBinary(b []byte) error {
+ if len(b) != marshaledSize {
+ return errors.New("sha3: invalid hash state")
+ }
+
+ magic := string(b[:len(magicSHA3)])
+ b = b[len(magicSHA3):]
+ switch {
+ case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
+ case magic == magicShake && d.dsbyte == dsbyteShake:
+ case magic == magicCShake && d.dsbyte == dsbyteCShake:
+ case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
+ default:
+ return errors.New("sha3: invalid hash state identifier")
+ }
+
+ rate := int(b[0])
+ b = b[1:]
+ if rate != d.rate {
+ return errors.New("sha3: invalid hash state function")
+ }
+
+ copy(d.a[:], b)
+ b = b[len(d.a):]
+
+ n, state := int(b[0]), spongeDirection(b[1])
+ if n > d.rate {
+ return errors.New("sha3: invalid hash state")
+ }
+ d.n = n
+ if state != spongeAbsorbing && state != spongeSqueezing {
+ return errors.New("sha3: invalid hash state")
+ }
+ d.state = state
+
+ return nil
+}
diff --git a/vendor/golang.org/x/crypto/sha3/shake.go b/vendor/golang.org/x/crypto/sha3/shake.go
index 1ea9275b..a6b3a428 100644
--- a/vendor/golang.org/x/crypto/sha3/shake.go
+++ b/vendor/golang.org/x/crypto/sha3/shake.go
@@ -16,9 +16,12 @@ package sha3
// [2] https://doi.org/10.6028/NIST.SP.800-185
import (
+ "bytes"
"encoding/binary"
+ "errors"
"hash"
"io"
+ "math/bits"
)
// ShakeHash defines the interface to hash functions that support
@@ -50,44 +53,36 @@ type cshakeState struct {
initBlock []byte
}
-// Consts for configuring initial SHA-3 state
-const (
- dsbyteShake = 0x1f
- dsbyteCShake = 0x04
- rate128 = 168
- rate256 = 136
-)
+func bytepad(data []byte, rate int) []byte {
+ out := make([]byte, 0, 9+len(data)+rate-1)
+ out = append(out, leftEncode(uint64(rate))...)
+ out = append(out, data...)
+ if padlen := rate - len(out)%rate; padlen < rate {
+ out = append(out, make([]byte, padlen)...)
+ }
+ return out
+}
-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++
+func leftEncode(x uint64) []byte {
+ // Let n be the smallest positive integer for which 2^(8n) > x.
+ n := (bits.Len64(x) + 7) / 8
+ if n == 0 {
+ n = 1
}
- // Prepend number of encoded bytes
- b[i-1] = 9 - i
- return b[i-1:]
+ // Return n || x with n as a byte and x an n bytes in big-endian order.
+ b := make([]byte, 9)
+ binary.BigEndian.PutUint64(b[1:], x)
+ b = b[9-n-1:]
+ b[0] = byte(n)
+ return b
}
func newCShake(N, S []byte, rate, outputLen int, dsbyte byte) ShakeHash {
c := cshakeState{state: &state{rate: rate, outputLen: outputLen, dsbyte: dsbyte}}
-
- // leftEncode returns max 9 bytes
- c.initBlock = make([]byte, 0, 9*2+len(N)+len(S))
- c.initBlock = append(c.initBlock, leftEncode(uint64(len(N)*8))...)
+ c.initBlock = make([]byte, 0, 9+len(N)+9+len(S)) // leftEncode returns max 9 bytes
+ 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, leftEncode(uint64(len(S))*8)...)
c.initBlock = append(c.initBlock, S...)
c.Write(bytepad(c.initBlock, c.rate))
return &c
@@ -111,6 +106,30 @@ func (c *state) Clone() ShakeHash {
return c.clone()
}
+func (c *cshakeState) MarshalBinary() ([]byte, error) {
+ return c.AppendBinary(make([]byte, 0, marshaledSize+len(c.initBlock)))
+}
+
+func (c *cshakeState) AppendBinary(b []byte) ([]byte, error) {
+ b, err := c.state.AppendBinary(b)
+ if err != nil {
+ return nil, err
+ }
+ b = append(b, c.initBlock...)
+ return b, nil
+}
+
+func (c *cshakeState) UnmarshalBinary(b []byte) error {
+ if len(b) <= marshaledSize {
+ return errors.New("sha3: invalid hash state")
+ }
+ if err := c.state.UnmarshalBinary(b[:marshaledSize]); err != nil {
+ return err
+ }
+ c.initBlock = bytes.Clone(b[marshaledSize:])
+ return nil
+}
+
// 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.
@@ -126,11 +145,11 @@ func NewShake256() ShakeHash {
}
func newShake128Generic() *state {
- return &state{rate: rate128, outputLen: 32, dsbyte: dsbyteShake}
+ return &state{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}
}
func newShake256Generic() *state {
- return &state{rate: rate256, outputLen: 64, dsbyte: dsbyteShake}
+ return &state{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}
}
// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash,
@@ -143,7 +162,7 @@ func NewCShake128(N, S []byte) ShakeHash {
if len(N) == 0 && len(S) == 0 {
return NewShake128()
}
- return newCShake(N, S, rate128, 32, dsbyteCShake)
+ return newCShake(N, S, rateK256, 32, dsbyteCShake)
}
// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash,
@@ -156,7 +175,7 @@ func NewCShake256(N, S []byte) ShakeHash {
if len(N) == 0 && len(S) == 0 {
return NewShake256()
}
- return newCShake(N, S, rate256, 64, dsbyteCShake)
+ return newCShake(N, S, rateK512, 64, dsbyteCShake)
}
// ShakeSum128 writes an arbitrary-length digest of data into hash.
diff --git a/vendor/golang.org/x/crypto/sha3/xor.go b/vendor/golang.org/x/crypto/sha3/xor.go
deleted file mode 100644
index 6ada5c95..00000000
--- a/vendor/golang.org/x/crypto/sha3/xor.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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 (
- "crypto/subtle"
- "encoding/binary"
- "unsafe"
-
- "golang.org/x/sys/cpu"
-)
-
-// xorIn xors the bytes in buf into the state.
-func xorIn(d *state, buf []byte) {
- if cpu.IsBigEndian {
- for i := 0; len(buf) >= 8; i++ {
- a := binary.LittleEndian.Uint64(buf)
- d.a[i] ^= a
- buf = buf[8:]
- }
- } else {
- ab := (*[25 * 64 / 8]byte)(unsafe.Pointer(&d.a))
- subtle.XORBytes(ab[:], ab[:], buf)
- }
-}
-
-// copyOut copies uint64s to a byte buffer.
-func copyOut(d *state, b []byte) {
- if cpu.IsBigEndian {
- for i := 0; len(b) >= 8; i++ {
- binary.LittleEndian.PutUint64(b, d.a[i])
- b = b[8:]
- }
- } else {
- ab := (*[25 * 64 / 8]byte)(unsafe.Pointer(&d.a))
- copy(b, ab[:])
- }
-}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
index b9396101..b86dde15 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -555,6 +555,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
}
gotMsgExtInfo := false
+ gotUserAuthInfoRequest := false
for {
packet, err := c.readPacket()
if err != nil {
@@ -585,6 +586,9 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
if msg.PartialSuccess {
return authPartialSuccess, msg.Methods, nil
}
+ if !gotUserAuthInfoRequest {
+ return authFailure, msg.Methods, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
+ }
return authFailure, msg.Methods, nil
case msgUserAuthSuccess:
return authSuccess, nil, nil
@@ -596,6 +600,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
if err := Unmarshal(packet, &msg); err != nil {
return authFailure, nil, err
}
+ gotUserAuthInfoRequest = true
// Manually unpack the prompt/echo pairs.
rest := msg.Prompts
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 3ca9e89e..5b5ccd96 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -149,7 +149,7 @@ func (s *ServerConfig) AddHostKey(key Signer) {
}
// cachedPubKey contains the results of querying whether a public key is
-// acceptable for a user.
+// acceptable for a user. This is a FIFO cache.
type cachedPubKey struct {
user string
pubKeyData []byte
@@ -157,7 +157,13 @@ type cachedPubKey struct {
perms *Permissions
}
-const maxCachedPubKeys = 16
+// maxCachedPubKeys is the number of cache entries we store.
+//
+// Due to consistent misuse of the PublicKeyCallback API, we have reduced this
+// to 1, such that the only key in the cache is the most recently seen one. This
+// forces the behavior that the last call to PublicKeyCallback will always be
+// with the key that is used for authentication.
+const maxCachedPubKeys = 1
// pubKeyCache caches tests for public keys. Since SSH clients
// will query whether a public key is acceptable before attempting to
@@ -179,9 +185,10 @@ func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
// add adds the given tuple to the cache.
func (c *pubKeyCache) add(candidate cachedPubKey) {
- if len(c.keys) < maxCachedPubKeys {
- c.keys = append(c.keys, candidate)
+ if len(c.keys) >= maxCachedPubKeys {
+ c.keys = c.keys[1:]
}
+ c.keys = append(c.keys, candidate)
}
// ServerConn is an authenticated SSH connection, as seen from the
@@ -510,8 +517,8 @@ userAuthLoop:
if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
return nil, err
}
-
- return nil, discMsg
+ authErrs = append(authErrs, discMsg)
+ return nil, &ServerAuthError{Errors: authErrs}
}
var userAuthReq userAuthRequestMsg
diff --git a/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s b/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s
new file mode 100644
index 00000000..ec2acfe5
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s
@@ -0,0 +1,17 @@
+// Copyright 2024 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 darwin && amd64 && gc
+
+#include "textflag.h"
+
+TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0
+ JMP libc_sysctl(SB)
+GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8
+DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB)
+
+TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0
+ JMP libc_sysctlbyname(SB)
+GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8
+DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB)
diff --git a/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go b/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go
new file mode 100644
index 00000000..b838cb9e
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go
@@ -0,0 +1,61 @@
+// Copyright 2024 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 darwin && amd64 && gc
+
+package cpu
+
+// darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl
+// call (see issue 43089). It also restricts AVX512 support for Darwin to
+// kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233).
+//
+// Background:
+// Darwin implements a special mechanism to economize on thread state when
+// AVX512 specific registers are not in use. This scheme minimizes state when
+// preempting threads that haven't yet used any AVX512 instructions, but adds
+// special requirements to check for AVX512 hardware support at runtime (e.g.
+// via sysctl call or commpage inspection). See issue 43089 and link below for
+// full background:
+// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240
+//
+// Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0
+// (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption
+// of the AVX512 mask registers (K0-K7) upon signal return. For this reason
+// AVX512 is considered unsafe to use on Darwin for kernel versions prior to
+// 21.3.0, where a fix has been confirmed. See issue 49233 for full background.
+func darwinSupportsAVX512() bool {
+ return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0)
+}
+
+// Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies
+func darwinKernelVersionCheck(major, minor, patch int) bool {
+ var release [256]byte
+ err := darwinOSRelease(&release)
+ if err != nil {
+ return false
+ }
+
+ var mmp [3]int
+ c := 0
+Loop:
+ for _, b := range release[:] {
+ switch {
+ case b >= '0' && b <= '9':
+ mmp[c] = 10*mmp[c] + int(b-'0')
+ case b == '.':
+ c++
+ if c > 2 {
+ return false
+ }
+ case b == 0:
+ break Loop
+ default:
+ return false
+ }
+ }
+ if c != 2 {
+ return false
+ }
+ return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch)
+}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
index 910728fb..32a44514 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go
@@ -6,10 +6,10 @@
package cpu
-// cpuid is implemented in cpu_x86.s for gc compiler
+// cpuid is implemented in cpu_gc_x86.s for gc compiler
// and in cpu_gccgo.c for gccgo.
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
-// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler
+// xgetbv with ecx = 0 is implemented in cpu_gc_x86.s for gc compiler
// and in cpu_gccgo.c for gccgo.
func xgetbv() (eax, edx uint32)
diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.s b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s
similarity index 94%
rename from vendor/golang.org/x/sys/cpu/cpu_x86.s
rename to vendor/golang.org/x/sys/cpu/cpu_gc_x86.s
index 7d7ba33e..ce208ce6 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_x86.s
+++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s
@@ -18,7 +18,7 @@ TEXT ·cpuid(SB), NOSPLIT, $0-24
RET
// func xgetbv() (eax, edx uint32)
-TEXT ·xgetbv(SB),NOSPLIT,$0-8
+TEXT ·xgetbv(SB), NOSPLIT, $0-8
MOVL $0, CX
XGETBV
MOVL AX, eax+0(FP)
diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go
index 99c60fe9..170d21dd 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go
@@ -23,9 +23,3 @@ func xgetbv() (eax, edx uint32) {
gccgoXgetbv(&a, &d)
return a, d
}
-
-// gccgo doesn't build on Darwin, per:
-// https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gcc.rb#L76
-func darwinSupportsAVX512() bool {
- return false
-}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go
index 08f35ea1..f1caf0f7 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go
@@ -110,7 +110,6 @@ func doinit() {
ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM)
ARM64.HasDIT = isSet(hwCap, hwcap_DIT)
-
// HWCAP2 feature bits
ARM64.HasSVE2 = isSet(hwCap2, hwcap2_SVE2)
ARM64.HasI8MM = isSet(hwCap2, hwcap2_I8MM)
diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_x86.go b/vendor/golang.org/x/sys/cpu/cpu_other_x86.go
new file mode 100644
index 00000000..a0fd7e2f
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/cpu_other_x86.go
@@ -0,0 +1,11 @@
+// Copyright 2024 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 || amd64p32 || (amd64 && (!darwin || !gc))
+
+package cpu
+
+func darwinSupportsAVX512() bool {
+ panic("only implemented for gc && amd64 && darwin")
+}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go
index c29f5e4c..600a6807 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_x86.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go
@@ -92,10 +92,8 @@ func archInit() {
osSupportsAVX = isSet(1, eax) && isSet(2, eax)
if runtime.GOOS == "darwin" {
- // Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers.
- // Since users can't rely on mask register contents, let's not advertise AVX-512 support.
- // See issue 49233.
- osSupportsAVX512 = false
+ // Darwin requires special AVX512 checks, see cpu_darwin_x86.go
+ osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512()
} else {
// Check if OPMASK and ZMM registers have OS support.
osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)
diff --git a/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go b/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go
new file mode 100644
index 00000000..4d0888b0
--- /dev/null
+++ b/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go
@@ -0,0 +1,98 @@
+// Copyright 2024 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.
+
+// Minimal copy of x/sys/unix so the cpu package can make a
+// system call on Darwin without depending on x/sys/unix.
+
+//go:build darwin && amd64 && gc
+
+package cpu
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+type _C_int int32
+
+// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419
+func darwinOSRelease(release *[256]byte) error {
+ // from x/sys/unix/zerrors_openbsd_amd64.go
+ const (
+ CTL_KERN = 0x1
+ KERN_OSRELEASE = 0x2
+ )
+
+ mib := []_C_int{CTL_KERN, KERN_OSRELEASE}
+ n := unsafe.Sizeof(*release)
+
+ return sysctl(mib, &release[0], &n, nil, 0)
+}
+
+type Errno = syscall.Errno
+
+var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes.
+
+// from x/sys/unix/zsyscall_darwin_amd64.go L791-807
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
+ var _p0 unsafe.Pointer
+ if len(mib) > 0 {
+ _p0 = unsafe.Pointer(&mib[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ if _, _, err := syscall_syscall6(
+ libc_sysctl_trampoline_addr,
+ uintptr(_p0),
+ uintptr(len(mib)),
+ uintptr(unsafe.Pointer(old)),
+ uintptr(unsafe.Pointer(oldlen)),
+ uintptr(unsafe.Pointer(new)),
+ uintptr(newlen),
+ ); err != 0 {
+ return err
+ }
+
+ return nil
+}
+
+var libc_sysctl_trampoline_addr uintptr
+
+// adapted from internal/cpu/cpu_arm64_darwin.go
+func darwinSysctlEnabled(name []byte) bool {
+ out := int32(0)
+ nout := unsafe.Sizeof(out)
+ if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil {
+ return false
+ }
+ return out > 0
+}
+
+//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
+
+var libc_sysctlbyname_trampoline_addr uintptr
+
+// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix
+func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
+ if _, _, err := syscall_syscall6(
+ libc_sysctlbyname_trampoline_addr,
+ uintptr(unsafe.Pointer(name)),
+ uintptr(unsafe.Pointer(old)),
+ uintptr(unsafe.Pointer(oldlen)),
+ uintptr(unsafe.Pointer(new)),
+ uintptr(newlen),
+ 0,
+ ); err != 0 {
+ return err
+ }
+
+ return nil
+}
+
+//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib"
+
+// Implemented in the runtime package (runtime/sys_darwin.go)
+func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+
+//go:linkname syscall_syscall6 syscall.syscall6
diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md
index 7d3c060e..6e08a76a 100644
--- a/vendor/golang.org/x/sys/unix/README.md
+++ b/vendor/golang.org/x/sys/unix/README.md
@@ -156,7 +156,7 @@ from the generated architecture-specific files listed below, and merge these
into a common file for each OS.
The merge is performed in the following steps:
-1. Construct the set of common code that is idential in all architecture-specific files.
+1. Construct the set of common code that is identical in all architecture-specific files.
2. Write this common code to the merged file.
3. Remove the common code from all architecture-specific files.
diff --git a/vendor/golang.org/x/sys/unix/ioctl_linux.go b/vendor/golang.org/x/sys/unix/ioctl_linux.go
index dbe680ea..7ca4fa12 100644
--- a/vendor/golang.org/x/sys/unix/ioctl_linux.go
+++ b/vendor/golang.org/x/sys/unix/ioctl_linux.go
@@ -58,6 +58,102 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
return &value, err
}
+// IoctlGetEthtoolTsInfo fetches ethtool timestamping and PHC
+// association for the network device specified by ifname.
+func IoctlGetEthtoolTsInfo(fd int, ifname string) (*EthtoolTsInfo, error) {
+ ifr, err := NewIfreq(ifname)
+ if err != nil {
+ return nil, err
+ }
+
+ value := EthtoolTsInfo{Cmd: ETHTOOL_GET_TS_INFO}
+ ifrd := ifr.withData(unsafe.Pointer(&value))
+
+ err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd)
+ return &value, err
+}
+
+// IoctlGetHwTstamp retrieves the hardware timestamping configuration
+// for the network device specified by ifname.
+func IoctlGetHwTstamp(fd int, ifname string) (*HwTstampConfig, error) {
+ ifr, err := NewIfreq(ifname)
+ if err != nil {
+ return nil, err
+ }
+
+ value := HwTstampConfig{}
+ ifrd := ifr.withData(unsafe.Pointer(&value))
+
+ err = ioctlIfreqData(fd, SIOCGHWTSTAMP, &ifrd)
+ return &value, err
+}
+
+// IoctlSetHwTstamp updates the hardware timestamping configuration for
+// the network device specified by ifname.
+func IoctlSetHwTstamp(fd int, ifname string, cfg *HwTstampConfig) error {
+ ifr, err := NewIfreq(ifname)
+ if err != nil {
+ return err
+ }
+ ifrd := ifr.withData(unsafe.Pointer(cfg))
+ return ioctlIfreqData(fd, SIOCSHWTSTAMP, &ifrd)
+}
+
+// FdToClockID derives the clock ID from the file descriptor number
+// - see clock_gettime(3), FD_TO_CLOCKID macros. The resulting ID is
+// suitable for system calls like ClockGettime.
+func FdToClockID(fd int) int32 { return int32((int(^fd) << 3) | 3) }
+
+// IoctlPtpClockGetcaps returns the description of a given PTP device.
+func IoctlPtpClockGetcaps(fd int) (*PtpClockCaps, error) {
+ var value PtpClockCaps
+ err := ioctlPtr(fd, PTP_CLOCK_GETCAPS2, unsafe.Pointer(&value))
+ return &value, err
+}
+
+// IoctlPtpSysOffsetPrecise returns a description of the clock
+// offset compared to the system clock.
+func IoctlPtpSysOffsetPrecise(fd int) (*PtpSysOffsetPrecise, error) {
+ var value PtpSysOffsetPrecise
+ err := ioctlPtr(fd, PTP_SYS_OFFSET_PRECISE2, unsafe.Pointer(&value))
+ return &value, err
+}
+
+// IoctlPtpSysOffsetExtended returns an extended description of the
+// clock offset compared to the system clock. The samples parameter
+// specifies the desired number of measurements.
+func IoctlPtpSysOffsetExtended(fd int, samples uint) (*PtpSysOffsetExtended, error) {
+ value := PtpSysOffsetExtended{Samples: uint32(samples)}
+ err := ioctlPtr(fd, PTP_SYS_OFFSET_EXTENDED2, unsafe.Pointer(&value))
+ return &value, err
+}
+
+// IoctlPtpPinGetfunc returns the configuration of the specified
+// I/O pin on given PTP device.
+func IoctlPtpPinGetfunc(fd int, index uint) (*PtpPinDesc, error) {
+ value := PtpPinDesc{Index: uint32(index)}
+ err := ioctlPtr(fd, PTP_PIN_GETFUNC2, unsafe.Pointer(&value))
+ return &value, err
+}
+
+// IoctlPtpPinSetfunc updates configuration of the specified PTP
+// I/O pin.
+func IoctlPtpPinSetfunc(fd int, pd *PtpPinDesc) error {
+ return ioctlPtr(fd, PTP_PIN_SETFUNC2, unsafe.Pointer(pd))
+}
+
+// IoctlPtpPeroutRequest configures the periodic output mode of the
+// PTP I/O pins.
+func IoctlPtpPeroutRequest(fd int, r *PtpPeroutRequest) error {
+ return ioctlPtr(fd, PTP_PEROUT_REQUEST2, unsafe.Pointer(r))
+}
+
+// IoctlPtpExttsRequest configures the external timestamping mode
+// of the PTP I/O pins.
+func IoctlPtpExttsRequest(fd int, r *PtpExttsRequest) error {
+ return ioctlPtr(fd, PTP_EXTTS_REQUEST2, unsafe.Pointer(r))
+}
+
// IoctlGetWatchdogInfo fetches information about a watchdog device from the
// Linux watchdog API. For more information, see:
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh
index e14b766a..6ab02b6c 100644
--- a/vendor/golang.org/x/sys/unix/mkerrors.sh
+++ b/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -158,6 +158,16 @@ includes_Linux='
#endif
#define _GNU_SOURCE
+// See the description in unix/linux/types.go
+#if defined(__ARM_EABI__) || \
+ (defined(__mips__) && (_MIPS_SIM == _ABIO32)) || \
+ (defined(__powerpc__) && (!defined(__powerpc64__)))
+# ifdef _TIME_BITS
+# undef _TIME_BITS
+# endif
+# define _TIME_BITS 32
+#endif
+
// is broken on powerpc64, as it fails to include definitions of
// these structures. We just include them copied from .
#if defined(__powerpc__)
@@ -256,6 +266,7 @@ struct ltchars {
#include
#include
#include
+#include
#include
#include
#include
@@ -527,6 +538,7 @@ ccflags="$@"
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
+ $2 ~ /^PTP_/ ||
$2 ~ /^RAW_PAYLOAD_/ ||
$2 ~ /^[US]F_/ ||
$2 ~ /^TP_STATUS_/ ||
@@ -656,7 +668,7 @@ errors=$(
signals=$(
echo '#include ' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
- grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
+ grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
sort
)
@@ -666,7 +678,7 @@ echo '#include ' | $CC -x c - -E -dM $ccflags |
sort >_error.grep
echo '#include ' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
- grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
+ grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
sort >_signal.grep
echo '// mkerrors.sh' "$@"
diff --git a/vendor/golang.org/x/sys/unix/syscall_aix.go b/vendor/golang.org/x/sys/unix/syscall_aix.go
index 67ce6cef..6f15ba1e 100644
--- a/vendor/golang.org/x/sys/unix/syscall_aix.go
+++ b/vendor/golang.org/x/sys/unix/syscall_aix.go
@@ -360,7 +360,7 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int,
var status _C_int
var r Pid_t
err = ERESTART
- // AIX wait4 may return with ERESTART errno, while the processus is still
+ // AIX wait4 may return with ERESTART errno, while the process is still
// active.
for err == ERESTART {
r, err = wait4(Pid_t(pid), &status, options, rusage)
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go
index 3f1d3d4c..230a9454 100644
--- a/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -1295,6 +1295,48 @@ func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
return &value, err
}
+// GetsockoptTCPCCVegasInfo returns algorithm specific congestion control information for a socket using the "vegas"
+// algorithm.
+//
+// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
+//
+// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
+func GetsockoptTCPCCVegasInfo(fd, level, opt int) (*TCPVegasInfo, error) {
+ var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
+ vallen := _Socklen(SizeofTCPCCInfo)
+ err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
+ out := (*TCPVegasInfo)(unsafe.Pointer(&value[0]))
+ return out, err
+}
+
+// GetsockoptTCPCCDCTCPInfo returns algorithm specific congestion control information for a socket using the "dctp"
+// algorithm.
+//
+// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
+//
+// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
+func GetsockoptTCPCCDCTCPInfo(fd, level, opt int) (*TCPDCTCPInfo, error) {
+ var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
+ vallen := _Socklen(SizeofTCPCCInfo)
+ err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
+ out := (*TCPDCTCPInfo)(unsafe.Pointer(&value[0]))
+ return out, err
+}
+
+// GetsockoptTCPCCBBRInfo returns algorithm specific congestion control information for a socket using the "bbr"
+// algorithm.
+//
+// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
+//
+// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
+func GetsockoptTCPCCBBRInfo(fd, level, opt int) (*TCPBBRInfo, error) {
+ var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
+ vallen := _Socklen(SizeofTCPCCInfo)
+ err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
+ out := (*TCPBBRInfo)(unsafe.Pointer(&value[0]))
+ return out, err
+}
+
// GetsockoptString returns the string value of the socket option opt for the
// socket associated with fd at the given socket level.
func GetsockoptString(fd, level, opt int) (string, error) {
@@ -1818,6 +1860,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys ClockAdjtime(clockid int32, buf *Timex) (state int, err error)
//sys ClockGetres(clockid int32, res *Timespec) (err error)
//sys ClockGettime(clockid int32, time *Timespec) (err error)
+//sys ClockSettime(clockid int32, time *Timespec) (err error)
//sys ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error)
//sys Close(fd int) (err error)
//sys CloseRange(first uint, last uint, flags uint) (err error)
@@ -1959,7 +2002,26 @@ func Getpgrp() (pid int) {
//sysnb Getpid() (pid int)
//sysnb Getppid() (ppid int)
//sys Getpriority(which int, who int) (prio int, err error)
-//sys Getrandom(buf []byte, flags int) (n int, err error)
+
+func Getrandom(buf []byte, flags int) (n int, err error) {
+ vdsoRet, supported := vgetrandom(buf, uint32(flags))
+ if supported {
+ if vdsoRet < 0 {
+ return 0, errnoErr(syscall.Errno(-vdsoRet))
+ }
+ return vdsoRet, nil
+ }
+ var p *byte
+ if len(buf) > 0 {
+ p = &buf[0]
+ }
+ r, _, e := Syscall(SYS_GETRANDOM, uintptr(unsafe.Pointer(p)), uintptr(len(buf)), uintptr(flags))
+ if e != 0 {
+ return 0, errnoErr(e)
+ }
+ return int(r), nil
+}
+
//sysnb Getrusage(who int, rusage *Rusage) (err error)
//sysnb Getsid(pid int) (sid int, err error)
//sysnb Gettid() (tid int)
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
index cf2ee6c7..745e5c7e 100644
--- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go
@@ -182,3 +182,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
}
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
}
+
+const SYS_FSTATAT = SYS_NEWFSTATAT
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
index 3d0e9845..dd2262a4 100644
--- a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
+++ b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go
@@ -214,3 +214,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
}
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
}
+
+const SYS_FSTATAT = SYS_NEWFSTATAT
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
index 6f5a2889..8cf3670b 100644
--- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go
@@ -187,3 +187,5 @@ func RISCVHWProbe(pairs []RISCVHWProbePairs, set *CPUSet, flags uint) (err error
}
return riscvHWProbe(pairs, setSize, set, flags)
}
+
+const SYS_FSTATAT = SYS_NEWFSTATAT
diff --git a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
index 312ae6ac..7bf5c04b 100644
--- a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
@@ -768,6 +768,15 @@ func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
+func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) {
+ xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset)
+ return unsafe.Pointer(xaddr), err
+}
+
+func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) {
+ return mapper.munmap(uintptr(addr), length)
+}
+
//sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
//sysnb Getgid() (gid int)
//sysnb Getpid() (pid int)
@@ -816,10 +825,10 @@ func Lstat(path string, stat *Stat_t) (err error) {
// for checking symlinks begins with $VERSION/ $SYSNAME/ $SYSSYMR/ $SYSSYMA/
func isSpecialPath(path []byte) (v bool) {
var special = [4][8]byte{
- [8]byte{'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'},
- [8]byte{'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'},
- [8]byte{'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'},
- [8]byte{'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}}
+ {'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'},
+ {'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'},
+ {'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'},
+ {'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}}
var i, j int
for i = 0; i < len(special); i++ {
@@ -3115,3 +3124,90 @@ func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) {
//sys Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT
//sys Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT
//sys Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT
+
+func fcntlAsIs(fd uintptr, cmd int, arg uintptr) (val int, err error) {
+ runtime.EnterSyscall()
+ r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), arg)
+ runtime.ExitSyscall()
+ val = int(r0)
+ if int64(r0) == -1 {
+ err = errnoErr2(e1, e2)
+ }
+ return
+}
+
+func Fcntl(fd uintptr, cmd int, op interface{}) (ret int, err error) {
+ switch op.(type) {
+ case *Flock_t:
+ err = FcntlFlock(fd, cmd, op.(*Flock_t))
+ if err != nil {
+ ret = -1
+ }
+ return
+ case int:
+ return FcntlInt(fd, cmd, op.(int))
+ case *F_cnvrt:
+ return fcntlAsIs(fd, cmd, uintptr(unsafe.Pointer(op.(*F_cnvrt))))
+ case unsafe.Pointer:
+ return fcntlAsIs(fd, cmd, uintptr(op.(unsafe.Pointer)))
+ default:
+ return -1, EINVAL
+ }
+ return
+}
+
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ return sendfile(outfd, infd, offset, count)
+}
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+ // TODO: use LE call instead if the call is implemented
+ originalOffset, err := Seek(infd, 0, SEEK_CUR)
+ if err != nil {
+ return -1, err
+ }
+ //start reading data from in_fd
+ if offset != nil {
+ _, err := Seek(infd, *offset, SEEK_SET)
+ if err != nil {
+ return -1, err
+ }
+ }
+
+ buf := make([]byte, count)
+ readBuf := make([]byte, 0)
+ var n int = 0
+ for i := 0; i < count; i += n {
+ n, err := Read(infd, buf)
+ if n == 0 {
+ if err != nil {
+ return -1, err
+ } else { // EOF
+ break
+ }
+ }
+ readBuf = append(readBuf, buf...)
+ buf = buf[0:0]
+ }
+
+ n2, err := Write(outfd, readBuf)
+ if err != nil {
+ return -1, err
+ }
+
+ //When sendfile() returns, this variable will be set to the
+ // offset of the byte following the last byte that was read.
+ if offset != nil {
+ *offset = *offset + int64(n)
+ // If offset is not NULL, then sendfile() does not modify the file
+ // offset of in_fd
+ _, err := Seek(infd, originalOffset, SEEK_SET)
+ if err != nil {
+ return -1, err
+ }
+ }
+ return n2, nil
+}
diff --git a/vendor/golang.org/x/sys/unix/vgetrandom_linux.go b/vendor/golang.org/x/sys/unix/vgetrandom_linux.go
new file mode 100644
index 00000000..07ac8e09
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/vgetrandom_linux.go
@@ -0,0 +1,13 @@
+// Copyright 2024 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 linux && go1.24
+
+package unix
+
+import _ "unsafe"
+
+//go:linkname vgetrandom runtime.vgetrandom
+//go:noescape
+func vgetrandom(p []byte, flags uint32) (ret int, supported bool)
diff --git a/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go b/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go
new file mode 100644
index 00000000..297e97bc
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go
@@ -0,0 +1,11 @@
+// Copyright 2024 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 !linux || !go1.24
+
+package unix
+
+func vgetrandom(p []byte, flags uint32) (ret int, supported bool) {
+ return -1, false
+}
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go
index 01a70b24..6ebc48b3 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -321,6 +321,9 @@ const (
AUDIT_INTEGRITY_STATUS = 0x70a
AUDIT_IPC = 0x517
AUDIT_IPC_SET_PERM = 0x51f
+ AUDIT_IPE_ACCESS = 0x58c
+ AUDIT_IPE_CONFIG_CHANGE = 0x58d
+ AUDIT_IPE_POLICY_LOAD = 0x58e
AUDIT_KERNEL = 0x7d0
AUDIT_KERNEL_OTHER = 0x524
AUDIT_KERN_MODULE = 0x532
@@ -489,12 +492,14 @@ const (
BPF_F_ID = 0x20
BPF_F_NETFILTER_IP_DEFRAG = 0x1
BPF_F_QUERY_EFFECTIVE = 0x1
+ BPF_F_REDIRECT_FLAGS = 0x19
BPF_F_REPLACE = 0x4
BPF_F_SLEEPABLE = 0x10
BPF_F_STRICT_ALIGNMENT = 0x1
BPF_F_TEST_REG_INVARIANTS = 0x80
BPF_F_TEST_RND_HI32 = 0x4
BPF_F_TEST_RUN_ON_CPU = 0x1
+ BPF_F_TEST_SKB_CHECKSUM_COMPLETE = 0x4
BPF_F_TEST_STATE_FREQ = 0x8
BPF_F_TEST_XDP_LIVE_FRAMES = 0x2
BPF_F_XDP_DEV_BOUND_ONLY = 0x40
@@ -1165,6 +1170,7 @@ const (
EXTA = 0xe
EXTB = 0xf
F2FS_SUPER_MAGIC = 0xf2f52010
+ FALLOC_FL_ALLOCATE_RANGE = 0x0
FALLOC_FL_COLLAPSE_RANGE = 0x8
FALLOC_FL_INSERT_RANGE = 0x20
FALLOC_FL_KEEP_SIZE = 0x1
@@ -1798,6 +1804,8 @@ const (
LANDLOCK_ACCESS_NET_BIND_TCP = 0x1
LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2
LANDLOCK_CREATE_RULESET_VERSION = 0x1
+ LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1
+ LANDLOCK_SCOPE_SIGNAL = 0x2
LINUX_REBOOT_CMD_CAD_OFF = 0x0
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
LINUX_REBOOT_CMD_HALT = 0xcdef0123
@@ -1922,6 +1930,8 @@ const (
MNT_EXPIRE = 0x4
MNT_FORCE = 0x1
MNT_ID_REQ_SIZE_VER0 = 0x18
+ MNT_ID_REQ_SIZE_VER1 = 0x20
+ MNT_NS_INFO_SIZE_VER0 = 0x10
MODULE_INIT_COMPRESSED_FILE = 0x4
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
MODULE_INIT_IGNORE_VERMAGIC = 0x2
@@ -2187,7 +2197,7 @@ const (
NFT_REG_SIZE = 0x10
NFT_REJECT_ICMPX_MAX = 0x3
NFT_RT_MAX = 0x4
- NFT_SECMARK_CTX_MAXLEN = 0x100
+ NFT_SECMARK_CTX_MAXLEN = 0x1000
NFT_SET_MAXNAMELEN = 0x100
NFT_SOCKET_MAX = 0x3
NFT_TABLE_F_MASK = 0x7
@@ -2356,9 +2366,11 @@ const (
PERF_MEM_LVLNUM_IO = 0xa
PERF_MEM_LVLNUM_L1 = 0x1
PERF_MEM_LVLNUM_L2 = 0x2
+ PERF_MEM_LVLNUM_L2_MHB = 0x5
PERF_MEM_LVLNUM_L3 = 0x3
PERF_MEM_LVLNUM_L4 = 0x4
PERF_MEM_LVLNUM_LFB = 0xc
+ PERF_MEM_LVLNUM_MSC = 0x6
PERF_MEM_LVLNUM_NA = 0xf
PERF_MEM_LVLNUM_PMEM = 0xe
PERF_MEM_LVLNUM_RAM = 0xd
@@ -2431,6 +2443,7 @@ const (
PRIO_PGRP = 0x1
PRIO_PROCESS = 0x0
PRIO_USER = 0x2
+ PROCFS_IOCTL_MAGIC = 'f'
PROC_SUPER_MAGIC = 0x9fa0
PROT_EXEC = 0x4
PROT_GROWSDOWN = 0x1000000
@@ -2620,6 +2633,28 @@ const (
PR_UNALIGN_NOPRINT = 0x1
PR_UNALIGN_SIGBUS = 0x2
PSTOREFS_MAGIC = 0x6165676c
+ PTP_CLK_MAGIC = '='
+ PTP_ENABLE_FEATURE = 0x1
+ PTP_EXTTS_EDGES = 0x6
+ PTP_EXTTS_EVENT_VALID = 0x1
+ PTP_EXTTS_V1_VALID_FLAGS = 0x7
+ PTP_EXTTS_VALID_FLAGS = 0x1f
+ PTP_EXT_OFFSET = 0x10
+ PTP_FALLING_EDGE = 0x4
+ PTP_MAX_SAMPLES = 0x19
+ PTP_PEROUT_DUTY_CYCLE = 0x2
+ PTP_PEROUT_ONE_SHOT = 0x1
+ PTP_PEROUT_PHASE = 0x4
+ PTP_PEROUT_V1_VALID_FLAGS = 0x0
+ PTP_PEROUT_VALID_FLAGS = 0x7
+ PTP_PIN_GETFUNC = 0xc0603d06
+ PTP_PIN_GETFUNC2 = 0xc0603d0f
+ PTP_RISING_EDGE = 0x2
+ PTP_STRICT_FLAGS = 0x8
+ PTP_SYS_OFFSET_EXTENDED = 0xc4c03d09
+ PTP_SYS_OFFSET_EXTENDED2 = 0xc4c03d12
+ PTP_SYS_OFFSET_PRECISE = 0xc0403d08
+ PTP_SYS_OFFSET_PRECISE2 = 0xc0403d11
PTRACE_ATTACH = 0x10
PTRACE_CONT = 0x7
PTRACE_DETACH = 0x11
@@ -2933,15 +2968,17 @@ const (
RUSAGE_SELF = 0x0
RUSAGE_THREAD = 0x1
RWF_APPEND = 0x10
+ RWF_ATOMIC = 0x40
RWF_DSYNC = 0x2
RWF_HIPRI = 0x1
RWF_NOAPPEND = 0x20
RWF_NOWAIT = 0x8
- RWF_SUPPORTED = 0x3f
+ RWF_SUPPORTED = 0x7f
RWF_SYNC = 0x4
RWF_WRITE_LIFE_NOT_SET = 0x0
SCHED_BATCH = 0x3
SCHED_DEADLINE = 0x6
+ SCHED_EXT = 0x7
SCHED_FIFO = 0x1
SCHED_FLAG_ALL = 0x7f
SCHED_FLAG_DL_OVERRUN = 0x4
@@ -3210,6 +3247,7 @@ const (
STATX_ATTR_MOUNT_ROOT = 0x2000
STATX_ATTR_NODUMP = 0x40
STATX_ATTR_VERITY = 0x100000
+ STATX_ATTR_WRITE_ATOMIC = 0x400000
STATX_BASIC_STATS = 0x7ff
STATX_BLOCKS = 0x400
STATX_BTIME = 0x800
@@ -3226,6 +3264,7 @@ const (
STATX_SUBVOL = 0x8000
STATX_TYPE = 0x1
STATX_UID = 0x8
+ STATX_WRITE_ATOMIC = 0x10000
STATX__RESERVED = 0x80000000
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
@@ -3624,6 +3663,7 @@ const (
XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000
XDP_UMEM_PGOFF_FILL_RING = 0x100000000
XDP_UMEM_REG = 0x4
+ XDP_UMEM_TX_METADATA_LEN = 0x4
XDP_UMEM_TX_SW_CSUM = 0x2
XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1
XDP_USE_NEED_WAKEUP = 0x8
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
index 684a5168..c0d45e32 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
@@ -109,6 +109,7 @@ const (
HIDIOCGRAWINFO = 0x80084803
HIDIOCGRDESC = 0x90044802
HIDIOCGRDESCSIZE = 0x80044801
+ HIDIOCREVOKE = 0x4004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -153,9 +154,14 @@ const (
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x8008b705
NS_GET_NSTYPE = 0xb703
NS_GET_OWNER_UID = 0xb704
NS_GET_PARENT = 0xb702
+ NS_GET_PID_FROM_PIDNS = 0x8004b706
+ NS_GET_PID_IN_PIDNS = 0x8004b708
+ NS_GET_TGID_FROM_PIDNS = 0x8004b707
+ NS_GET_TGID_IN_PIDNS = 0x8004b709
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
@@ -232,6 +238,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x7434
PPPIOCXFERUNIT = 0x744e
PR_SET_PTRACER_ANY = 0xffffffff
+ PTP_CLOCK_GETCAPS = 0x80503d01
+ PTP_CLOCK_GETCAPS2 = 0x80503d0a
+ PTP_ENABLE_PPS = 0x40043d04
+ PTP_ENABLE_PPS2 = 0x40043d0d
+ PTP_EXTTS_REQUEST = 0x40103d02
+ PTP_EXTTS_REQUEST2 = 0x40103d0b
+ PTP_MASK_CLEAR_ALL = 0x3d13
+ PTP_MASK_EN_SINGLE = 0x40043d14
+ PTP_PEROUT_REQUEST = 0x40383d03
+ PTP_PEROUT_REQUEST2 = 0x40383d0c
+ PTP_PIN_SETFUNC = 0x40603d07
+ PTP_PIN_SETFUNC2 = 0x40603d10
+ PTP_SYS_OFFSET = 0x43403d05
+ PTP_SYS_OFFSET2 = 0x43403d0e
PTRACE_GETFPREGS = 0xe
PTRACE_GETFPXREGS = 0x12
PTRACE_GET_THREAD_AREA = 0x19
@@ -278,6 +298,8 @@ const (
RTC_WIE_ON = 0x700f
RTC_WKALM_RD = 0x80287010
RTC_WKALM_SET = 0x4028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -316,6 +338,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
index 61d74b59..c731d24f 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
@@ -109,6 +109,7 @@ const (
HIDIOCGRAWINFO = 0x80084803
HIDIOCGRDESC = 0x90044802
HIDIOCGRDESCSIZE = 0x80044801
+ HIDIOCREVOKE = 0x4004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -153,9 +154,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x8008b705
NS_GET_NSTYPE = 0xb703
NS_GET_OWNER_UID = 0xb704
NS_GET_PARENT = 0xb702
+ NS_GET_PID_FROM_PIDNS = 0x8004b706
+ NS_GET_PID_IN_PIDNS = 0x8004b708
+ NS_GET_TGID_FROM_PIDNS = 0x8004b707
+ NS_GET_TGID_IN_PIDNS = 0x8004b709
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
@@ -232,6 +238,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x7434
PPPIOCXFERUNIT = 0x744e
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x80503d01
+ PTP_CLOCK_GETCAPS2 = 0x80503d0a
+ PTP_ENABLE_PPS = 0x40043d04
+ PTP_ENABLE_PPS2 = 0x40043d0d
+ PTP_EXTTS_REQUEST = 0x40103d02
+ PTP_EXTTS_REQUEST2 = 0x40103d0b
+ PTP_MASK_CLEAR_ALL = 0x3d13
+ PTP_MASK_EN_SINGLE = 0x40043d14
+ PTP_PEROUT_REQUEST = 0x40383d03
+ PTP_PEROUT_REQUEST2 = 0x40383d0c
+ PTP_PIN_SETFUNC = 0x40603d07
+ PTP_PIN_SETFUNC2 = 0x40603d10
+ PTP_SYS_OFFSET = 0x43403d05
+ PTP_SYS_OFFSET2 = 0x43403d0e
PTRACE_ARCH_PRCTL = 0x1e
PTRACE_GETFPREGS = 0xe
PTRACE_GETFPXREGS = 0x12
@@ -279,6 +299,8 @@ const (
RTC_WIE_ON = 0x700f
RTC_WKALM_RD = 0x80287010
RTC_WKALM_SET = 0x4028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -317,6 +339,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
index a28c9e3e..680018a4 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x80084803
HIDIOCGRDESC = 0x90044802
HIDIOCGRDESCSIZE = 0x80044801
+ HIDIOCREVOKE = 0x4004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -150,9 +151,14 @@ const (
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x8008b705
NS_GET_NSTYPE = 0xb703
NS_GET_OWNER_UID = 0xb704
NS_GET_PARENT = 0xb702
+ NS_GET_PID_FROM_PIDNS = 0x8004b706
+ NS_GET_PID_IN_PIDNS = 0x8004b708
+ NS_GET_TGID_FROM_PIDNS = 0x8004b707
+ NS_GET_TGID_IN_PIDNS = 0x8004b709
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
@@ -229,6 +235,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x7434
PPPIOCXFERUNIT = 0x744e
PR_SET_PTRACER_ANY = 0xffffffff
+ PTP_CLOCK_GETCAPS = 0x80503d01
+ PTP_CLOCK_GETCAPS2 = 0x80503d0a
+ PTP_ENABLE_PPS = 0x40043d04
+ PTP_ENABLE_PPS2 = 0x40043d0d
+ PTP_EXTTS_REQUEST = 0x40103d02
+ PTP_EXTTS_REQUEST2 = 0x40103d0b
+ PTP_MASK_CLEAR_ALL = 0x3d13
+ PTP_MASK_EN_SINGLE = 0x40043d14
+ PTP_PEROUT_REQUEST = 0x40383d03
+ PTP_PEROUT_REQUEST2 = 0x40383d0c
+ PTP_PIN_SETFUNC = 0x40603d07
+ PTP_PIN_SETFUNC2 = 0x40603d10
+ PTP_SYS_OFFSET = 0x43403d05
+ PTP_SYS_OFFSET2 = 0x43403d0e
PTRACE_GETCRUNCHREGS = 0x19
PTRACE_GETFDPIC = 0x1f
PTRACE_GETFDPIC_EXEC = 0x0
@@ -284,6 +304,8 @@ const (
RTC_WIE_ON = 0x700f
RTC_WKALM_RD = 0x80287010
RTC_WKALM_SET = 0x4028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -322,6 +344,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
index ab5d1fe8..a63909f3 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
@@ -112,6 +112,7 @@ const (
HIDIOCGRAWINFO = 0x80084803
HIDIOCGRDESC = 0x90044802
HIDIOCGRDESCSIZE = 0x80044801
+ HIDIOCREVOKE = 0x4004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -154,9 +155,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x8008b705
NS_GET_NSTYPE = 0xb703
NS_GET_OWNER_UID = 0xb704
NS_GET_PARENT = 0xb702
+ NS_GET_PID_FROM_PIDNS = 0x8004b706
+ NS_GET_PID_IN_PIDNS = 0x8004b708
+ NS_GET_TGID_FROM_PIDNS = 0x8004b707
+ NS_GET_TGID_IN_PIDNS = 0x8004b709
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
@@ -200,6 +206,7 @@ const (
PERF_EVENT_IOC_SET_BPF = 0x40042408
PERF_EVENT_IOC_SET_FILTER = 0x40082406
PERF_EVENT_IOC_SET_OUTPUT = 0x2405
+ POE_MAGIC = 0x504f4530
PPPIOCATTACH = 0x4004743d
PPPIOCATTCHAN = 0x40047438
PPPIOCBRIDGECHAN = 0x40047435
@@ -235,6 +242,20 @@ const (
PROT_BTI = 0x10
PROT_MTE = 0x20
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x80503d01
+ PTP_CLOCK_GETCAPS2 = 0x80503d0a
+ PTP_ENABLE_PPS = 0x40043d04
+ PTP_ENABLE_PPS2 = 0x40043d0d
+ PTP_EXTTS_REQUEST = 0x40103d02
+ PTP_EXTTS_REQUEST2 = 0x40103d0b
+ PTP_MASK_CLEAR_ALL = 0x3d13
+ PTP_MASK_EN_SINGLE = 0x40043d14
+ PTP_PEROUT_REQUEST = 0x40383d03
+ PTP_PEROUT_REQUEST2 = 0x40383d0c
+ PTP_PIN_SETFUNC = 0x40603d07
+ PTP_PIN_SETFUNC2 = 0x40603d10
+ PTP_SYS_OFFSET = 0x43403d05
+ PTP_SYS_OFFSET2 = 0x43403d0e
PTRACE_PEEKMTETAGS = 0x21
PTRACE_POKEMTETAGS = 0x22
PTRACE_SYSEMU = 0x1f
@@ -275,6 +296,8 @@ const (
RTC_WIE_ON = 0x700f
RTC_WKALM_RD = 0x80287010
RTC_WKALM_SET = 0x4028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -313,6 +336,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
index c523090e..9b0a2573 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go
@@ -109,6 +109,7 @@ const (
HIDIOCGRAWINFO = 0x80084803
HIDIOCGRDESC = 0x90044802
HIDIOCGRDESCSIZE = 0x80044801
+ HIDIOCREVOKE = 0x4004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -154,9 +155,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x8008b705
NS_GET_NSTYPE = 0xb703
NS_GET_OWNER_UID = 0xb704
NS_GET_PARENT = 0xb702
+ NS_GET_PID_FROM_PIDNS = 0x8004b706
+ NS_GET_PID_IN_PIDNS = 0x8004b708
+ NS_GET_TGID_FROM_PIDNS = 0x8004b707
+ NS_GET_TGID_IN_PIDNS = 0x8004b709
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
@@ -233,6 +239,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x7434
PPPIOCXFERUNIT = 0x744e
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x80503d01
+ PTP_CLOCK_GETCAPS2 = 0x80503d0a
+ PTP_ENABLE_PPS = 0x40043d04
+ PTP_ENABLE_PPS2 = 0x40043d0d
+ PTP_EXTTS_REQUEST = 0x40103d02
+ PTP_EXTTS_REQUEST2 = 0x40103d0b
+ PTP_MASK_CLEAR_ALL = 0x3d13
+ PTP_MASK_EN_SINGLE = 0x40043d14
+ PTP_PEROUT_REQUEST = 0x40383d03
+ PTP_PEROUT_REQUEST2 = 0x40383d0c
+ PTP_PIN_SETFUNC = 0x40603d07
+ PTP_PIN_SETFUNC2 = 0x40603d10
+ PTP_SYS_OFFSET = 0x43403d05
+ PTP_SYS_OFFSET2 = 0x43403d0e
PTRACE_SYSEMU = 0x1f
PTRACE_SYSEMU_SINGLESTEP = 0x20
RLIMIT_AS = 0x9
@@ -271,6 +291,8 @@ const (
RTC_WIE_ON = 0x700f
RTC_WKALM_RD = 0x80287010
RTC_WKALM_SET = 0x4028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -309,6 +331,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
index 01e6ea78..958e6e06 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x100
@@ -150,9 +151,14 @@ const (
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
@@ -229,6 +235,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x20007434
PPPIOCXFERUNIT = 0x2000744e
PR_SET_PTRACER_ANY = 0xffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETFPREGS = 0xe
PTRACE_GET_THREAD_AREA = 0x19
PTRACE_GET_THREAD_AREA_3264 = 0xc4
@@ -277,6 +297,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -315,6 +337,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x1029
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
index 7aa610b1..50c7f25b 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x100
@@ -150,9 +151,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
@@ -229,6 +235,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x20007434
PPPIOCXFERUNIT = 0x2000744e
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETFPREGS = 0xe
PTRACE_GET_THREAD_AREA = 0x19
PTRACE_GET_THREAD_AREA_3264 = 0xc4
@@ -277,6 +297,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -315,6 +337,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x1029
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
index 92af771b..ced21d66 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x100
@@ -150,9 +151,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
@@ -229,6 +235,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x20007434
PPPIOCXFERUNIT = 0x2000744e
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETFPREGS = 0xe
PTRACE_GET_THREAD_AREA = 0x19
PTRACE_GET_THREAD_AREA_3264 = 0xc4
@@ -277,6 +297,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -315,6 +337,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x1029
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
index b27ef5e6..226c0441 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x100
@@ -150,9 +151,14 @@ const (
NFDBITS = 0x20
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
@@ -229,6 +235,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x20007434
PPPIOCXFERUNIT = 0x2000744e
PR_SET_PTRACER_ANY = 0xffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETFPREGS = 0xe
PTRACE_GET_THREAD_AREA = 0x19
PTRACE_GET_THREAD_AREA_3264 = 0xc4
@@ -277,6 +297,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -315,6 +337,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x1029
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
index 237a2cef..3122737c 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x4000
ICANON = 0x100
IEXTEN = 0x400
@@ -152,9 +153,14 @@ const (
NL3 = 0x300
NLDLY = 0x300
NOFLSH = 0x80000000
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x4
ONLCR = 0x2
@@ -232,6 +238,20 @@ const (
PPPIOCXFERUNIT = 0x2000744e
PROT_SAO = 0x10
PR_SET_PTRACER_ANY = 0xffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETEVRREGS = 0x14
PTRACE_GETFPREGS = 0xe
PTRACE_GETREGS64 = 0x16
@@ -332,6 +352,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -370,6 +392,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
index 4a5c555a..eb5d3467 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x4000
ICANON = 0x100
IEXTEN = 0x400
@@ -152,9 +153,14 @@ const (
NL3 = 0x300
NLDLY = 0x300
NOFLSH = 0x80000000
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x4
ONLCR = 0x2
@@ -232,6 +238,20 @@ const (
PPPIOCXFERUNIT = 0x2000744e
PROT_SAO = 0x10
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETEVRREGS = 0x14
PTRACE_GETFPREGS = 0xe
PTRACE_GETREGS64 = 0x16
@@ -336,6 +356,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -374,6 +396,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
index a02fb49a..e921ebc6 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x4000
ICANON = 0x100
IEXTEN = 0x400
@@ -152,9 +153,14 @@ const (
NL3 = 0x300
NLDLY = 0x300
NOFLSH = 0x80000000
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x4
ONLCR = 0x2
@@ -232,6 +238,20 @@ const (
PPPIOCXFERUNIT = 0x2000744e
PROT_SAO = 0x10
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETEVRREGS = 0x14
PTRACE_GETFPREGS = 0xe
PTRACE_GETREGS64 = 0x16
@@ -336,6 +356,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -374,6 +396,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
index e26a7c61..38ba81c5 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x80084803
HIDIOCGRDESC = 0x90044802
HIDIOCGRDESCSIZE = 0x80044801
+ HIDIOCREVOKE = 0x4004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -150,9 +151,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x8008b705
NS_GET_NSTYPE = 0xb703
NS_GET_OWNER_UID = 0xb704
NS_GET_PARENT = 0xb702
+ NS_GET_PID_FROM_PIDNS = 0x8004b706
+ NS_GET_PID_IN_PIDNS = 0x8004b708
+ NS_GET_TGID_FROM_PIDNS = 0x8004b707
+ NS_GET_TGID_IN_PIDNS = 0x8004b709
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
@@ -229,6 +235,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x7434
PPPIOCXFERUNIT = 0x744e
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x80503d01
+ PTP_CLOCK_GETCAPS2 = 0x80503d0a
+ PTP_ENABLE_PPS = 0x40043d04
+ PTP_ENABLE_PPS2 = 0x40043d0d
+ PTP_EXTTS_REQUEST = 0x40103d02
+ PTP_EXTTS_REQUEST2 = 0x40103d0b
+ PTP_MASK_CLEAR_ALL = 0x3d13
+ PTP_MASK_EN_SINGLE = 0x40043d14
+ PTP_PEROUT_REQUEST = 0x40383d03
+ PTP_PEROUT_REQUEST2 = 0x40383d0c
+ PTP_PIN_SETFUNC = 0x40603d07
+ PTP_PIN_SETFUNC2 = 0x40603d10
+ PTP_SYS_OFFSET = 0x43403d05
+ PTP_SYS_OFFSET2 = 0x43403d0e
PTRACE_GETFDPIC = 0x21
PTRACE_GETFDPIC_EXEC = 0x0
PTRACE_GETFDPIC_INTERP = 0x1
@@ -268,6 +288,8 @@ const (
RTC_WIE_ON = 0x700f
RTC_WKALM_RD = 0x80287010
RTC_WKALM_SET = 0x4028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -306,6 +328,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
index c48f7c21..71f04009 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
@@ -108,6 +108,7 @@ const (
HIDIOCGRAWINFO = 0x80084803
HIDIOCGRDESC = 0x90044802
HIDIOCGRDESCSIZE = 0x80044801
+ HIDIOCREVOKE = 0x4004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -150,9 +151,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x8008b705
NS_GET_NSTYPE = 0xb703
NS_GET_OWNER_UID = 0xb704
NS_GET_PARENT = 0xb702
+ NS_GET_PID_FROM_PIDNS = 0x8004b706
+ NS_GET_PID_IN_PIDNS = 0x8004b708
+ NS_GET_TGID_FROM_PIDNS = 0x8004b707
+ NS_GET_TGID_IN_PIDNS = 0x8004b709
NS_GET_USERNS = 0xb701
OLCUC = 0x2
ONLCR = 0x4
@@ -229,6 +235,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x7434
PPPIOCXFERUNIT = 0x744e
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x80503d01
+ PTP_CLOCK_GETCAPS2 = 0x80503d0a
+ PTP_ENABLE_PPS = 0x40043d04
+ PTP_ENABLE_PPS2 = 0x40043d0d
+ PTP_EXTTS_REQUEST = 0x40103d02
+ PTP_EXTTS_REQUEST2 = 0x40103d0b
+ PTP_MASK_CLEAR_ALL = 0x3d13
+ PTP_MASK_EN_SINGLE = 0x40043d14
+ PTP_PEROUT_REQUEST = 0x40383d03
+ PTP_PEROUT_REQUEST2 = 0x40383d0c
+ PTP_PIN_SETFUNC = 0x40603d07
+ PTP_PIN_SETFUNC2 = 0x40603d10
+ PTP_SYS_OFFSET = 0x43403d05
+ PTP_SYS_OFFSET2 = 0x43403d0e
PTRACE_DISABLE_TE = 0x5010
PTRACE_ENABLE_TE = 0x5009
PTRACE_GET_LAST_BREAK = 0x5006
@@ -340,6 +360,8 @@ const (
RTC_WIE_ON = 0x700f
RTC_WKALM_RD = 0x80287010
RTC_WKALM_SET = 0x4028700f
+ SCM_DEVMEM_DMABUF = 0x4f
+ SCM_DEVMEM_LINEAR = 0x4e
SCM_TIMESTAMPING = 0x25
SCM_TIMESTAMPING_OPT_STATS = 0x36
SCM_TIMESTAMPING_PKTINFO = 0x3a
@@ -378,6 +400,9 @@ const (
SO_CNX_ADVICE = 0x35
SO_COOKIE = 0x39
SO_DETACH_REUSEPORT_BPF = 0x44
+ SO_DEVMEM_DMABUF = 0x4f
+ SO_DEVMEM_DONTNEED = 0x50
+ SO_DEVMEM_LINEAR = 0x4e
SO_DOMAIN = 0x27
SO_DONTROUTE = 0x5
SO_ERROR = 0x4
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
index ad4b9aac..c44a3133 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
@@ -112,6 +112,7 @@ const (
HIDIOCGRAWINFO = 0x40084803
HIDIOCGRDESC = 0x50044802
HIDIOCGRDESCSIZE = 0x40044801
+ HIDIOCREVOKE = 0x8004480d
HUPCL = 0x400
ICANON = 0x2
IEXTEN = 0x8000
@@ -155,9 +156,14 @@ const (
NFDBITS = 0x40
NLDLY = 0x100
NOFLSH = 0x80
+ NS_GET_MNTNS_ID = 0x4008b705
NS_GET_NSTYPE = 0x2000b703
NS_GET_OWNER_UID = 0x2000b704
NS_GET_PARENT = 0x2000b702
+ NS_GET_PID_FROM_PIDNS = 0x4004b706
+ NS_GET_PID_IN_PIDNS = 0x4004b708
+ NS_GET_TGID_FROM_PIDNS = 0x4004b707
+ NS_GET_TGID_IN_PIDNS = 0x4004b709
NS_GET_USERNS = 0x2000b701
OLCUC = 0x2
ONLCR = 0x4
@@ -234,6 +240,20 @@ const (
PPPIOCUNBRIDGECHAN = 0x20007434
PPPIOCXFERUNIT = 0x2000744e
PR_SET_PTRACER_ANY = 0xffffffffffffffff
+ PTP_CLOCK_GETCAPS = 0x40503d01
+ PTP_CLOCK_GETCAPS2 = 0x40503d0a
+ PTP_ENABLE_PPS = 0x80043d04
+ PTP_ENABLE_PPS2 = 0x80043d0d
+ PTP_EXTTS_REQUEST = 0x80103d02
+ PTP_EXTTS_REQUEST2 = 0x80103d0b
+ PTP_MASK_CLEAR_ALL = 0x20003d13
+ PTP_MASK_EN_SINGLE = 0x80043d14
+ PTP_PEROUT_REQUEST = 0x80383d03
+ PTP_PEROUT_REQUEST2 = 0x80383d0c
+ PTP_PIN_SETFUNC = 0x80603d07
+ PTP_PIN_SETFUNC2 = 0x80603d10
+ PTP_SYS_OFFSET = 0x83403d05
+ PTP_SYS_OFFSET2 = 0x83403d0e
PTRACE_GETFPAREGS = 0x14
PTRACE_GETFPREGS = 0xe
PTRACE_GETFPREGS64 = 0x19
@@ -331,6 +351,8 @@ const (
RTC_WIE_ON = 0x2000700f
RTC_WKALM_RD = 0x40287010
RTC_WKALM_SET = 0x8028700f
+ SCM_DEVMEM_DMABUF = 0x58
+ SCM_DEVMEM_LINEAR = 0x57
SCM_TIMESTAMPING = 0x23
SCM_TIMESTAMPING_OPT_STATS = 0x38
SCM_TIMESTAMPING_PKTINFO = 0x3c
@@ -417,6 +439,9 @@ const (
SO_CNX_ADVICE = 0x37
SO_COOKIE = 0x3b
SO_DETACH_REUSEPORT_BPF = 0x47
+ SO_DEVMEM_DMABUF = 0x58
+ SO_DEVMEM_DONTNEED = 0x59
+ SO_DEVMEM_LINEAR = 0x57
SO_DOMAIN = 0x1029
SO_DONTROUTE = 0x10
SO_ERROR = 0x1007
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go
index 1bc1a5ad..5cc1e8eb 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go
@@ -592,6 +592,16 @@ func ClockGettime(clockid int32, time *Timespec) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func ClockSettime(clockid int32, time *Timespec) (err error) {
+ _, _, e1 := Syscall(SYS_CLOCK_SETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error) {
_, _, e1 := Syscall6(SYS_CLOCK_NANOSLEEP, uintptr(clockid), uintptr(flags), uintptr(unsafe.Pointer(request)), uintptr(unsafe.Pointer(remain)), 0, 0)
if e1 != 0 {
@@ -971,23 +981,6 @@ func Getpriority(which int, who int) (prio int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getrandom(buf []byte, flags int) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := Syscall(SYS_GETRANDOM, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Getrusage(who int, rusage *Rusage) (err error) {
_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
if e1 != 0 {
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
index d3e38f68..f485dbf4 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
@@ -341,6 +341,7 @@ const (
SYS_STATX = 332
SYS_IO_PGETEVENTS = 333
SYS_RSEQ = 334
+ SYS_URETPROBE = 335
SYS_PIDFD_SEND_SIGNAL = 424
SYS_IO_URING_SETUP = 425
SYS_IO_URING_ENTER = 426
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
index 6c778c23..1893e2fe 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
@@ -85,7 +85,7 @@ const (
SYS_SPLICE = 76
SYS_TEE = 77
SYS_READLINKAT = 78
- SYS_FSTATAT = 79
+ SYS_NEWFSTATAT = 79
SYS_FSTAT = 80
SYS_SYNC = 81
SYS_FSYNC = 82
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go
index 37281cf5..16a4017d 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go
@@ -84,6 +84,8 @@ const (
SYS_SPLICE = 76
SYS_TEE = 77
SYS_READLINKAT = 78
+ SYS_NEWFSTATAT = 79
+ SYS_FSTAT = 80
SYS_SYNC = 81
SYS_FSYNC = 82
SYS_FDATASYNC = 83
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
index 9889f6a5..a5459e76 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
@@ -84,7 +84,7 @@ const (
SYS_SPLICE = 76
SYS_TEE = 77
SYS_READLINKAT = 78
- SYS_FSTATAT = 79
+ SYS_NEWFSTATAT = 79
SYS_FSTAT = 80
SYS_SYNC = 81
SYS_FSYNC = 82
diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
index d003c3d4..17c53bd9 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
@@ -462,11 +462,14 @@ type FdSet struct {
const (
SizeofIfMsghdr = 0x70
+ SizeofIfMsghdr2 = 0xa0
SizeofIfData = 0x60
+ SizeofIfData64 = 0x80
SizeofIfaMsghdr = 0x14
SizeofIfmaMsghdr = 0x10
SizeofIfmaMsghdr2 = 0x14
SizeofRtMsghdr = 0x5c
+ SizeofRtMsghdr2 = 0x5c
SizeofRtMetrics = 0x38
)
@@ -480,6 +483,20 @@ type IfMsghdr struct {
Data IfData
}
+type IfMsghdr2 struct {
+ Msglen uint16
+ Version uint8
+ Type uint8
+ Addrs int32
+ Flags int32
+ Index uint16
+ Snd_len int32
+ Snd_maxlen int32
+ Snd_drops int32
+ Timer int32
+ Data IfData64
+}
+
type IfData struct {
Type uint8
Typelen uint8
@@ -512,6 +529,34 @@ type IfData struct {
Reserved2 uint32
}
+type IfData64 struct {
+ Type uint8
+ Typelen uint8
+ Physical uint8
+ Addrlen uint8
+ Hdrlen uint8
+ Recvquota uint8
+ Xmitquota uint8
+ Unused1 uint8
+ Mtu uint32
+ Metric uint32
+ Baudrate uint64
+ Ipackets uint64
+ Ierrors uint64
+ Opackets uint64
+ Oerrors uint64
+ Collisions uint64
+ Ibytes uint64
+ Obytes uint64
+ Imcasts uint64
+ Omcasts uint64
+ Iqdrops uint64
+ Noproto uint64
+ Recvtiming uint32
+ Xmittiming uint32
+ Lastchange Timeval32
+}
+
type IfaMsghdr struct {
Msglen uint16
Version uint8
@@ -557,6 +602,21 @@ type RtMsghdr struct {
Rmx RtMetrics
}
+type RtMsghdr2 struct {
+ Msglen uint16
+ Version uint8
+ Type uint8
+ Index uint16
+ Flags int32
+ Addrs int32
+ Refcnt int32
+ Parentflags int32
+ Reserved int32
+ Use int32
+ Inits uint32
+ Rmx RtMetrics
+}
+
type RtMetrics struct {
Locks uint32
Mtu uint32
diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
index 0d45a941..2392226a 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
@@ -462,11 +462,14 @@ type FdSet struct {
const (
SizeofIfMsghdr = 0x70
+ SizeofIfMsghdr2 = 0xa0
SizeofIfData = 0x60
+ SizeofIfData64 = 0x80
SizeofIfaMsghdr = 0x14
SizeofIfmaMsghdr = 0x10
SizeofIfmaMsghdr2 = 0x14
SizeofRtMsghdr = 0x5c
+ SizeofRtMsghdr2 = 0x5c
SizeofRtMetrics = 0x38
)
@@ -480,6 +483,20 @@ type IfMsghdr struct {
Data IfData
}
+type IfMsghdr2 struct {
+ Msglen uint16
+ Version uint8
+ Type uint8
+ Addrs int32
+ Flags int32
+ Index uint16
+ Snd_len int32
+ Snd_maxlen int32
+ Snd_drops int32
+ Timer int32
+ Data IfData64
+}
+
type IfData struct {
Type uint8
Typelen uint8
@@ -512,6 +529,34 @@ type IfData struct {
Reserved2 uint32
}
+type IfData64 struct {
+ Type uint8
+ Typelen uint8
+ Physical uint8
+ Addrlen uint8
+ Hdrlen uint8
+ Recvquota uint8
+ Xmitquota uint8
+ Unused1 uint8
+ Mtu uint32
+ Metric uint32
+ Baudrate uint64
+ Ipackets uint64
+ Ierrors uint64
+ Opackets uint64
+ Oerrors uint64
+ Collisions uint64
+ Ibytes uint64
+ Obytes uint64
+ Imcasts uint64
+ Omcasts uint64
+ Iqdrops uint64
+ Noproto uint64
+ Recvtiming uint32
+ Xmittiming uint32
+ Lastchange Timeval32
+}
+
type IfaMsghdr struct {
Msglen uint16
Version uint8
@@ -557,6 +602,21 @@ type RtMsghdr struct {
Rmx RtMetrics
}
+type RtMsghdr2 struct {
+ Msglen uint16
+ Version uint8
+ Type uint8
+ Index uint16
+ Flags int32
+ Addrs int32
+ Refcnt int32
+ Parentflags int32
+ Reserved int32
+ Use int32
+ Inits uint32
+ Rmx RtMetrics
+}
+
type RtMetrics struct {
Locks uint32
Mtu uint32
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go
index 9f2550dc..5537148d 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -87,31 +87,35 @@ type StatxTimestamp struct {
}
type Statx_t struct {
- Mask uint32
- Blksize uint32
- Attributes uint64
- Nlink uint32
- Uid uint32
- Gid uint32
- Mode uint16
- _ [1]uint16
- Ino uint64
- Size uint64
- Blocks uint64
- Attributes_mask uint64
- Atime StatxTimestamp
- Btime StatxTimestamp
- Ctime StatxTimestamp
- Mtime StatxTimestamp
- Rdev_major uint32
- Rdev_minor uint32
- Dev_major uint32
- Dev_minor uint32
- Mnt_id uint64
- Dio_mem_align uint32
- Dio_offset_align uint32
- Subvol uint64
- _ [11]uint64
+ Mask uint32
+ Blksize uint32
+ Attributes uint64
+ Nlink uint32
+ Uid uint32
+ Gid uint32
+ Mode uint16
+ _ [1]uint16
+ Ino uint64
+ Size uint64
+ Blocks uint64
+ Attributes_mask uint64
+ Atime StatxTimestamp
+ Btime StatxTimestamp
+ Ctime StatxTimestamp
+ Mtime StatxTimestamp
+ Rdev_major uint32
+ Rdev_minor uint32
+ Dev_major uint32
+ Dev_minor uint32
+ Mnt_id uint64
+ Dio_mem_align uint32
+ Dio_offset_align uint32
+ Subvol uint64
+ Atomic_write_unit_min uint32
+ Atomic_write_unit_max uint32
+ Atomic_write_segments_max uint32
+ _ [1]uint32
+ _ [9]uint64
}
type Fsid struct {
@@ -516,6 +520,29 @@ type TCPInfo struct {
Total_rto_time uint32
}
+type TCPVegasInfo struct {
+ Enabled uint32
+ Rttcnt uint32
+ Rtt uint32
+ Minrtt uint32
+}
+
+type TCPDCTCPInfo struct {
+ Enabled uint16
+ Ce_state uint16
+ Alpha uint32
+ Ab_ecn uint32
+ Ab_tot uint32
+}
+
+type TCPBBRInfo struct {
+ Bw_lo uint32
+ Bw_hi uint32
+ Min_rtt uint32
+ Pacing_gain uint32
+ Cwnd_gain uint32
+}
+
type CanFilter struct {
Id uint32
Mask uint32
@@ -557,6 +584,7 @@ const (
SizeofICMPv6Filter = 0x20
SizeofUcred = 0xc
SizeofTCPInfo = 0xf8
+ SizeofTCPCCInfo = 0x14
SizeofCanFilter = 0x8
SizeofTCPRepairOpt = 0x8
)
@@ -1724,12 +1752,6 @@ const (
IFLA_IPVLAN_UNSPEC = 0x0
IFLA_IPVLAN_MODE = 0x1
IFLA_IPVLAN_FLAGS = 0x2
- NETKIT_NEXT = -0x1
- NETKIT_PASS = 0x0
- NETKIT_DROP = 0x2
- NETKIT_REDIRECT = 0x7
- NETKIT_L2 = 0x0
- NETKIT_L3 = 0x1
IFLA_NETKIT_UNSPEC = 0x0
IFLA_NETKIT_PEER_INFO = 0x1
IFLA_NETKIT_PRIMARY = 0x2
@@ -1768,6 +1790,7 @@ const (
IFLA_VXLAN_DF = 0x1d
IFLA_VXLAN_VNIFILTER = 0x1e
IFLA_VXLAN_LOCALBYPASS = 0x1f
+ IFLA_VXLAN_LABEL_POLICY = 0x20
IFLA_GENEVE_UNSPEC = 0x0
IFLA_GENEVE_ID = 0x1
IFLA_GENEVE_REMOTE = 0x2
@@ -1797,6 +1820,8 @@ const (
IFLA_GTP_ROLE = 0x4
IFLA_GTP_CREATE_SOCKETS = 0x5
IFLA_GTP_RESTART_COUNT = 0x6
+ IFLA_GTP_LOCAL = 0x7
+ IFLA_GTP_LOCAL6 = 0x8
IFLA_BOND_UNSPEC = 0x0
IFLA_BOND_MODE = 0x1
IFLA_BOND_ACTIVE_SLAVE = 0x2
@@ -1829,6 +1854,7 @@ const (
IFLA_BOND_AD_LACP_ACTIVE = 0x1d
IFLA_BOND_MISSED_MAX = 0x1e
IFLA_BOND_NS_IP6_TARGET = 0x1f
+ IFLA_BOND_COUPLED_CONTROL = 0x20
IFLA_BOND_AD_INFO_UNSPEC = 0x0
IFLA_BOND_AD_INFO_AGGREGATOR = 0x1
IFLA_BOND_AD_INFO_NUM_PORTS = 0x2
@@ -1897,6 +1923,7 @@ const (
IFLA_HSR_SEQ_NR = 0x5
IFLA_HSR_VERSION = 0x6
IFLA_HSR_PROTOCOL = 0x7
+ IFLA_HSR_INTERLINK = 0x8
IFLA_STATS_UNSPEC = 0x0
IFLA_STATS_LINK_64 = 0x1
IFLA_STATS_LINK_XSTATS = 0x2
@@ -1949,6 +1976,15 @@ const (
IFLA_DSA_MASTER = 0x1
)
+const (
+ NETKIT_NEXT = -0x1
+ NETKIT_PASS = 0x0
+ NETKIT_DROP = 0x2
+ NETKIT_REDIRECT = 0x7
+ NETKIT_L2 = 0x0
+ NETKIT_L3 = 0x1
+)
+
const (
NF_INET_PRE_ROUTING = 0x0
NF_INET_LOCAL_IN = 0x1
@@ -2558,8 +2594,8 @@ const (
SOF_TIMESTAMPING_BIND_PHC = 0x8000
SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000
- SOF_TIMESTAMPING_LAST = 0x10000
- SOF_TIMESTAMPING_MASK = 0x1ffff
+ SOF_TIMESTAMPING_LAST = 0x20000
+ SOF_TIMESTAMPING_MASK = 0x3ffff
SCM_TSTAMP_SND = 0x0
SCM_TSTAMP_SCHED = 0x1
@@ -3505,7 +3541,7 @@ type Nhmsg struct {
type NexthopGrp struct {
Id uint32
Weight uint8
- Resvd1 uint8
+ High uint8
Resvd2 uint16
}
@@ -3766,7 +3802,7 @@ const (
ETHTOOL_MSG_PSE_GET = 0x24
ETHTOOL_MSG_PSE_SET = 0x25
ETHTOOL_MSG_RSS_GET = 0x26
- ETHTOOL_MSG_USER_MAX = 0x2b
+ ETHTOOL_MSG_USER_MAX = 0x2d
ETHTOOL_MSG_KERNEL_NONE = 0x0
ETHTOOL_MSG_STRSET_GET_REPLY = 0x1
ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2
@@ -3806,7 +3842,7 @@ const (
ETHTOOL_MSG_MODULE_NTF = 0x24
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
ETHTOOL_MSG_RSS_GET_REPLY = 0x26
- ETHTOOL_MSG_KERNEL_MAX = 0x2b
+ ETHTOOL_MSG_KERNEL_MAX = 0x2e
ETHTOOL_FLAG_COMPACT_BITSETS = 0x1
ETHTOOL_FLAG_OMIT_REPLY = 0x2
ETHTOOL_FLAG_STATS = 0x4
@@ -3814,7 +3850,7 @@ const (
ETHTOOL_A_HEADER_DEV_INDEX = 0x1
ETHTOOL_A_HEADER_DEV_NAME = 0x2
ETHTOOL_A_HEADER_FLAGS = 0x3
- ETHTOOL_A_HEADER_MAX = 0x3
+ ETHTOOL_A_HEADER_MAX = 0x4
ETHTOOL_A_BITSET_BIT_UNSPEC = 0x0
ETHTOOL_A_BITSET_BIT_INDEX = 0x1
ETHTOOL_A_BITSET_BIT_NAME = 0x2
@@ -3951,7 +3987,7 @@ const (
ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17
ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18
ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19
- ETHTOOL_A_COALESCE_MAX = 0x1c
+ ETHTOOL_A_COALESCE_MAX = 0x1e
ETHTOOL_A_PAUSE_UNSPEC = 0x0
ETHTOOL_A_PAUSE_HEADER = 0x1
ETHTOOL_A_PAUSE_AUTONEG = 0x2
@@ -3995,11 +4031,11 @@ const (
ETHTOOL_A_CABLE_RESULT_UNSPEC = 0x0
ETHTOOL_A_CABLE_RESULT_PAIR = 0x1
ETHTOOL_A_CABLE_RESULT_CODE = 0x2
- ETHTOOL_A_CABLE_RESULT_MAX = 0x2
+ ETHTOOL_A_CABLE_RESULT_MAX = 0x3
ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC = 0x0
ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR = 0x1
ETHTOOL_A_CABLE_FAULT_LENGTH_CM = 0x2
- ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = 0x2
+ ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = 0x3
ETHTOOL_A_CABLE_TEST_NTF_STATUS_UNSPEC = 0x0
ETHTOOL_A_CABLE_TEST_NTF_STATUS_STARTED = 0x1
ETHTOOL_A_CABLE_TEST_NTF_STATUS_COMPLETED = 0x2
@@ -4082,6 +4118,107 @@ type EthtoolDrvinfo struct {
Regdump_len uint32
}
+type EthtoolTsInfo struct {
+ Cmd uint32
+ So_timestamping uint32
+ Phc_index int32
+ Tx_types uint32
+ Tx_reserved [3]uint32
+ Rx_filters uint32
+ Rx_reserved [3]uint32
+}
+
+type HwTstampConfig struct {
+ Flags int32
+ Tx_type int32
+ Rx_filter int32
+}
+
+const (
+ HWTSTAMP_FILTER_NONE = 0x0
+ HWTSTAMP_FILTER_ALL = 0x1
+ HWTSTAMP_FILTER_SOME = 0x2
+ HWTSTAMP_FILTER_PTP_V1_L4_EVENT = 0x3
+ HWTSTAMP_FILTER_PTP_V2_L4_EVENT = 0x6
+ HWTSTAMP_FILTER_PTP_V2_L2_EVENT = 0x9
+ HWTSTAMP_FILTER_PTP_V2_EVENT = 0xc
+)
+
+const (
+ HWTSTAMP_TX_OFF = 0x0
+ HWTSTAMP_TX_ON = 0x1
+ HWTSTAMP_TX_ONESTEP_SYNC = 0x2
+)
+
+type (
+ PtpClockCaps struct {
+ Max_adj int32
+ N_alarm int32
+ N_ext_ts int32
+ N_per_out int32
+ Pps int32
+ N_pins int32
+ Cross_timestamping int32
+ Adjust_phase int32
+ Max_phase_adj int32
+ Rsv [11]int32
+ }
+ PtpClockTime struct {
+ Sec int64
+ Nsec uint32
+ Reserved uint32
+ }
+ PtpExttsEvent struct {
+ T PtpClockTime
+ Index uint32
+ Flags uint32
+ Rsv [2]uint32
+ }
+ PtpExttsRequest struct {
+ Index uint32
+ Flags uint32
+ Rsv [2]uint32
+ }
+ PtpPeroutRequest struct {
+ StartOrPhase PtpClockTime
+ Period PtpClockTime
+ Index uint32
+ Flags uint32
+ On PtpClockTime
+ }
+ PtpPinDesc struct {
+ Name [64]byte
+ Index uint32
+ Func uint32
+ Chan uint32
+ Rsv [5]uint32
+ }
+ PtpSysOffset struct {
+ Samples uint32
+ Rsv [3]uint32
+ Ts [51]PtpClockTime
+ }
+ PtpSysOffsetExtended struct {
+ Samples uint32
+ Clockid int32
+ Rsv [2]uint32
+ Ts [25][3]PtpClockTime
+ }
+ PtpSysOffsetPrecise struct {
+ Device PtpClockTime
+ Realtime PtpClockTime
+ Monoraw PtpClockTime
+ Rsv [4]uint32
+ }
+)
+
+const (
+ PTP_PF_NONE = 0x0
+ PTP_PF_EXTTS = 0x1
+ PTP_PF_PEROUT = 0x2
+ PTP_PF_PHYSYNC = 0x3
+)
+
type (
HIDRawReportDescriptor struct {
Size uint32
@@ -4263,6 +4400,7 @@ const (
type LandlockRulesetAttr struct {
Access_fs uint64
Access_net uint64
+ Scoped uint64
}
type LandlockPathBeneathAttr struct {
@@ -4609,7 +4747,7 @@ const (
NL80211_ATTR_MAC_HINT = 0xc8
NL80211_ATTR_MAC_MASK = 0xd7
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
- NL80211_ATTR_MAX = 0x14a
+ NL80211_ATTR_MAX = 0x14c
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
NL80211_ATTR_MAX_MATCH_SETS = 0x85
@@ -5213,7 +5351,7 @@ const (
NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf
NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe
NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf
- NL80211_FREQUENCY_ATTR_MAX = 0x20
+ NL80211_FREQUENCY_ATTR_MAX = 0x21
NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6
NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
diff --git a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go
index d9a13af4..2e5d5a44 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go
@@ -377,6 +377,12 @@ type Flock_t struct {
Pid int32
}
+type F_cnvrt struct {
+ Cvtcmd int32
+ Pccsid int16
+ Fccsid int16
+}
+
type Termios struct {
Cflag uint32
Iflag uint32
diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go
index 115341fb..4e613cf6 100644
--- a/vendor/golang.org/x/sys/windows/dll_windows.go
+++ b/vendor/golang.org/x/sys/windows/dll_windows.go
@@ -65,7 +65,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
return d, nil
}
-// MustLoadDLL is like LoadDLL but panics if load operation failes.
+// MustLoadDLL is like LoadDLL but panics if load operation fails.
func MustLoadDLL(name string) *DLL {
d, e := LoadDLL(name)
if e != nil {
diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go
index 5cee9a31..4a325438 100644
--- a/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -168,6 +168,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *SecurityAttributes) (handle Handle, err error) [failretval==InvalidHandle] = CreateNamedPipeW
//sys ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error)
//sys DisconnectNamedPipe(pipe Handle) (err error)
+//sys GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err error)
+//sys GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err error)
//sys GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error)
//sys GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
//sys SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) = SetNamedPipeHandleState
@@ -725,20 +727,12 @@ func DurationSinceBoot() time.Duration {
}
func Ftruncate(fd Handle, length int64) (err error) {
- curoffset, e := Seek(fd, 0, 1)
- if e != nil {
- return e
- }
- defer Seek(fd, curoffset, 0)
- _, e = Seek(fd, length, 0)
- if e != nil {
- return e
+ type _FILE_END_OF_FILE_INFO struct {
+ EndOfFile int64
}
- e = SetEndOfFile(fd)
- if e != nil {
- return e
- }
- return nil
+ var info _FILE_END_OF_FILE_INFO
+ info.EndOfFile = length
+ return SetFileInformationByHandle(fd, FileEndOfFileInfo, (*byte)(unsafe.Pointer(&info)), uint32(unsafe.Sizeof(info)))
}
func Gettimeofday(tv *Timeval) (err error) {
@@ -894,6 +888,11 @@ const socket_error = uintptr(^uint32(0))
//sys GetACP() (acp uint32) = kernel32.GetACP
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
//sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
+//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
+//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
+//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
+//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange
+//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2
// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
@@ -1685,13 +1684,16 @@ func (s NTStatus) Error() string {
// do not use NTUnicodeString, and instead UTF16PtrFromString should be used for
// the more common *uint16 string type.
func NewNTUnicodeString(s string) (*NTUnicodeString, error) {
- var u NTUnicodeString
- s16, err := UTF16PtrFromString(s)
+ s16, err := UTF16FromString(s)
if err != nil {
return nil, err
}
- RtlInitUnicodeString(&u, s16)
- return &u, nil
+ n := uint16(len(s16) * 2)
+ return &NTUnicodeString{
+ Length: n - 2, // subtract 2 bytes for the NULL terminator
+ MaximumLength: n,
+ Buffer: &s16[0],
+ }, nil
}
// Slice returns a uint16 slice that aliases the data in the NTUnicodeString.
diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go
index 7b97a154..9d138de5 100644
--- a/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/vendor/golang.org/x/sys/windows/types_windows.go
@@ -176,6 +176,7 @@ const (
WAIT_FAILED = 0xFFFFFFFF
// Access rights for process.
+ PROCESS_ALL_ACCESS = 0xFFFF
PROCESS_CREATE_PROCESS = 0x0080
PROCESS_CREATE_THREAD = 0x0002
PROCESS_DUP_HANDLE = 0x0040
@@ -2203,6 +2204,132 @@ const (
IfOperStatusLowerLayerDown = 7
)
+const (
+ IF_MAX_PHYS_ADDRESS_LENGTH = 32
+ IF_MAX_STRING_SIZE = 256
+)
+
+// MIB_IF_ENTRY_LEVEL enumeration from netioapi.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getifentry2ex.
+const (
+ MibIfEntryNormal = 0
+ MibIfEntryNormalWithoutStatistics = 2
+)
+
+// MIB_NOTIFICATION_TYPE enumeration from netioapi.h or
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ne-netioapi-mib_notification_type.
+const (
+ MibParameterNotification = 0
+ MibAddInstance = 1
+ MibDeleteInstance = 2
+ MibInitialNotification = 3
+)
+
+// MibIfRow2 stores information about a particular interface. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_if_row2.
+type MibIfRow2 struct {
+ InterfaceLuid uint64
+ InterfaceIndex uint32
+ InterfaceGuid GUID
+ Alias [IF_MAX_STRING_SIZE + 1]uint16
+ Description [IF_MAX_STRING_SIZE + 1]uint16
+ PhysicalAddressLength uint32
+ PhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8
+ PermanentPhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8
+ Mtu uint32
+ Type uint32
+ TunnelType uint32
+ MediaType uint32
+ PhysicalMediumType uint32
+ AccessType uint32
+ DirectionType uint32
+ InterfaceAndOperStatusFlags uint8
+ OperStatus uint32
+ AdminStatus uint32
+ MediaConnectState uint32
+ NetworkGuid GUID
+ ConnectionType uint32
+ TransmitLinkSpeed uint64
+ ReceiveLinkSpeed uint64
+ InOctets uint64
+ InUcastPkts uint64
+ InNUcastPkts uint64
+ InDiscards uint64
+ InErrors uint64
+ InUnknownProtos uint64
+ InUcastOctets uint64
+ InMulticastOctets uint64
+ InBroadcastOctets uint64
+ OutOctets uint64
+ OutUcastPkts uint64
+ OutNUcastPkts uint64
+ OutDiscards uint64
+ OutErrors uint64
+ OutUcastOctets uint64
+ OutMulticastOctets uint64
+ OutBroadcastOctets uint64
+ OutQLen uint64
+}
+
+// MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See
+// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row.
+type MibUnicastIpAddressRow struct {
+ Address RawSockaddrInet6 // SOCKADDR_INET union
+ InterfaceLuid uint64
+ InterfaceIndex uint32
+ PrefixOrigin uint32
+ SuffixOrigin uint32
+ ValidLifetime uint32
+ PreferredLifetime uint32
+ OnLinkPrefixLength uint8
+ SkipAsSource uint8
+ DadState uint32
+ ScopeId uint32
+ CreationTimeStamp Filetime
+}
+
+const ScopeLevelCount = 16
+
+// MIB_IPINTERFACE_ROW stores interface management information for a particular IP address family on a network interface.
+// See https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipinterface_row.
+type MibIpInterfaceRow struct {
+ Family uint16
+ InterfaceLuid uint64
+ InterfaceIndex uint32
+ MaxReassemblySize uint32
+ InterfaceIdentifier uint64
+ MinRouterAdvertisementInterval uint32
+ MaxRouterAdvertisementInterval uint32
+ AdvertisingEnabled uint8
+ ForwardingEnabled uint8
+ WeakHostSend uint8
+ WeakHostReceive uint8
+ UseAutomaticMetric uint8
+ UseNeighborUnreachabilityDetection uint8
+ ManagedAddressConfigurationSupported uint8
+ OtherStatefulConfigurationSupported uint8
+ AdvertiseDefaultRoute uint8
+ RouterDiscoveryBehavior uint32
+ DadTransmits uint32
+ BaseReachableTime uint32
+ RetransmitTime uint32
+ PathMtuDiscoveryTimeout uint32
+ LinkLocalAddressBehavior uint32
+ LinkLocalAddressTimeout uint32
+ ZoneIndices [ScopeLevelCount]uint32
+ SitePrefixLength uint32
+ Metric uint32
+ NlMtu uint32
+ Connected uint8
+ SupportsWakeUpPatterns uint8
+ SupportsNeighborDiscovery uint8
+ SupportsRouterDiscovery uint8
+ ReachableTime uint32
+ TransmitOffload uint32
+ ReceiveOffload uint32
+ DisableDefaultRoutes uint8
+}
+
// Console related constants used for the mode parameter to SetConsoleMode. See
// https://docs.microsoft.com/en-us/windows/console/setconsolemode for details.
diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index 4c2e1bdc..01c0716c 100644
--- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -181,10 +181,15 @@ var (
procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree")
procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute")
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
+ procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2")
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx")
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
+ procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex")
+ procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
+ procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
+ procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
procAddDllDirectory = modkernel32.NewProc("AddDllDirectory")
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
procCancelIo = modkernel32.NewProc("CancelIo")
@@ -275,8 +280,10 @@ var (
procGetMaximumProcessorCount = modkernel32.NewProc("GetMaximumProcessorCount")
procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW")
procGetModuleHandleExW = modkernel32.NewProc("GetModuleHandleExW")
+ procGetNamedPipeClientProcessId = modkernel32.NewProc("GetNamedPipeClientProcessId")
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
+ procGetNamedPipeServerProcessId = modkernel32.NewProc("GetNamedPipeServerProcessId")
procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
procGetPriorityClass = modkernel32.NewProc("GetPriorityClass")
procGetProcAddress = modkernel32.NewProc("GetProcAddress")
@@ -1606,6 +1613,14 @@ func DwmSetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, si
return
}
+func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) {
+ r0, _, _ := syscall.Syscall(procCancelMibChangeNotify2.Addr(), 1, uintptr(notificationHandle), 0, 0)
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0)
if r0 != 0 {
@@ -1638,6 +1653,46 @@ func GetIfEntry(pIfRow *MibIfRow) (errcode error) {
return
}
+func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) {
+ r0, _, _ := syscall.Syscall(procGetIfEntry2Ex.Addr(), 2, uintptr(level), uintptr(unsafe.Pointer(row)), 0)
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
+func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
+ r0, _, _ := syscall.Syscall(procGetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0)
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
+func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
+ var _p0 uint32
+ if initialNotification {
+ _p0 = 1
+ }
+ r0, _, _ := syscall.Syscall6(procNotifyIpInterfaceChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0)
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
+func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
+ var _p0 uint32
+ if initialNotification {
+ _p0 = 1
+ }
+ r0, _, _ := syscall.Syscall6(procNotifyUnicastIpAddressChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0)
+ if r0 != 0 {
+ errcode = syscall.Errno(r0)
+ }
+ return
+}
+
func AddDllDirectory(path *uint16) (cookie uintptr, err error) {
r0, _, e1 := syscall.Syscall(procAddDllDirectory.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
cookie = uintptr(r0)
@@ -2393,6 +2448,14 @@ func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err er
return
}
+func GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetNamedPipeClientProcessId.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(clientProcessID)), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
if r1 == 0 {
@@ -2409,6 +2472,14 @@ func GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint3
return
}
+func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetNamedPipeServerProcessId.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(serverProcessID)), 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) {
var _p0 uint32
if wait {
diff --git a/vendor/golang.org/x/term/README.md b/vendor/golang.org/x/term/README.md
index d03d0aef..05ff623f 100644
--- a/vendor/golang.org/x/term/README.md
+++ b/vendor/golang.org/x/term/README.md
@@ -4,16 +4,13 @@
This repository provides Go terminal and console support packages.
-## Download/Install
-
-The easiest way to install is to run `go get -u golang.org/x/term`. You can
-also manually git clone the repository to `$GOPATH/src/golang.org/x/term`.
-
## Report Issues / Send Patches
This repository uses Gerrit for code changes. To learn how to submit changes to
-this repository, see https://golang.org/doc/contribute.html.
+this repository, see https://go.dev/doc/contribute.
+
+The git repository is https://go.googlesource.com/term.
The main issue tracker for the term repository is located at
-https://github.com/golang/go/issues. Prefix your issue with "x/term:" in the
+https://go.dev/issues. Prefix your issue with "x/term:" in the
subject line, so it is easy to find.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 71f12d33..46bfa756 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -8,8 +8,8 @@ github.com/Microsoft/go-winio/internal/fs
github.com/Microsoft/go-winio/internal/socket
github.com/Microsoft/go-winio/internal/stringbuffer
github.com/Microsoft/go-winio/pkg/guid
-# github.com/ProtonMail/go-crypto v1.0.0
-## explicit; go 1.13
+# github.com/ProtonMail/go-crypto v1.1.3
+## explicit; go 1.17
github.com/ProtonMail/go-crypto/bitcurves
github.com/ProtonMail/go-crypto/brainpool
github.com/ProtonMail/go-crypto/eax
@@ -20,6 +20,8 @@ github.com/ProtonMail/go-crypto/openpgp/aes/keywrap
github.com/ProtonMail/go-crypto/openpgp/armor
github.com/ProtonMail/go-crypto/openpgp/ecdh
github.com/ProtonMail/go-crypto/openpgp/ecdsa
+github.com/ProtonMail/go-crypto/openpgp/ed25519
+github.com/ProtonMail/go-crypto/openpgp/ed448
github.com/ProtonMail/go-crypto/openpgp/eddsa
github.com/ProtonMail/go-crypto/openpgp/elgamal
github.com/ProtonMail/go-crypto/openpgp/errors
@@ -28,6 +30,8 @@ github.com/ProtonMail/go-crypto/openpgp/internal/ecc
github.com/ProtonMail/go-crypto/openpgp/internal/encoding
github.com/ProtonMail/go-crypto/openpgp/packet
github.com/ProtonMail/go-crypto/openpgp/s2k
+github.com/ProtonMail/go-crypto/openpgp/x25519
+github.com/ProtonMail/go-crypto/openpgp/x448
# github.com/bitrise-io/colorstring v0.0.0-20180614154802-a8cd70115192
## explicit
github.com/bitrise-io/colorstring
@@ -100,7 +104,7 @@ github.com/cloudflare/circl/sign/ed448
# github.com/cpuguy83/go-md2man/v2 v2.0.4
## explicit; go 1.11
github.com/cpuguy83/go-md2man/v2/md2man
-# github.com/cyphar/filepath-securejoin v0.2.4
+# github.com/cyphar/filepath-securejoin v0.2.5
## explicit; go 1.13
github.com/cyphar/filepath-securejoin
# github.com/davecgh/go-spew v1.1.1
@@ -159,16 +163,16 @@ github.com/go-git/gcfg
github.com/go-git/gcfg/scanner
github.com/go-git/gcfg/token
github.com/go-git/gcfg/types
-# github.com/go-git/go-billy/v5 v5.5.0
-## explicit; go 1.19
+# github.com/go-git/go-billy/v5 v5.6.0
+## explicit; go 1.20
github.com/go-git/go-billy/v5
github.com/go-git/go-billy/v5/helper/chroot
github.com/go-git/go-billy/v5/helper/polyfill
github.com/go-git/go-billy/v5/memfs
github.com/go-git/go-billy/v5/osfs
github.com/go-git/go-billy/v5/util
-# github.com/go-git/go-git/v5 v5.12.0
-## explicit; go 1.19
+# github.com/go-git/go-git/v5 v5.13.0
+## explicit; go 1.21
github.com/go-git/go-git/v5
github.com/go-git/go-git/v5/config
github.com/go-git/go-git/v5/internal/path_util
@@ -283,12 +287,13 @@ github.com/sergi/go-diff/diffmatchpatch
# github.com/sirupsen/logrus v1.9.3
## explicit; go 1.13
github.com/sirupsen/logrus
-# github.com/skeema/knownhosts v1.2.2
+# github.com/skeema/knownhosts v1.3.0
## explicit; go 1.17
github.com/skeema/knownhosts
-# github.com/stretchr/testify v1.9.0
+# github.com/stretchr/testify v1.10.0
## explicit; go 1.17
github.com/stretchr/testify/assert
+github.com/stretchr/testify/assert/yaml
github.com/stretchr/testify/require
# github.com/urfave/cli v1.22.15
## explicit; go 1.11
@@ -296,7 +301,7 @@ github.com/urfave/cli
# github.com/xanzy/ssh-agent v0.3.3
## explicit; go 1.16
github.com/xanzy/ssh-agent
-# golang.org/x/crypto v0.27.0
+# golang.org/x/crypto v0.31.0
## explicit; go 1.20
golang.org/x/crypto/argon2
golang.org/x/crypto/blake2b
@@ -319,22 +324,22 @@ golang.org/x/exp/maps
# golang.org/x/mod v0.21.0
## explicit; go 1.22.0
golang.org/x/mod/semver
-# golang.org/x/net v0.29.0
+# golang.org/x/net v0.33.0
## explicit; go 1.18
golang.org/x/net/context
golang.org/x/net/internal/socks
golang.org/x/net/proxy
-# golang.org/x/sync v0.8.0
+# golang.org/x/sync v0.10.0
## explicit; go 1.18
golang.org/x/sync/errgroup
-# golang.org/x/sys v0.25.0
+# golang.org/x/sys v0.28.0
## explicit; go 1.18
golang.org/x/sys/cpu
golang.org/x/sys/execabs
golang.org/x/sys/plan9
golang.org/x/sys/unix
golang.org/x/sys/windows
-# golang.org/x/term v0.24.0
+# golang.org/x/term v0.27.0
## explicit; go 1.18
golang.org/x/term
# golang.org/x/time v0.5.0
diff --git a/version/build.go b/version/build.go
index 0d150e8e..e4ea6575 100644
--- a/version/build.go
+++ b/version/build.go
@@ -1,7 +1,7 @@
package version
// VERSION is the main CLI version number. It's defined at build time using -ldflags
-var VERSION = "2.24.3"
+var VERSION = "2.25.2"
// BuildNumber is the CI build number that creates the release. It's defined at build time using -ldflags
var BuildNumber = ""