From a434d4f186ed7cd52d1c07d5b8fca291abd0c05a Mon Sep 17 00:00:00 2001 From: user Date: Tue, 5 May 2026 19:43:57 -0400 Subject: [PATCH 1/2] feat: embed ACVP wrapper with reproducible public-API test flow Add ACVP wrapper entrypoints to clickhouse-backup and package the acvp symlink so the shipped binary can be exercised by acvptool. Add a tracked public-API-only ACVP config, reproducibility script, and documentation with pinned upstream references while aligning advertised wrapper capabilities with the supported public Go crypto scope. Co-authored-by: Cursor --- Makefile | 1 + cmd/clickhouse-backup/main.go | 16 + go.sum | 351 ----- pkg/acvpwrapper/README.md | 129 ++ .../acvp_test_fips140v1.26.public.config.json | 55 + pkg/acvpwrapper/doc.go | 8 + pkg/acvpwrapper/go_port_extra.go | 1073 ++++++++++++++ pkg/acvpwrapper/official_compat.go | 351 +++++ pkg/acvpwrapper/run.sh | 52 + pkg/acvpwrapper/wrapper.go | 1235 +++++++++++++++++ pkg/acvpwrapper/wrapper_test.go | 65 + 11 files changed, 2985 insertions(+), 351 deletions(-) create mode 100644 pkg/acvpwrapper/README.md create mode 100644 pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json create mode 100644 pkg/acvpwrapper/doc.go create mode 100644 pkg/acvpwrapper/go_port_extra.go create mode 100644 pkg/acvpwrapper/official_compat.go create mode 100644 pkg/acvpwrapper/run.sh create mode 100644 pkg/acvpwrapper/wrapper.go create mode 100644 pkg/acvpwrapper/wrapper_test.go diff --git a/Makefile b/Makefile index d50d90356..344d451bd 100644 --- a/Makefile +++ b/Makefile @@ -85,6 +85,7 @@ build/linux/amd64/pkg build/linux/arm64/pkg: build config mkdir -pv pkg/etc/$(NAME) && \ mkdir -pv pkg/usr/bin && \ cp -lv $(NAME) pkg/usr/bin/ && \ + ln -sfv $(NAME) pkg/usr/bin/$(NAME)-acvp && \ cp -lv ../../../$(NAME)/config.yml pkg/etc/$(NAME)/config.yml.example diff --git a/cmd/clickhouse-backup/main.go b/cmd/clickhouse-backup/main.go index 995891378..1302abd18 100644 --- a/cmd/clickhouse-backup/main.go +++ b/cmd/clickhouse-backup/main.go @@ -6,12 +6,14 @@ import ( "fmt" stdlog "log" "os" + "path/filepath" "runtime" "strings" "github.com/rs/zerolog/log" "github.com/urfave/cli" + "github.com/Altinity/clickhouse-backup/v2/pkg/acvpwrapper" "github.com/Altinity/clickhouse-backup/v2/pkg/backup" "github.com/Altinity/clickhouse-backup/v2/pkg/config" "github.com/Altinity/clickhouse-backup/v2/pkg/log_helper" @@ -30,6 +32,12 @@ func main() { log.Logger = log_helper.SetupLogger(os.Stderr) //log.Logger = zerolog.New(os.Stdout).With().Timestamp().Caller().Logger() stdlog.SetOutput(log.Logger) + if filepath.Base(os.Args[0]) == "clickhouse-backup-acvp" { + if err := acvpwrapper.Run(os.Stdin, os.Stdout); err != nil { + log.Fatal().Stack().Err(err).Send() + } + return + } cliapp := cli.NewApp() cliapp.Name = "clickhouse-backup" cliapp.Usage = "Tool for easy backup of ClickHouse with cloud support" @@ -788,6 +796,14 @@ func main() { }, ), }, + { + Name: "acvp", + Usage: "Run ACVP wrapper protocol over stdin/stdout", + UsageText: "clickhouse-backup acvp", + Action: func(*cli.Context) error { + return acvpwrapper.Run(os.Stdin, os.Stdout) + }, + }, { Name: "server", Usage: "Run API server", diff --git a/go.sum b/go.sum index 284b508e8..2f2e6d920 100644 --- a/go.sum +++ b/go.sum @@ -2,250 +2,24 @@ cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= -cloud.google.com/go/accessapproval v1.9.0 h1:1VDsl/eOH+KGBKs4DfnQmH4ctq46skAhpfWF11Hg7NA= -cloud.google.com/go/accessapproval v1.9.0/go.mod h1:GLlfSKe9gJN28w2CVfR9J8eWZgFruNutEU+GAx1iXHo= -cloud.google.com/go/accesscontextmanager v1.10.0 h1:rD94r5dkI7MKvTGZ9Gh3jMtydi/Gkot5lasqTRaz1jo= -cloud.google.com/go/accesscontextmanager v1.10.0/go.mod h1:F6ajq/ZMZ0bYpOr3LRtBQrhI0l1i80Esg7b128YNVas= -cloud.google.com/go/aiplatform v1.122.0 h1:l9euMxde3/yL/txA1ngCM6zyTSXbjmos/OtUXDAeqhw= -cloud.google.com/go/aiplatform v1.122.0/go.mod h1:Z0QhICmtYNxf0fbl/axHrVXCGcfdYuedH5NK+GwVu1I= -cloud.google.com/go/analytics v0.31.0 h1:Pqx7ijruNEdZxU6LKlQVTm14IUlYQJK3asnCg49E6wo= -cloud.google.com/go/analytics v0.31.0/go.mod h1:3nTQB3QiqS9Z07tbj+8Q2Yf9HQnSP256tkpwFilY7qs= -cloud.google.com/go/apigateway v1.8.0 h1:ILgnEnW22KJ0+UxIs/CAEPzZtlT78YfFRxzHPZElxlk= -cloud.google.com/go/apigateway v1.8.0/go.mod h1:G/+yRp7QCx2JDnw5awoCqpOOxeFS1EU2YU1kIip/0BE= -cloud.google.com/go/apigeeconnect v1.8.0 h1:6ki2O8bYtzJR1pd22EoflIdCrTmnfqBR2XyPALyuCBc= -cloud.google.com/go/apigeeconnect v1.8.0/go.mod h1:1SwzPtTk3T2nmEmYQB3vxO6kdSE22HGPOvoWIzyXjmg= -cloud.google.com/go/apigeeregistry v0.11.0 h1:hMU7z5yWpN/H9Sne4gKaq4Ot6YhGoblqm6fQJ/EF1NE= -cloud.google.com/go/apigeeregistry v0.11.0/go.mod h1:UR0cACaSYm2nocg3R6mKNBY83atd9pz1HqLADp40lF8= -cloud.google.com/go/appengine v1.10.0 h1:AR570QVl/GsjfY08746nnhZH4CitatoOIfuGHRVBYCg= -cloud.google.com/go/appengine v1.10.0/go.mod h1:IStRRjdbvxAesIPg8vWSCfz4SgEroFHyNZh2oYwoyOQ= -cloud.google.com/go/area120 v0.11.0 h1:8KqInhJtLU6iPMK3UiSeUhP8YfH0WAXTOP/e1w6hmXA= -cloud.google.com/go/area120 v0.11.0/go.mod h1:/Q8MRFwW+enSQrxsmrKZtEh+E+LuVh7Ytg3tCkzq2lw= -cloud.google.com/go/artifactregistry v1.21.0 h1:JroY3+JSqXTFVm6/jyV2RcaeiEL1sWPbD4QlUuS2/vI= -cloud.google.com/go/artifactregistry v1.21.0/go.mod h1:IhMxwuMpzlVJjpTodjz1eZXMxvMxXS9/vgG5hbnYUz0= -cloud.google.com/go/asset v1.23.0 h1:st7nbY+qFstQlEfKm3Qz6Db8BtaSqqrPCGyzbb+8sB8= -cloud.google.com/go/asset v1.23.0/go.mod h1:LTL+e6J4kc493wnt5uSlC3Dss+S6b9QgK5cBxjTghqw= -cloud.google.com/go/assuredworkloads v1.14.0 h1:Ow97NtLGWaJwAKe9yL7LlYQ+mR3qf7S5IFekmGz3fwA= -cloud.google.com/go/assuredworkloads v1.14.0/go.mod h1:eSvUapoU9yH71+XZ4WNOXQAXqKj1X1xbPPudXGxDCbA= cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= -cloud.google.com/go/automl v1.16.0 h1:NyJfSIUCESwBrhmMDJAtU7GBX/sKXKNk2g79ztYINvk= -cloud.google.com/go/automl v1.16.0/go.mod h1:01pqJU9T8xQ6JW4zcP9zgtnKLDugRrtJrO5Mcl5S0rg= -cloud.google.com/go/baremetalsolution v1.5.0 h1:hZyXs1WGrQo01CGK9HAqrKAUsZ7ns9DhxRlZlqnUkxI= -cloud.google.com/go/baremetalsolution v1.5.0/go.mod h1:e4+LWVqGObMTL1R6HVqWNA+Km32H/qvf573xB47T+bM= -cloud.google.com/go/batch v1.15.0 h1:rT0sgSDCz0egr9QXEHOuCmctwCsy0eSE+md06WpqqJg= -cloud.google.com/go/batch v1.15.0/go.mod h1:/3beOUtaLJChD59xNgCgXxEeXrtv5EDLMzUVYr9aiqo= -cloud.google.com/go/beyondcorp v1.3.0 h1:25t2kJjtHhf+rF0bMrfLpw46kzi4tzh0mIWnGbv82BQ= -cloud.google.com/go/beyondcorp v1.3.0/go.mod h1:8yO8ZZOF8ZNfRHcQ1nB6PjZx+9f9ey38uKcQZcM4VSA= -cloud.google.com/go/bigquery v1.75.0 h1:gI4AgIhXNZ8hxvPDOp4hLGUnpNBjoBor6POSLcrdWkY= -cloud.google.com/go/bigquery v1.75.0/go.mod h1:zNCHWok+hfTgKCwNqT+V7GH/YmFFgZqjzljKCZBJTWc= -cloud.google.com/go/bigtable v1.45.0 h1:OWl6kq6Ju8m4fZkV3bve7n9882W4HrlXPqtW5zT5ttA= -cloud.google.com/go/bigtable v1.45.0/go.mod h1:Ztklmotutn5zkAYzsn2w8ye8wvy+azwyGwYmujW5JHg= -cloud.google.com/go/billing v1.22.0 h1:yU4GwnMlr67TAV7apg+Ca2i7Lu1rJnWGgmLS6d+qTyM= -cloud.google.com/go/billing v1.22.0/go.mod h1:nQVTVqWyw8YK0QScVV1pXr9KrvjvM7cabIQr6tLJMys= -cloud.google.com/go/binaryauthorization v1.11.0 h1:6KaAsLGvf9DQmS00NqYb6ZJjsUwjILlmEjlJqgXjEMc= -cloud.google.com/go/binaryauthorization v1.11.0/go.mod h1:2GBJK67zdEkeXGpnHYDXa21cngrYL99jR+Z688gom5c= -cloud.google.com/go/certificatemanager v1.10.0 h1:3cyEmZs+sK+dXsO9R04ZprBInovTVpMz0DfFidiwY4Y= -cloud.google.com/go/certificatemanager v1.10.0/go.mod h1:dfJSJnWK2wgw2BTQ5oaAalombcajsviqsA6liniLL/U= -cloud.google.com/go/channel v1.22.0 h1:wU7nhpf/u44HpywYZVwR4EeC321/gKL4hLgjNQvvmQ4= -cloud.google.com/go/channel v1.22.0/go.mod h1:Eodq1pGB6UnpVB622T0NGf2qvW9aJYGqaojcW8IS6UU= -cloud.google.com/go/cloudbuild v1.26.0 h1:cXQPxSPw8Dv+geEXIp2kr+1ShUO/l96T4Vg6OJOSO0o= -cloud.google.com/go/cloudbuild v1.26.0/go.mod h1:gKgjpgxUSqlX4TLVPoCYYAskEtHdbNpnTMEL2vUMT1s= -cloud.google.com/go/clouddms v1.9.0 h1:TAzF67eY6r2QIKVF+NnniFl0TE12IB075X+00fJB2qA= -cloud.google.com/go/clouddms v1.9.0/go.mod h1:O0P8OX8QBK0UFlDJx+Xd32aHi3qltjel4q67YyZPJIg= -cloud.google.com/go/cloudtasks v1.14.0 h1:l+9VVqB6Bbpn1NhYBwn9TMs5Yu7jU0bSfd9mrRilt48= -cloud.google.com/go/cloudtasks v1.14.0/go.mod h1:mFzsLKuM4gzzmlbu1363510Fjm5ZJR+8mH1C2w5roJo= -cloud.google.com/go/compute v1.58.0 h1:WQamD8d9Vxu+m5IJBxgUzqsbHxXwx/T7Ol4V5GyVCZE= -cloud.google.com/go/compute v1.58.0/go.mod h1:5/1KiFDIdFPcx/Fw6pFQpcQaBGc6MGtgSfczeLFBj7o= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -cloud.google.com/go/contactcenterinsights v1.18.0 h1:rJmH8gce0C2hmpDp8eeZFGK4Jb/uq8ryCK3HH/MMK3g= -cloud.google.com/go/contactcenterinsights v1.18.0/go.mod h1:uvgwG1ey82pNIxZ6r4gfu0bZZ+EiVdUqxKa7b/Ilw+A= -cloud.google.com/go/container v1.47.0 h1:bQFpaGHEnNOv3FM8tYj3efzi/omInP/YO/kzZrLjTRU= -cloud.google.com/go/container v1.47.0/go.mod h1:ySZKwTx9fTEqo1YiWN09SrM96a/dgpxXsi1tEzWGQd0= -cloud.google.com/go/containeranalysis v0.15.0 h1:yNQvV+y0zmxcMU1ILyVqq8U42MF63mTDF63EHGO/gvA= -cloud.google.com/go/containeranalysis v0.15.0/go.mod h1:CgPFsUrNm5vZDlxW4DBdeYTW9KVtZVJLzHOtERyuEVc= -cloud.google.com/go/datacatalog v1.27.0 h1:AnghhtHKCqYIe62gTPHcn9nJr5jtxjZHV4D/Fob23gg= -cloud.google.com/go/datacatalog v1.27.0/go.mod h1:YTI11pFlC5HCj4CphEf+qWCy/z9udd7o0HVN6c2Povg= -cloud.google.com/go/dataflow v0.12.0 h1:pPCJDUMz86izPoO3rHqrWWD4A1oZIZMcc8CXj2dvJcs= -cloud.google.com/go/dataflow v0.12.0/go.mod h1:jcNeMiDW4pVYYKLi4jFkJmPwtq2A8OIF0CCqoh9K6yI= -cloud.google.com/go/dataform v0.15.0 h1:CXiCcxwib/94U+WhWA3SGvK64soijKH17FKhF3AvJfw= -cloud.google.com/go/dataform v0.15.0/go.mod h1:buNB3+hgOk+RhmONRw13Mk7uqANhRYGJOUVWDx63PtM= -cloud.google.com/go/datafusion v1.9.0 h1:Y8El5INUC/nXFdMFW+vCWzsEIT7U3nem4ePbpAnoCDg= -cloud.google.com/go/datafusion v1.9.0/go.mod h1:sJzQ3KEt3pVmQzlO1RDnujdf5gB2agNzlKt0svOEj40= -cloud.google.com/go/datalabeling v0.10.0 h1:8Xk8Vvubg2lvvbezHvnT2jxnAyJS/rH1RHE202khpo4= -cloud.google.com/go/datalabeling v0.10.0/go.mod h1:2JlC6SFzPXTAjK8XSbdeRJYLjk6QV4+AyCxJZlc4Ju4= -cloud.google.com/go/dataplex v1.30.0 h1:VeGEANl3ywJ7txZ79BN1BlRluzfxxyv/CbOsh2u4cVQ= -cloud.google.com/go/dataplex v1.30.0/go.mod h1:GgV6b+1viq2nMtr+AUzKNUbaR+tKGxdhVaMN8TPPu0w= -cloud.google.com/go/dataproc/v2 v2.17.0 h1:jqH6LpQaMytLb7xW6zu6GoL9v/lYWcRXqXqndgT9mXQ= -cloud.google.com/go/dataproc/v2 v2.17.0/go.mod h1:lUY58QBxs6IIScAo9ZZKSOxx3imkHBxz6dow9f4fSRM= -cloud.google.com/go/dataqna v0.10.0 h1:7T25XR853o+1Z8cNuxYkHCUo4tIewzlfebcn6CCqNVg= -cloud.google.com/go/dataqna v0.10.0/go.mod h1:TJ6nt/jAilxNYzzbPMa4CsxO+l/9glfiNYb0Oarbvho= -cloud.google.com/go/datastore v1.22.0 h1:FOyx2Ag6ibD2wFkz9S8EiNrmBugia8pQOfpyJxi2yqA= -cloud.google.com/go/datastore v1.22.0/go.mod h1:aopSX+Whx0lHspWWBj+AjWt68/zjYsPfDe3LjWtqZg8= -cloud.google.com/go/datastream v1.16.0 h1:DN0VQZ+ZK8+UPjceA7U2zKmdLneMbzNJrEhBRnhsJjY= -cloud.google.com/go/datastream v1.16.0/go.mod h1:9gPqghndibXcAXA7Y+PdbkoyTkGT95UbuoXk1vNdt1g= -cloud.google.com/go/deploy v1.28.0 h1:DoWXcdsS9Vex40nM9yZ2YvRhtMC9DBS48QO1/Ivrwk4= -cloud.google.com/go/deploy v1.28.0/go.mod h1:1x7W4Ql3uvz/1ljPTxES33/D4ss8ro/Q5pyhOzXaXvA= -cloud.google.com/go/dialogflow v1.78.0 h1:OD/6lx2Bc/n/JVfJ9zBQcbd7hlFL1OvuVf9TmnTKyjk= -cloud.google.com/go/dialogflow v1.78.0/go.mod h1:H+SCvWiah4SNalfbG9P4wGYaxlyemLa8OFD/ljKSlRA= -cloud.google.com/go/dlp v1.30.0 h1:Xm60otZkf0aoz9qN44d6qQLaGYbgFSLw2g59pSrokdc= -cloud.google.com/go/dlp v1.30.0/go.mod h1:HVcPCYTniHItHfk8LqepllS6fGE0hmYCtGHvQE+wSpU= -cloud.google.com/go/documentai v1.44.0 h1:KHiXtPInCnnHrw78OW2KPBPm7TXo7YSGxQxvJBl0Ap8= -cloud.google.com/go/documentai v1.44.0/go.mod h1:ePqAOw0PvlezPoysTeP7TImdSzx52lErU3k1f4LrxWM= -cloud.google.com/go/domains v0.11.0 h1:cAmUWUOE2IMTE5SxpHVG0360LyIXexKH+OhsJMCtEv0= -cloud.google.com/go/domains v0.11.0/go.mod h1:jvi1QTJYy1w14K+3nBYjYJPaTHi1Zuv0y8wQkFqV8AE= -cloud.google.com/go/edgecontainer v1.5.0 h1:qRKqCm0Rfym19IQkwBsjoEV1No6Rf6Ja1MgHGAl0+zU= -cloud.google.com/go/edgecontainer v1.5.0/go.mod h1:5iCEsaMo8lw6wwJzt33fyfxKqpm/r1iMoXyFzAG9kHQ= -cloud.google.com/go/errorreporting v0.5.0 h1:jz06HUtXoJwBTop/KvQp+aB9U0uZMdSpeefcr2XaOdA= -cloud.google.com/go/errorreporting v0.5.0/go.mod h1:l7UT6tcjSmR37Pn8TjSrKYtoiPyOMAmWuCceowHMY+w= -cloud.google.com/go/essentialcontacts v1.8.0 h1:D0zAI6zxOTQt8KCnnfKSkT4u+ZzUTHA+cU384eQtHJU= -cloud.google.com/go/essentialcontacts v1.8.0/go.mod h1:/nlPxHm9vyDSZyWHB1CQYkRV44VEp8VjPlqoeGweApE= -cloud.google.com/go/eventarc v1.19.0 h1:K5LrgI6FR1lM+YRpa3s2LSG9DxHGmShdP+ULOm90LnQ= -cloud.google.com/go/eventarc v1.19.0/go.mod h1:xO4c0cMGNC47wZPJVe7gpABvOLJF+Wt6ze2n6KM70ak= -cloud.google.com/go/filestore v1.11.0 h1:gRdVpDwzWo98WMQLLEaMBx8b6S79DH3ixD5Lz0JsNCA= -cloud.google.com/go/filestore v1.11.0/go.mod h1:SOM0F8N/VIQaI8/KLbc1evVqX8S9KQmGdLYuj9HaQns= -cloud.google.com/go/firestore v1.21.0 h1:BhopUsx7kh6NFx77ccRsHhrtkbJUmDAxNY3uapWdjcM= -cloud.google.com/go/firestore v1.21.0/go.mod h1:1xH6HNcnkf/gGyR8udd6pFO4Z7GWJSwLKQMx/u6UrP4= -cloud.google.com/go/functions v1.20.0 h1:32Njh/dOxmhPclof7thv9UadyHtP+koeF8GzfrizRsY= -cloud.google.com/go/functions v1.20.0/go.mod h1:TW6jT0+yQsnI9ICkhJfz7HDFzdwtTaTOlKi1c9wQTqA= -cloud.google.com/go/gkebackup v1.9.0 h1:gSvNzCm7tg1d1ooevZlG/W4xfNkqRYVgfo/qcstPNDU= -cloud.google.com/go/gkebackup v1.9.0/go.mod h1:Rzxd7vr7h5Tsr9VHnexiK5LtFKGc+4LHRN9KI1osGXU= -cloud.google.com/go/gkeconnect v0.13.0 h1:oJLnuXoDXuM6jgxGwiRBGBZyyFW7COJFXeMfC6Nw+KA= -cloud.google.com/go/gkeconnect v0.13.0/go.mod h1:C06HGlhVhE6Og1QA9hQRO4wLyxItldAnq16kIQpG/ws= -cloud.google.com/go/gkehub v0.17.0 h1:m7ahnaSHGG8tK2JSjSCulLy/LFQK2rYYjqVHJZtikyY= -cloud.google.com/go/gkehub v0.17.0/go.mod h1:PAznKTCcvzLy2cJVb+tulfwaQUABlhYYRw5r3hMsgAI= -cloud.google.com/go/gkemulticloud v1.7.0 h1:cZ8I+QTY8zqC6oCtwyEh6U6MMA5rObd+AZV0fCLodPM= -cloud.google.com/go/gkemulticloud v1.7.0/go.mod h1:Cei8ayrpfxRDivJLCiQbFvmieBTldPf9sAd5vYdVvWI= -cloud.google.com/go/gsuiteaddons v1.8.0 h1:zb8CDRnMjr+3h97FZyVoiWAbMID3zExlp5i7kTAhfl8= -cloud.google.com/go/gsuiteaddons v1.8.0/go.mod h1:iObYcSP07RXsRaflrKn/o6hQ+Ygzem3Nd9PovowChAg= cloud.google.com/go/iam v1.8.0 h1:e5QOdN1zQ3MTWYtXIf2buX+jxqvo2sKqBCOLrteLd1M= cloud.google.com/go/iam v1.8.0/go.mod h1:IkWUaEeLK91WQqTKa/fi5xdHJbL49kv2j/vlAZQSJ+k= -cloud.google.com/go/iap v1.13.0 h1:R8DxLwieSdai17dwdUhR0jRznODC1OeU3IHTNaVM5I0= -cloud.google.com/go/iap v1.13.0/go.mod h1:/EMWDLYdDGelUxucj9drtP8SyY1L1RfzbqeUnWCoaNA= -cloud.google.com/go/ids v1.6.0 h1:CTbW76lKV1uJFPMyCCJMpdU989rsNrTRryjgG2ulGbo= -cloud.google.com/go/ids v1.6.0/go.mod h1:mSTbYgnZUQM3triYR96y+m07C4i7bAkMEZYbwDyTSTg= -cloud.google.com/go/iot v1.9.0 h1:xubUh2DW96j+L9St34vA2relRtcEHWAtcnVLIxZFHkg= -cloud.google.com/go/iot v1.9.0/go.mod h1:Yj14ToMHIR2+IIdoWY2ziYNKbFnrlV/YahmcFhxWQlQ= -cloud.google.com/go/kms v1.27.0 h1:iYYgoD0HJIqz35A+He1G0dS5qTQzQsDXFsyXwzkUCXM= -cloud.google.com/go/kms v1.27.0/go.mod h1:KPxrdf61iYEOZ86uPwR86muBpSik2y4Ion6e83fVl1Q= -cloud.google.com/go/language v1.15.0 h1:O38Z5z1X66gadN4wgUFQXR4qhfQfrSEbRXfBnizYaOM= -cloud.google.com/go/language v1.15.0/go.mod h1:4Q+axu8ZalG3KQKuoDisLKMoTxaM51fLOwLNOR8R4I4= -cloud.google.com/go/lifesciences v0.11.0 h1:FmUNRjG6+zulWHBuy1GPbV866xCcvpu6fjuzeN+3E2I= -cloud.google.com/go/lifesciences v0.11.0/go.mod h1:LIgB118ExLb5A4MwPuMB9U1i5S6vIa6D4aVz6iXhScQ= cloud.google.com/go/logging v1.14.0 h1:xpPpY8cVT6n9DgIRgrWyE+YEsGlO/994pWnbc7o5Eh4= cloud.google.com/go/logging v1.14.0/go.mod h1:jmI+Try/fZeOTOAer3wVYOuPf9WX9PyzhlSDoBAi4HM= cloud.google.com/go/longrunning v0.9.0 h1:0EzbDEGsAvOZNbqXopgniY0w0a1phvu5IdUFq8grmqY= cloud.google.com/go/longrunning v0.9.0/go.mod h1:pkTz846W7bF4o2SzdWJ40Hu0Re+UoNT6Q5t+igIcb8E= -cloud.google.com/go/managedidentities v1.8.0 h1:Txm/BvLwE5+8CJkXFahgCo9rr2Ant2igCbt/ipdLuYs= -cloud.google.com/go/managedidentities v1.8.0/go.mod h1:/YZXzgEYRzmYa/wLWr+5/2hXhg6wTJolpSCCoDDQ6II= -cloud.google.com/go/maps v1.31.0 h1:FQyJ5oEiOKWwroX+i/huJdJrs/4AOY/nxuqZBFPLnP4= -cloud.google.com/go/maps v1.31.0/go.mod h1:mWhSlc7r3FdTfh+9grRnmAy24yoHzQHSd9qPGeWFFe8= -cloud.google.com/go/mediatranslation v0.10.0 h1:VJldc3pFU4F+pUXo1PTBQ0UaoOplmvoK+w8cprv3Ejo= -cloud.google.com/go/mediatranslation v0.10.0/go.mod h1:zNtvcd8C5YEX7nW9dX0mOa4upqmzu8DGpuzgvvXb7mE= -cloud.google.com/go/memcache v1.12.0 h1:q3OVeL0nVjLU23QCz5Y2HRm8Y4eCU//8bSQ6PJyTmFY= -cloud.google.com/go/memcache v1.12.0/go.mod h1:LfD72uuBN2xkj307WIFn4am3x4nsfKoADA7sL5Ww2KU= -cloud.google.com/go/metastore v1.15.0 h1:6Te57v1ODRxqe5NQbzPBYo3+Xve8H/1bvS7i1ydlf+Q= -cloud.google.com/go/metastore v1.15.0/go.mod h1:iKjrQqKUFc5yw0VVQjh/rHU3ASW4GAQpSXqhMPn2cXQ= cloud.google.com/go/monitoring v1.26.0 h1:858kWP5akszJFeiWBSmQJIfS8vsCqkX9hjc7HPsv/tk= cloud.google.com/go/monitoring v1.26.0/go.mod h1:72NOVjJXHY/HBfoLT0+qlCZBT059+9VXLeAnL2PeeVM= -cloud.google.com/go/networkconnectivity v1.22.0 h1:wvBU0AjvnT0IhDm7KCsRsDKtA9jynV4gbNh0nsYzMcQ= -cloud.google.com/go/networkconnectivity v1.22.0/go.mod h1:E7lmnd1M04GM6ZjZPtWqYUWsJX40uHYlYpvqKJ5weqU= -cloud.google.com/go/networkmanagement v1.24.0 h1:BvQX5Tboxp6GuFX63UDR6PIHBdGCyYkgRdJt1ipoCqk= -cloud.google.com/go/networkmanagement v1.24.0/go.mod h1:rbVzje/eG7/w+iWIdbNMT25dU/89rA91X2iqI4cRniY= -cloud.google.com/go/networksecurity v0.12.0 h1:jClw7eryNWLBDlkZpo32iLt1a9XqTUsmOOu0ZxoQpkw= -cloud.google.com/go/networksecurity v0.12.0/go.mod h1:/xkjQdYYGHZGlpE+kF43RMJFx2Ak5FcUXEYXkBzuWHE= -cloud.google.com/go/notebooks v1.13.0 h1:+HvGq6flO4EeX3DxlaLvLc1rsavkqXt+BgKCLBYIURY= -cloud.google.com/go/notebooks v1.13.0/go.mod h1:ODeLG8Kzaxsh/jaQVGRzPj/5qTyrxetHfp4qBp4IytU= -cloud.google.com/go/optimization v1.8.0 h1:kXx8MkReDE1KEZmBckhDVaKTKtfUBjPweRkSVbu1kWE= -cloud.google.com/go/optimization v1.8.0/go.mod h1:JjunBI7Gg+rI1kOu5Qhtk8xetbLKeAsRcxpOelFL1HQ= -cloud.google.com/go/orchestration v1.12.0 h1:WoAXCwjP6P5/eBQZsRxyn9945VlZNWLAMi0taR4AHig= -cloud.google.com/go/orchestration v1.12.0/go.mod h1:z5NJIg6gM6mDcvnjNeUXhQYr08cBCeuQ3l3OCedGZ1A= -cloud.google.com/go/orgpolicy v1.16.0 h1:MdF2ebs6H4CoxgrtPQ7XDvE1ACIeSQDY2a1/QwVgqvA= -cloud.google.com/go/orgpolicy v1.16.0/go.mod h1:l88jhhDM/KYN0FJF87m5Gub1qcOFkN94efA2uhy+U0s= -cloud.google.com/go/osconfig v1.17.0 h1:e4EhWz5w7S/7fJ+rhGtyWpSls0Bxr5sxXc2PGWjiI/o= -cloud.google.com/go/osconfig v1.17.0/go.mod h1:iveYW1fYygItJeJwbQ/fkzYAzLEbXOQnr7+eBmH9MJ0= -cloud.google.com/go/oslogin v1.15.0 h1:UtRf8tM9qzobfJsNysaGpegVcPGpwzY6+TRU64kac28= -cloud.google.com/go/oslogin v1.15.0/go.mod h1:hZPTJtRwb0f2SNvqOVqb2QoF6z1C1s6yvSx23jUnnFk= -cloud.google.com/go/phishingprotection v0.10.0 h1:reHzRaFuBwFd8FxaZNJqF+j4oPLHtLPRsEqngejpE7s= -cloud.google.com/go/phishingprotection v0.10.0/go.mod h1:6SxFjbwfY0UPbX8px45qFuejcqo6xaLliYBqnSNUYQs= -cloud.google.com/go/policytroubleshooter v1.12.0 h1:HXSV+V0EJpUxoNx9t24y4hycTUfXKbCESpgrfPDoAkk= -cloud.google.com/go/policytroubleshooter v1.12.0/go.mod h1:9YkZq/rC3wMBmBW3bhPux8haEss0t0C8e1xxs1kawws= -cloud.google.com/go/privatecatalog v0.11.0 h1:bVomBlOXLYcQxFPL04XJCPIi83oqTtkOKyxbAol6flM= -cloud.google.com/go/privatecatalog v0.11.0/go.mod h1:2Y+RuSNZWsM+tfHVI0/Lx0AbRW5jsliIr771Z/vvR/0= -cloud.google.com/go/pubsub v1.50.2 h1:54Up97HnThdP4H8jjWJSSQ/mnYG2EKon7ZSNETRq0tM= -cloud.google.com/go/pubsub v1.50.2/go.mod h1:jyCWeZdGFqd4mitSsBERnJcpqaHBsxQoPkNvjj4sp0w= -cloud.google.com/go/pubsub/v2 v2.5.1 h1:+TwXJr78P9RrMV3S8lKHIhJo2E99jI7ta65e+ujJjts= -cloud.google.com/go/pubsub/v2 v2.5.1/go.mod h1:Pd+qeabMX+576vQJhTN7TelE4k6kJh15dLU/ptOQ/UA= -cloud.google.com/go/pubsublite v1.8.2 h1:jLQozsEVr+c6tOU13vDugtnaBSUy/PD5zK6mhm+uF1Y= -cloud.google.com/go/pubsublite v1.8.2/go.mod h1:4r8GSa9NznExjuLPEJlF1VjOPOpgf3IT6k8x/YgaOPI= -cloud.google.com/go/recaptchaenterprise/v2 v2.22.0 h1:UCffgZ9HiSB0d6UZdLrZcXpKcptboGd5YUZ/H72cslo= -cloud.google.com/go/recaptchaenterprise/v2 v2.22.0/go.mod h1:3jHDVYA4b/hlrISmTYjk4cXZWZLk4PenhH+NyrlYhRQ= -cloud.google.com/go/recommendationengine v0.10.0 h1:NshsCTaTXs3mz99TJ8Kq3N/MtjxALrXTobu8xsjF/jc= -cloud.google.com/go/recommendationengine v0.10.0/go.mod h1:548mK1fxhG12vg4kHrLfWKX9BC7fsq2udo1YsED4L2s= -cloud.google.com/go/recommender v1.14.0 h1:sbpP+ztzYy8ELvM4YOlC7SUIzJeJ1qClyz00iX6Q6hg= -cloud.google.com/go/recommender v1.14.0/go.mod h1:21EuILd1jr+9X/aHcf7it+nWvB6VH+/ALz2vPqm4Dog= -cloud.google.com/go/redis v1.19.0 h1:2ZoK/yOVAHFuRduQQR931BccLw1jd5CvjdDAI+06QTc= -cloud.google.com/go/redis v1.19.0/go.mod h1:vdL4FIUmY5DFGORAb/iBrpJWoWxygEpT9Ls8wK+8bsk= -cloud.google.com/go/resourcemanager v1.11.0 h1:9SJ/sfpUnxchKOthw4p7sXycLPjkWh2PaHHOekoMvs8= -cloud.google.com/go/resourcemanager v1.11.0/go.mod h1:jBdKCDtskipgmN1BC9wJnBzlGG7HpVIQ60cT9LEMgeQ= -cloud.google.com/go/resourcesettings v1.8.3 h1:13HOFU7v4cEvIHXSAQbinF4wp2Baybbq7q9FMctg1Ek= -cloud.google.com/go/resourcesettings v1.8.3/go.mod h1:BzgfXFHIWOOmHe6ZV9+r3OWfpHJgnqXy8jqwx4zTMLw= -cloud.google.com/go/retail v1.27.0 h1:ISw0lymD83NJ5Cf2DRz+bhhvXNPk8QmfMXoHnFYpjZg= -cloud.google.com/go/retail v1.27.0/go.mod h1:aDziApdysNZudAlkRvbPv4pdPwR/hc3sPsYWCpeJOnc= -cloud.google.com/go/run v1.17.0 h1:Ffdtcg+qjKmZFDuRwGOkgmd1Bkt2AHiMx4wSIxZYrtM= -cloud.google.com/go/run v1.17.0/go.mod h1:24NIu/ueXZFL3OyKJfkhp1j3VJDAEukuclpBSiL9pa0= -cloud.google.com/go/scheduler v1.12.0 h1:WenZ0uenlvQlTggmlk5AEWEpb2EZjZYKN6TGywx1JBE= -cloud.google.com/go/scheduler v1.12.0/go.mod h1:A11HxINAugN6GqEYx36OVcc78dL6UHTT+1YXPZj2KBI= -cloud.google.com/go/secretmanager v1.17.0 h1:rji2m9dikfOxUvYxgJ5XpSvDtwqjouqKFAPp4Hgfyto= -cloud.google.com/go/secretmanager v1.17.0/go.mod h1:ojzpR7KA2il9qcmBYaysgHsclj8nMcCL/Hc+WYxUsGA= -cloud.google.com/go/security v1.20.0 h1:YTfgZ9X21w/kQs4ZQM/sl3ZsCkoBMZq6sZIpHvtWSYo= -cloud.google.com/go/security v1.20.0/go.mod h1:a/4VUEX2QdSolTbtqlNoCGGyBHc198XEvvBtaM14SKM= -cloud.google.com/go/securitycenter v1.40.0 h1:9qfvB1qeQt69VDUJDNNhImPElcfdBdNgMwTWyD2332U= -cloud.google.com/go/securitycenter v1.40.0/go.mod h1:zxPwtKVAu6kBRQDYWFi6MdDmT72mI/N4CdTs77ktCjQ= -cloud.google.com/go/servicedirectory v1.13.0 h1:j+RQxDmE8RvG0L7WUgFFGb/VOjrZOK79FqUaT48gXys= -cloud.google.com/go/servicedirectory v1.13.0/go.mod h1:W1BVLsabUKHRkU/pVf1xY7v4JRIfZ7ly6+GoJyoCOeQ= -cloud.google.com/go/shell v1.9.0 h1:dqqLQkvtWl1xbbmCjSqNdmIGh5LV+VErieaqBw4vxD0= -cloud.google.com/go/shell v1.9.0/go.mod h1:baiOHQUhZxzUL3DhLDdE0F9puPPmubxtTRfsgL96WpQ= -cloud.google.com/go/spanner v1.89.0 h1:r3h5Z5RA8JRPf3HCvA6ujNhREIMhPY+MrDL9mkY8jS0= -cloud.google.com/go/spanner v1.89.0/go.mod h1:okNuxnp1wdPaVoM5M28Al2irKZLkHhZ2Z+DW6/ZJWGw= -cloud.google.com/go/speech v1.31.0 h1:+K91seSmxnmk7lKzzUjn7H0NwMfs4BBfLBvJgeHGl6U= -cloud.google.com/go/speech v1.31.0/go.mod h1:8U80+TvXb17d7L/5jDLC3BGGKTrVqR7jFX0SvTkXs30= cloud.google.com/go/storage v1.62.0 h1:w2pQJhpUqVerMON45vatE2FpCYsNTf7OHjkn6ux5mMU= cloud.google.com/go/storage v1.62.0/go.mod h1:T5hz3qzcpnxZ5LdKc7y8Tw7lh4v9zeeVyrD/cLJAzZU= -cloud.google.com/go/storagetransfer v1.14.0 h1:03hl9UR63xarS3+oq+uXRdCzHzxYttsv8df5tTAXbwk= -cloud.google.com/go/storagetransfer v1.14.0/go.mod h1:AXV3Zq+8CDDYa5VlFB4xCnve/LnuHRnCKh2ZP8bVFm4= -cloud.google.com/go/talent v1.9.0 h1:Rze0tmvOPs2VMFx2wMVUY7iZRyf9DNt9/LNMv25k7UE= -cloud.google.com/go/talent v1.9.0/go.mod h1:NW4daUY2mJAFrQ5C5+LrR+RoOyHgjQXKXDhhMxvpe9w= -cloud.google.com/go/texttospeech v1.17.0 h1:zwqHUyaxtzsmcIYMAygBHFuC/5/C31iBhRTvFYe8mvM= -cloud.google.com/go/texttospeech v1.17.0/go.mod h1:qXUktcF2pHd2Gh9GcY2NFEtZPnIeC+kKVPC3wes7LSk= -cloud.google.com/go/tpu v1.9.0 h1:cOp2EVD5yXJ3R3TRbeep3EpT68unJXHsPY8Sw6aaPYg= -cloud.google.com/go/tpu v1.9.0/go.mod h1:MeJ0QXume/iLq+DEk9LcD62l6HynG5KZdW38pOkF7RU= cloud.google.com/go/trace v1.12.0 h1:XvWHYfr9q88cX4pZyou6qCcSagnuASyUq2ej1dB6NzQ= cloud.google.com/go/trace v1.12.0/go.mod h1:TOYfyeoyCGsSH0ifXD6Aius24uQI9xV3RyvOdljFIyg= -cloud.google.com/go/translate v1.13.0 h1:AX+qllhStJOOs/nWvAJUUo9eucQtmtW3KqpYM8MOfBQ= -cloud.google.com/go/translate v1.13.0/go.mod h1:gNfroOEKGH2eAu1hm24Ex8E4e2bTiUDkWZWsfuMVGj0= -cloud.google.com/go/video v1.28.0 h1:OtwxjeUillhbrX75Rf2SBL4B3Lk6hfKir4eb3ttkIMs= -cloud.google.com/go/video v1.28.0/go.mod h1:ZjAJB+69e6A8fTr9ut+agY8gyWQP4+L+DLgSLO14RqE= -cloud.google.com/go/videointelligence v1.13.0 h1:VabCmI0umYSHHlHMBQQNZepD6Hw7ty7tZXhNmkGo244= -cloud.google.com/go/videointelligence v1.13.0/go.mod h1:jZ25omw+UDsubcHHyzKFR/h1lb+6NrqCoFTaN2rAtD0= -cloud.google.com/go/vision/v2 v2.10.0 h1:g3E+IOSxkKtWOx75nydgXcjGsaYh0KSJDpCc6p5+fA8= -cloud.google.com/go/vision/v2 v2.10.0/go.mod h1:zyF6oZkvg4S0yCPAUcCVLKs+x2xqTBU0w1CI9+dlTA4= -cloud.google.com/go/vmmigration v1.11.0 h1:qcQQNg1zZe060ZUTF8E/syCBEyiQYLIvbvD+oR5oy2s= -cloud.google.com/go/vmmigration v1.11.0/go.mod h1:C8eGJ9LJE6KSInDCLQY349NK2KpebPIaahR/fin/xJQ= -cloud.google.com/go/vmwareengine v1.4.0 h1:FyUm4IWc/LTjifBizePFXR0lsAGFoVXFA6NkuZIB9sc= -cloud.google.com/go/vmwareengine v1.4.0/go.mod h1:fuz8B0EIb8CwioqmBSRCTZ4MQDT94Q0OiF4pPE/57Uc= -cloud.google.com/go/vpcaccess v1.9.0 h1:EL8kWVaEZKg9VIEnX4+HV4dj/hyhBsv2UxyDw5zcfRs= -cloud.google.com/go/vpcaccess v1.9.0/go.mod h1:AYFkpistDjSc9FooHo3ezICbRsDoIyyoAbeXD1rDFOE= -cloud.google.com/go/webrisk v1.12.0 h1:LY7OFgg64Hrc/mP5mRv5jLwPBpbm+nUBQKeR+Hizua4= -cloud.google.com/go/webrisk v1.12.0/go.mod h1:oLNOZ1L/abccgx/OHi6us3YKHTsxYZKYd4eWv+hyvJQ= -cloud.google.com/go/websecurityscanner v1.8.0 h1:Eq37QFxjWuy6wieo6+nopVYCUkN/kdjTZdD1D4ZHzNM= -cloud.google.com/go/websecurityscanner v1.8.0/go.mod h1:2FS2WQ+RaL6O3/HaGBl9JHkSbhKLRulmRNEHRS15Plw= -cloud.google.com/go/workflows v1.15.0 h1:ZtsGSM5zO9Is/k3Jrjdw5XZZTaRzcuQcSTYymI5fB0g= -cloud.google.com/go/workflows v1.15.0/go.mod h1:2UOYVoNLYsroRbG3Ok6eBliFPThf5ronyqlD64NFLx8= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28= @@ -267,7 +41,6 @@ github.com/Azure/go-autorest/autorest/adal v0.9.24 h1:BHZfgGsGwdkHDyZdtQRQk1WeUd github.com/Azure/go-autorest/autorest/adal v0.9.24/go.mod h1:7T1+g0PYFmACYW5LlG2fcoPiPlFHjClyRGL7dRlP5c8= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= @@ -277,7 +50,6 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.7.1 h1:edShSHV3DV90+kt+CMaEXEzR9QF7wFrPJxVGz2blMIU= github.com/AzureAD/microsoft-authentication-library-for-go v1.7.1/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= -github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ClickHouse/ch-go v0.71.0 h1:bUdZ/EZj/LcVHsMqaRUP2holqygrPWQKeMjc6nZoyRM= github.com/ClickHouse/ch-go v0.71.0/go.mod h1:NwbNc+7jaqfY58dmdDUbG4Jl22vThgx1cYjBw0vtgXw= @@ -293,10 +65,6 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapp github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.56.0/go.mod h1:6ZZMQhZKDvUvkJw2rc+oDP90tMMzuU/J+5HG1ZmPOmE= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= -github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= -github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= -github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro= github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/antchfx/xmlquery v1.5.1 h1:T9I4Ns1EXiWHy0IqKupGhnfTQtJwlGrpXtauYOoNv78= @@ -351,8 +119,6 @@ github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk= github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -361,22 +127,12 @@ github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= -github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw= -github.com/connesc/cipherio v0.2.1/go.mod h1:ukY0MWJDFnJEbXMQtOcn2VmTpRfzcTz4OoVrWGGJZcA= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= -github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= -github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= -github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= -github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= -github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -390,8 +146,6 @@ github.com/djherbis/buffer v1.2.0 h1:PH5Dd2ss0C7CRRhQCZ2u7MssF+No9ide8Ye71nPHcrQ github.com/djherbis/buffer v1.2.0/go.mod h1:fjnebbZjCUpPinBRD+TDwXSOeNQ7fPQWLfGQqiAiUyE= github.com/djherbis/nio/v3 v3.0.1 h1:6wxhnuppteMa6RHA4L81Dq7ThkZH8SwnDzXDYy95vB4= github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmWgZxOcmg= -github.com/dmarkham/enumer v1.6.3 h1:B4aV4OsfzbrS5rvjILt4mMjiWBA//cKxJUMsvHZ8mEI= -github.com/dmarkham/enumer v1.6.3/go.mod h1:DyjXaqCglj4GhELF73oWiparNkYkXvmOBLza/o4kO74= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= @@ -400,14 +154,9 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= -github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780 h1:tFh1tRc4CA31yP6qDcu+Trax5wW5GuMxvkIba07qVLY= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA= github.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= -github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= -github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= @@ -418,7 +167,6 @@ github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMD github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -440,16 +188,12 @@ github.com/go-zookeeper/zk v1.0.4 h1:DPzxraQx7OrPyXq2phlGlNSIyWEsAox0RJmjTseMV6I github.com/go-zookeeper/zk v1.0.4/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ= github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= -github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= @@ -461,8 +205,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-pkcs11 v0.3.0 h1:PVRnTgtArZ3QQqTGtbtjtnIkzl2iY2kt24yqbrf7td8= -github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0= github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU= @@ -482,8 +224,6 @@ github.com/googleapis/gax-go/v2 v2.21.0 h1:h45NjjzEO3faG9Lg/cFrBh2PgegVVgzqKzuZl github.com/googleapis/gax-go/v2 v2.21.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -491,28 +231,13 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= -github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= -github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= -github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg= github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI= github.com/jolestar/go-commons-pool/v2 v2.1.2 h1:E+XGo58F23t7HtZiC/W6jzO2Ux2IccSH/yx4nD+J1CM= github.com/jolestar/go-commons-pool/v2 v2.1.2/go.mod h1:r4NYccrkS5UqP1YQI1COyTZ9UjPJAAGTUxzcsK1kqhY= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= @@ -520,7 +245,6 @@ github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXw github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -529,7 +253,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -538,10 +261,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak= github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= -github.com/lyft/protoc-gen-star/v2 v2.0.4 h1:JDlNKttNIRd68AAIychs0AqEpO8/I/WYi01OQ7Raw6Q= -github.com/lyft/protoc-gen-star/v2 v2.0.4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= -github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= -github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= @@ -556,30 +275,14 @@ github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60V github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615 h1:/mD+ABZyXD39BzJI2XyRJlqdZG11gXFo0SSynL+OFeU= -github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= -github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= -github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= -github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= -github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= -github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.7.0 h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY/JU= -github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= @@ -587,8 +290,6 @@ github.com/mozillazg/go-httpheader v0.4.0 h1:aBn6aRXtFzyDLZ4VIRLsZbbJloagQfMnCiY github.com/mozillazg/go-httpheader v0.4.0/go.mod h1:PuT8h0pw6efvp8ZeUec1Rs7dwjK08bt6gKSReGMqtdA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nwaples/rardecode/v2 v2.2.2 h1:/5oL8dzYivRM/tqX9VcTSWfbpwcbwKG1QtSJr3b3KcU= github.com/nwaples/rardecode/v2 v2.2.2/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -599,12 +300,8 @@ github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= -github.com/pascaldekloe/name v1.0.1 h1:9lnXOHeqeHHnWLbKfH6X98+4+ETVqFqxN09UXSjcMb0= -github.com/pascaldekloe/name v1.0.1/go.mod h1:Z//MfYJnH4jVpQ9wkclwu2I2MkHmXTlT9wR5UZScttM= github.com/paulmach/orb v0.13.0 h1:r7n7mQGGF+cj/CbcivEj9J3HGK+XR+yXnvzRdq9saIw= github.com/paulmach/orb v0.13.0/go.mod h1:6scRWINywA2Jf05dcjOfLfxrUIMECvTSG2MVbRLxu/k= -github.com/paulmach/protoscan v0.2.1 h1:rM0FpcTjUMvPUNk2BhPJrreDKetq43ChnL+x1sRg8O8= -github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY= github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -634,28 +331,15 @@ github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 h1:d github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285/go.mod h1:fxIDly1xtudczrZeOOlfaUvd2OPb2qZAPuWdU2BsBTk= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 h1:18kd+8ZUlt/ARXhljq+14TwAoKa61q6dX8jtwOf6DH8= github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA= -github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= -github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI= github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc= -github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= -github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= -github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0= github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= -github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs= -github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/shoenig/go-m1cpu v0.2.1 h1:yqRB4fvOge2+FyRXFkXqsyMoqPazv14Yyy+iyccT2E4= github.com/shoenig/go-m1cpu v0.2.1/go.mod h1:KkDOw6m3ZJQAPHbrzkZki4hnx+pDRR1Lo+ldA56wD5w= github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk= @@ -666,10 +350,6 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -686,16 +366,11 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563 h1:2VDxTtn9dAqI2DnnvB9fXpPE4DblOmquyzmN2zxTD8A= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563 h1:FoX+MK4vHThvPO6FbP5q98zD8S3n+d5+DbtK7skl++c= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0= github.com/tencentyun/cos-go-sdk-v5 v0.7.73 h1:uFfgp1A7cQaAGR6QP9DsIkoEQ67b8ewj5r1RV6XB540= github.com/tencentyun/cos-go-sdk-v5 v0.7.73/go.mod h1:STbTNaNKq03u+gscPEGOahKzLcGSYOj6Dzc5zNay7Pg= -github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20250515025012-e0eec8a5d123 h1:OBdxZoM27gCwvBiXfdnzoyT0rSOYktwm0L6a3ArBEZI= github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20250515025012-e0eec8a5d123/go.mod h1:b18KQa4IxHbxeseW1GcZox53d7J0z39VNONTxvvlkXw= -github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU= -github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= @@ -707,28 +382,17 @@ github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ= github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo= -github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= -github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/xyproto/gionice v1.3.0 h1:v0X22Iduy+lplGT735pKRc6c550vvXYXvgXy0ZkA+qM= github.com/xyproto/gionice v1.3.0/go.mod h1:bXnNfrv26yrsvmIXmTPztA+/MJ6wDjKv4l5can8P0cw= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc= github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= -github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= -go.etcd.io/gofail v0.2.0 h1:p19drv16FKK345a09a1iubchlw/vmRuksmRzgBIGjcA= -go.etcd.io/gofail v0.2.0/go.mod h1:nL3ILMGfkXTekKI3clMBNazKnjUZjYLKmBHzsVAnC1o= -go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= -go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU= @@ -757,10 +421,6 @@ go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpu go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= -go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -830,7 +490,6 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= 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= @@ -864,35 +523,25 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= -golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.275.0 h1:vfY5d9vFVJeWEZT65QDd9hbndr7FyZ2+6mIzGAh71NI= google.golang.org/api v0.275.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20260406210006-6f92a3bedf2d h1:N1Ec54vZnIPd7MnxRiYLW+oY4fDR4BOS/LrssdD9+ek= google.golang.org/genproto v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:c2hJ1grtnH0xUiEKGDGkjGNTJ1Hy2LrblyKOHF0sqRM= google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d h1:/aDRtSZJjyLQzm75d+a1wOJaqyKBMvIAfeQmoa3ORiI= google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:etfGUgejTiadZAUaEP14NP97xi1RGeawqkjDARA/UOs= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20260319201613-d00831a3d3e7 h1:6jJ8xNMxB3mmH3HsxEMPjJU+WeFOiwBJ+cLm60OvSZs= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:6TABGosqSqU2l1+fJ3jdvOYPPVryeKybxYF0cCZkTBE= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= -google.golang.org/grpc/examples v0.0.0-20250407062114-b368379ef8f6 h1:ExN12ndbJ608cboPYflpTny6mXSzPrDLh0iTaVrRrds= -google.golang.org/grpc/examples v0.0.0-20250407062114-b368379ef8f6/go.mod h1:6ytKWczdvnpnO+m+JiG9NjEDzR1FJfsnmJdG7B8QVZ8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/acvpwrapper/README.md b/pkg/acvpwrapper/README.md new file mode 100644 index 000000000..4542f16ae --- /dev/null +++ b/pkg/acvpwrapper/README.md @@ -0,0 +1,129 @@ +# ACVP Wrapper Repro Guide + +This folder contains the embedded ACVP wrapper used by `clickhouse-backup-acvp` +and `clickhouse-backup acvp`. + +The tracked config for public-Go-API validation is: + +- `pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json` + +It intentionally excludes `ML-KEM` and `ML-DSA` vector suites because those +ACVP paths rely on internal Go crypto APIs that are not publicly exposed in +Go 1.26. + +## Compliance Scope + +- This wrapper is a reproducibility harness for ACVP expected-output tests. +- It is **not** itself a CMVP certificate artifact. +- The compliance-relevant cryptographic implementation is Go's native + `crypto/internal/fips140/...` module when run with `GODEBUG=fips140=on` + (or `only`), per Go's FIPS documentation. + +## Certificate And Security Policy Context + +- Go's official FIPS status and validation lifecycle is documented here: + [FIPS 140-3 Compliance (Go docs)](https://go.dev/doc/security/fips140). +- As documented by Go, module validations are tracked in CMVP lists; at the time + of writing, v1.26.0 is listed as "Implementation Under Test" and v1.0.0 is + listed as "In Process" (with CAVP certificate A6650). +- Go's published FIPS documentation and blog post are the authoritative public + references for certificate/security-policy context: + - [The FIPS 140-3 Go Cryptographic Module (Go blog)](https://go.dev/blog/fips140) + - [CMVP Modules In Process List](https://csrc.nist.gov/Projects/cryptographic-module-validation-program/modules-in-process/modules-in-process-list) + - [CMVP Validated Modules Search (Go Cryptographic Module)](https://csrc.nist.gov/projects/cryptographic-module-validation-program/validated-modules/search?SearchMode=Basic&ModuleName=Go+Cryptographic+Module&CertificateStatus=Active&ValidationYear=0) + - [CAVP Certificate A6650](https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/details?validation=39260) + +## Reference Traceability (Claim -> Source) + +| Claim | Source | +| --- | --- | +| Go supports native FIPS 140-3 mode in the standard toolchain and documents `GODEBUG=fips140=...` behavior. | [Go FIPS 140-3 compliance docs](https://go.dev/doc/security/fips140) | +| The relevant cryptographic implementation is Go's `crypto/internal/fips140/...` module in FIPS mode. | [Go FIPS 140-3 compliance docs](https://go.dev/doc/security/fips140) | +| Go module-validation lifecycle/status is tracked via CMVP lists (Validated / In Process / IUT). | [Go FIPS 140-3 compliance docs](https://go.dev/doc/security/fips140), [CMVP MIP list](https://csrc.nist.gov/Projects/cryptographic-module-validation-program/modules-in-process/modules-in-process-list), [CMVP validated modules search](https://csrc.nist.gov/projects/cryptographic-module-validation-program/validated-modules/search?SearchMode=Basic&ModuleName=Go+Cryptographic+Module&CertificateStatus=Active&ValidationYear=0) | +| Go Cryptographic Module v1.0.0 has CAVP certificate A6650 and entered CMVP in-process workflow. | [Go FIPS blog](https://go.dev/blog/fips140), [CAVP A6650](https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/details?validation=39260), [CMVP MIP list](https://csrc.nist.gov/Projects/cryptographic-module-validation-program/modules-in-process/modules-in-process-list) | +| Pins used by this repo's ACVP repro (`baaf868e6e8f`, `d893de8b8b1c`) come from upstream Go `fips140test` ACVP test constants. | Upstream Go source: `src/crypto/internal/fips140test/acvp_test.go` (constants `bsslVersion` and `goAcvpVersion`) | +| This repo's tracked config is a public-API-only derivative of Go's v1.26 ACVP config. | Upstream Go source: `src/crypto/internal/fips140test/acvp_test_fips140v1.26.config.json`, local tracked file `pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json` | +| The reproducibility result target in this repo is `38 ACVP tests matched expectations`. | Local reproducibility flow in `pkg/acvpwrapper/run.sh` and command output from `check_expected.go` | + +## Pinned Version Provenance + +Pins used by `run.sh` are taken from upstream Go's ACVP test setup for the +v1.26 stream: + +- `boringssl` commit: `baaf868e6e8f` + - From `bsslVersion = v0.0.0-20251111011041-baaf868e6e8f` in Go + `crypto/internal/fips140test/acvp_test.go`. +- `acvp-testdata` commit: `d893de8b8b1c` + - From `goAcvpVersion = v0.0.0-20251201200548-d893de8b8b1c` in the same Go test. +- Upstream config source: + - `src/crypto/internal/fips140test/acvp_test_fips140v1.26.config.json` + in Go source. +- This repo's tracked config: + - `pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json` + - Derived from Go's v1.26 config, with `ML-KEM` and `ML-DSA` suites removed + to keep the run strictly on public Go crypto APIs. + +## Reproduce The Current Result + +Run from the repository root. + +### One-command repro + +```bash +bash pkg/acvpwrapper/run.sh +``` + +Expected output includes: + +- `38 ACVP tests matched expectations` + +### Manual step-by-step + +### 1) Build the wrapper binary + +```bash +docker run --rm \ + -v "$PWD:/work" \ + -w /work \ + golang:1.26-alpine \ + sh -lc 'export PATH=$PATH:/usr/local/go/bin && CGO_ENABLED=0 go build -o clickhouse-backup ./cmd/clickhouse-backup && ln -sf clickhouse-backup clickhouse-backup-acvp' +``` + +### 2) Fetch pinned upstream inputs + +```bash +rm -rf /tmp/boringssl /tmp/acvp-testdata +git clone https://boringssl.googlesource.com/boringssl /tmp/boringssl +git -C /tmp/boringssl checkout baaf868e6e8f + +git clone https://github.com/geomys/acvp-testdata /tmp/acvp-testdata +git -C /tmp/acvp-testdata checkout d893de8b8b1c +``` + +### 3) Build pinned `acvptool` + +```bash +docker run --rm \ + -v /tmp/boringssl:/src \ + -w /src \ + golang:1.26-alpine \ + sh -lc 'export PATH=$PATH:/usr/local/go/bin && go build -o /src/acvptool-pinned ./util/fipstools/acvp/acvptool' +``` + +### 4) Run the expected-output check + +```bash +docker run --rm \ + -e ACVP_WRAPPER=1 \ + -e GODEBUG=fips140=on \ + -v "$PWD:/work" \ + -v /tmp/boringssl:/tmp/boringssl:ro \ + -v /tmp/acvp-testdata:/tmp/acvp-testdata:rw \ + -w /tmp/acvp-testdata \ + golang:1.26-alpine \ + sh -lc 'export PATH=$PATH:/usr/local/go/bin && go run /tmp/boringssl/util/fipstools/acvp/acvptool/test/check_expected.go -tool /tmp/boringssl/acvptool-pinned -module-wrappers go:/work/clickhouse-backup-acvp -tests /work/pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json' +``` + +Expected output includes: + +- `38 ACVP tests matched expectations` diff --git a/pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json b/pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json new file mode 100644 index 000000000..f5275cbe9 --- /dev/null +++ b/pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json @@ -0,0 +1,55 @@ +[ + {"Wrapper": "go", "In": "vectors/SHA2-224.bz2", "Out": "expected/SHA2-224.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA2-256.bz2", "Out": "expected/SHA2-256.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA2-384.bz2", "Out": "expected/SHA2-384.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA2-512.bz2", "Out": "expected/SHA2-512.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA2-512-224.bz2", "Out": "expected/SHA2-512-224.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA2-512-256.bz2", "Out": "expected/SHA2-512-256.bz2"}, + + {"Wrapper": "go", "In": "vectors/SHA3-224.bz2", "Out": "expected/SHA3-224.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA3-256.bz2", "Out": "expected/SHA3-256.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA3-384.bz2", "Out": "expected/SHA3-384.bz2"}, + {"Wrapper": "go", "In": "vectors/SHA3-512.bz2", "Out": "expected/SHA3-512.bz2"}, + + {"Wrapper": "go", "In": "vectors/SHAKE-128.bz2", "Out": "expected/SHAKE-128.bz2"}, + {"Wrapper": "go", "In": "vectors/SHAKE-256.bz2", "Out": "expected/SHAKE-256.bz2"}, + {"Wrapper": "go", "In": "vectors/cSHAKE-128.bz2", "Out": "expected/cSHAKE-128.bz2"}, + {"Wrapper": "go", "In": "vectors/cSHAKE-256.bz2", "Out": "expected/cSHAKE-256.bz2"}, + + {"Wrapper": "go", "In": "vectors/HMAC-SHA2-224.bz2", "Out": "expected/HMAC-SHA2-224.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA2-256.bz2", "Out": "expected/HMAC-SHA2-256.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA2-384.bz2", "Out": "expected/HMAC-SHA2-384.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA2-512.bz2", "Out": "expected/HMAC-SHA2-512.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA2-512-224.bz2", "Out": "expected/HMAC-SHA2-512-224.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA2-512-256.bz2", "Out": "expected/HMAC-SHA2-512-256.bz2"}, + + {"Wrapper": "go", "In": "vectors/KDA.bz2", "Out": "expected/KDA.bz2"}, + + {"Wrapper": "go", "In": "vectors/HMAC-SHA3-224.bz2", "Out": "expected/HMAC-SHA3-224.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA3-256.bz2", "Out": "expected/HMAC-SHA3-256.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA3-384.bz2", "Out": "expected/HMAC-SHA3-384.bz2"}, + {"Wrapper": "go", "In": "vectors/HMAC-SHA3-512.bz2", "Out": "expected/HMAC-SHA3-512.bz2"}, + + {"Wrapper": "go", "In": "vectors/PBKDF.bz2", "Out": "expected/PBKDF.bz2"}, + + {"Wrapper": "go", "In": "vectors/hmacDRBG.bz2", "Out": "expected/hmacDRBG.bz2"}, + + {"Wrapper": "go", "In": "vectors/ctrDRBG.bz2", "Out": "expected/ctrDRBG.bz2"}, + + {"Wrapper": "go", "In": "vectors/EDDSA.bz2", "Out": "expected/EDDSA.bz2"}, + + {"Wrapper": "go", "In": "vectors/ECDSA.bz2", "Out": "expected/ECDSA.bz2"}, + + {"Wrapper": "go", "In": "vectors/ACVP-AES-CBC.bz2", "Out": "expected/ACVP-AES-CBC.bz2"}, + {"Wrapper": "go", "In": "vectors/ACVP-AES-CTR.bz2", "Out": "expected/ACVP-AES-CTR.bz2"}, + {"Wrapper": "go", "In": "vectors/ACVP-AES-GCM.bz2", "Out": "expected/ACVP-AES-GCM.bz2"}, + + {"Wrapper": "go", "In": "vectors/CMAC-AES.bz2", "Out": "expected/CMAC-AES.bz2"}, + + {"Wrapper": "go", "In": "vectors/TLS-v1.2.bz2", "Out": "expected/TLS-v1.2.bz2"}, + {"Wrapper": "go", "In": "vectors/TLS-v1.3.bz2", "Out": "expected/TLS-v1.3.bz2"}, + + {"Wrapper": "go", "In": "vectors/kdf-components.bz2", "Out": "expected/kdf-components.bz2"}, + + {"Wrapper": "go", "In": "vectors/RSA.bz2", "Out": "expected/RSA.bz2"} +] diff --git a/pkg/acvpwrapper/doc.go b/pkg/acvpwrapper/doc.go new file mode 100644 index 000000000..cae45afb4 --- /dev/null +++ b/pkg/acvpwrapper/doc.go @@ -0,0 +1,8 @@ +// Package acvpwrapper implements ACVP module-wrapper protocol handlers that +// are embedded into the clickhouse-backup binary. +// +// Files are split by concern: +// - wrapper.go: base modulewrapper command set and protocol loop. +// - official_compat.go: shared command handlers modeled after Go fips140test +// behavior where public APIs allow. +package acvpwrapper diff --git a/pkg/acvpwrapper/go_port_extra.go b/pkg/acvpwrapper/go_port_extra.go new file mode 100644 index 000000000..87a825bc5 --- /dev/null +++ b/pkg/acvpwrapper/go_port_extra.go @@ -0,0 +1,1073 @@ +package acvpwrapper + +import ( + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/hkdf" + "crypto/hmac" + "crypto/mlkem" + "crypto/mlkem/mlkemtest" + cryptoRand "crypto/rand" + "crypto/rsa" + "crypto/sha512" + "crypto/subtle" + "encoding/binary" + "errors" + "fmt" + "hash" + "io" + "math/big" + "strings" + "sync" +) + +func cmdMLDSA44KeyGen() command { return cmdUnsupportedMLDSA(1) } +func cmdMLDSA65KeyGen() command { return cmdUnsupportedMLDSA(1) } +func cmdMLDSA87KeyGen() command { return cmdUnsupportedMLDSA(1) } +func cmdMLDSA44SigGen() command { return cmdUnsupportedMLDSA(5) } +func cmdMLDSA65SigGen() command { return cmdUnsupportedMLDSA(5) } +func cmdMLDSA87SigGen() command { return cmdUnsupportedMLDSA(5) } +func cmdMLDSA44SigVer() command { return cmdUnsupportedMLDSA(5) } +func cmdMLDSA65SigVer() command { return cmdUnsupportedMLDSA(5) } +func cmdMLDSA87SigVer() command { return cmdUnsupportedMLDSA(5) } + +func cmdUnsupportedMLDSA(requiredArgs int) command { + return command{ + requiredArgs: requiredArgs, + handler: func(args [][]byte) ([][]byte, error) { + return nil, errors.New("ML-DSA is not implemented with public Go crypto APIs in this build") + }, + } +} + +func cmdEDDSAKeyGen() command { + return command{ + requiredArgs: 1, // curve + handler: func(args [][]byte) ([][]byte, error) { + if string(args[0]) != "ED-25519" { + return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0]) + } + pub, priv, err := ed25519.GenerateKey(cryptoRand.Reader) + if err != nil { + return nil, err + } + return [][]byte{priv.Seed(), pub}, nil + }, + } +} + +func cmdEDDSAKeyVer() command { + return command{ + requiredArgs: 2, // curve, public key + handler: func(args [][]byte) ([][]byte, error) { + if string(args[0]) != "ED-25519" { + return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0]) + } + if len(args[1]) != ed25519.PublicKeySize { + return [][]byte{{0}}, nil + } + // ACVP keyVer requires curve-point validation independent of signature checks. + err := ed25519.VerifyWithOptions(ed25519.PublicKey(args[1]), []byte{0}, make([]byte, ed25519.SignatureSize), &ed25519.Options{}) + if err != nil && err.Error() == "ed25519: bad public key" { + return [][]byte{{0}}, nil + } + return [][]byte{{1}}, nil + }, + } +} + +func cmdEDDSASigGen() command { + return command{ + requiredArgs: 5, // curve, private key seed, message, prehash, context + handler: func(args [][]byte) ([][]byte, error) { + if string(args[0]) != "ED-25519" { + return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0]) + } + if len(args[1]) != ed25519.SeedSize { + return nil, fmt.Errorf("invalid EDDSA seed size: %d", len(args[1])) + } + priv := ed25519.NewKeyFromSeed(args[1]) + msg := args[2] + prehash := len(args[3]) > 0 && args[3][0] == 1 + context := string(args[4]) + + if prehash { + sum := sha512.Sum512(msg) + sig, err := priv.Sign(cryptoRand.Reader, sum[:], &ed25519.Options{ + Hash: crypto.SHA512, + Context: context, + }) + if err != nil { + return nil, err + } + return [][]byte{sig}, nil + } + return [][]byte{ed25519.Sign(priv, msg)}, nil + }, + } +} + +func cmdEDDSASigVer() command { + return command{ + requiredArgs: 5, // curve, message, public key, signature, prehash + handler: func(args [][]byte) ([][]byte, error) { + if string(args[0]) != "ED-25519" { + return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0]) + } + pub := ed25519.PublicKey(args[2]) + msg := args[1] + sig := args[3] + prehash := len(args[4]) > 0 && args[4][0] == 1 + + if prehash { + sum := sha512.Sum512(msg) + err := ed25519.VerifyWithOptions(pub, sum[:], sig, &ed25519.Options{Hash: crypto.SHA512}) + if err != nil { + return [][]byte{{0}}, nil + } + return [][]byte{{1}}, nil + } + if ed25519.Verify(pub, msg, sig) { + return [][]byte{{1}}, nil + } + return [][]byte{{0}}, nil + }, + } +} + +func cmdECDSAKeyGen() command { + return command{ + requiredArgs: 1, // curve + handler: func(args [][]byte) ([][]byte, error) { + curve, err := lookupCurveByName(string(args[0])) + if err != nil { + return nil, err + } + priv, err := ecdsa.GenerateKey(curve, cryptoRand.Reader) + if err != nil { + return nil, err + } + pubBytes := elliptic.Marshal(curve, priv.X, priv.Y) + byteLen := (curve.Params().BitSize + 7) / 8 + return [][]byte{ + priv.D.Bytes(), + pubBytes[1 : 1+byteLen], + pubBytes[1+byteLen:], + }, nil + }, + } +} + +func cmdECDSAKeyVer() command { + return command{ + requiredArgs: 3, // curve, x, y + handler: func(args [][]byte) ([][]byte, error) { + curve, err := lookupCurveByName(string(args[0])) + if err != nil { + return nil, err + } + x := new(big.Int).SetBytes(args[1]) + y := new(big.Int).SetBytes(args[2]) + if curve.IsOnCurve(x, y) { + return [][]byte{{1}}, nil + } + return [][]byte{{0}}, nil + }, + } +} + +type deterministicReader struct { + seed []byte + ctr uint64 + buf []byte +} + +func (d *deterministicReader) Read(p []byte) (int, error) { + n := 0 + for n < len(p) { + if len(d.buf) == 0 { + h := sha512.New() + h.Write(d.seed) + var ctr [8]byte + binary.BigEndian.PutUint64(ctr[:], d.ctr) + d.ctr++ + h.Write(ctr[:]) + d.buf = h.Sum(nil) + } + c := copy(p[n:], d.buf) + d.buf = d.buf[c:] + n += c + } + return n, nil +} + +func cmdECDSASigGen(deterministic bool) command { + return command{ + requiredArgs: 4, // curve, private key, hash name, message + handler: func(args [][]byte) ([][]byte, error) { + curve, err := lookupCurveByName(string(args[0])) + if err != nil { + return nil, err + } + hashFn, err := lookupHashByName(string(args[2])) + if err != nil { + return nil, err + } + d := new(big.Int).SetBytes(args[1]) + x, y := curve.ScalarBaseMult(d.Bytes()) + priv := &ecdsa.PrivateKey{ + PublicKey: ecdsa.PublicKey{Curve: curve, X: x, Y: y}, + D: d, + } + + h := hashFn() + h.Write(args[3]) + digest := h.Sum(nil) + + reader := io.Reader(cryptoRand.Reader) + if deterministic { + seed := make([]byte, 0, len(args[1])+len(args[3])) + seed = append(seed, args[1]...) + seed = append(seed, args[3]...) + reader = &deterministicReader{seed: seed} + } + r, s, err := ecdsa.Sign(reader, priv, digest) + if err != nil { + return nil, err + } + return [][]byte{r.Bytes(), s.Bytes()}, nil + }, + } +} + +func cmdECDSASigVer() command { + return command{ + requiredArgs: 7, // curve, hash, message, x, y, r, s + handler: func(args [][]byte) ([][]byte, error) { + curve, err := lookupCurveByName(string(args[0])) + if err != nil { + return nil, err + } + hashFn, err := lookupHashByName(string(args[1])) + if err != nil { + return nil, err + } + pub := &ecdsa.PublicKey{ + Curve: curve, + X: new(big.Int).SetBytes(args[3]), + Y: new(big.Int).SetBytes(args[4]), + } + h := hashFn() + h.Write(args[2]) + digest := h.Sum(nil) + if ecdsa.Verify(pub, digest, new(big.Int).SetBytes(args[5]), new(big.Int).SetBytes(args[6])) { + return [][]byte{{1}}, nil + } + return [][]byte{{0}}, nil + }, + } +} + +func lookupCurveByName(name string) (elliptic.Curve, error) { + switch name { + case "P-224": + return elliptic.P224(), nil + case "P-256": + return elliptic.P256(), nil + case "P-384": + return elliptic.P384(), nil + case "P-521": + return elliptic.P521(), nil + default: + return nil, fmt.Errorf("unknown curve name: %q", name) + } +} + +func cmdCMACAESAFT() command { + return command{ + requiredArgs: 3, // output bytes, key, message + handler: func(args [][]byte) ([][]byte, error) { + outLen := int(binary.LittleEndian.Uint32(args[0])) + tag, err := aesCMAC(args[1], args[2]) + if err != nil { + return nil, err + } + if outLen > len(tag) { + return nil, fmt.Errorf("invalid output length: %d", outLen) + } + return [][]byte{tag[:outLen]}, nil + }, + } +} + +func cmdCMACAESVerifyAFT() command { + return command{ + requiredArgs: 3, // key, message, claimed tag + handler: func(args [][]byte) ([][]byte, error) { + tag, err := aesCMAC(args[0], args[1]) + if err != nil { + return nil, err + } + claimed := args[2] + if len(claimed) > len(tag) || subtle.ConstantTimeCompare(tag[:len(claimed)], claimed) != 1 { + return [][]byte{{0}}, nil + } + return [][]byte{{1}}, nil + }, + } +} + +func aesCMAC(key, msg []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + L := make([]byte, aes.BlockSize) + block.Encrypt(L, make([]byte, aes.BlockSize)) + k1 := leftShiftOneBit(L) + if L[0]&0x80 != 0 { + k1[len(k1)-1] ^= 0x87 + } + k2 := leftShiftOneBit(k1) + if k1[0]&0x80 != 0 { + k2[len(k2)-1] ^= 0x87 + } + + n := (len(msg) + aes.BlockSize - 1) / aes.BlockSize + if n == 0 { + n = 1 + } + + last := make([]byte, aes.BlockSize) + complete := len(msg) > 0 && len(msg)%aes.BlockSize == 0 + if complete { + copy(last, msg[(n-1)*aes.BlockSize:]) + xorBlock(last, k1) + } else { + start := (n - 1) * aes.BlockSize + if start < len(msg) { + copy(last, msg[start:]) + } + last[len(msg)-start] = 0x80 + xorBlock(last, k2) + } + + x := make([]byte, aes.BlockSize) + y := make([]byte, aes.BlockSize) + for i := 0; i < n-1; i++ { + copy(y, msg[i*aes.BlockSize:(i+1)*aes.BlockSize]) + xorBlock(y, x) + block.Encrypt(x, y) + } + copy(y, last) + xorBlock(y, x) + block.Encrypt(x, y) + return x, nil +} + +func leftShiftOneBit(in []byte) []byte { + out := make([]byte, len(in)) + var carry byte + for i := len(in) - 1; i >= 0; i-- { + out[i] = (in[i] << 1) | carry + carry = (in[i] >> 7) & 1 + } + return out +} + +func xorBlock(dst, src []byte) { + for i := range dst { + dst[i] ^= src[i] + } +} + +func cmdKDFCounter() command { + return command{ + requiredArgs: 5, // output bytes, prf, counter location, key, counter bits + handler: func(args [][]byte) ([][]byte, error) { + outputBytes := int(binary.LittleEndian.Uint32(args[0])) + prf := string(args[1]) + counterLocation := string(args[2]) + key := args[3] + counterBits := binary.LittleEndian.Uint32(args[4]) + + if outputBytes <= 0 || outputBytes > 4096 { + return nil, fmt.Errorf("unsupported output length %d", outputBytes) + } + if prf != "CMAC-AES128" && prf != "CMAC-AES192" && prf != "CMAC-AES256" { + return nil, fmt.Errorf("unsupported PRF %q", prf) + } + if counterLocation != "before fixed data" { + return nil, fmt.Errorf("unsupported counter location %q", counterLocation) + } + if len(key) == 0 { + return nil, errors.New("deferred test cases are not supported") + } + if counterBits != 16 { + return nil, fmt.Errorf("unsupported counter bits %d", counterBits) + } + + var context [12]byte + if _, err := cryptoRand.Read(context[:]); err != nil { + return nil, err + } + fixedData := make([]byte, 14) // label(1) + separator(1) + context(12) + copy(fixedData[2:], context[:]) + + result := make([]byte, 0, outputBytes) + for i := 1; len(result) < outputBytes; i++ { + input := make([]byte, 2+len(fixedData)) + binary.BigEndian.PutUint16(input[:2], uint16(i)) + copy(input[2:], fixedData) + tag, err := aesCMAC(key, input) + if err != nil { + return nil, err + } + result = append(result, tag...) + } + return [][]byte{key, fixedData, result[:outputBytes]}, nil + }, + } +} + +func cmdKDFFeedback() command { + return command{ + requiredArgs: 5, // output bytes, prf, counter location, key, counter bits + handler: func(args [][]byte) ([][]byte, error) { + outputBytes := int(binary.LittleEndian.Uint32(args[0])) + prf := string(args[1]) + counterLocation := string(args[2]) + key := args[3] + counterBits := binary.LittleEndian.Uint32(args[4]) + + if !strings.HasPrefix(prf, "HMAC-") { + return nil, fmt.Errorf("unsupported PRF %q", prf) + } + hashName := prf[len("HMAC-"):] + hashFn, err := lookupHashByName(hashName) + if err != nil { + return nil, err + } + if counterLocation != "after fixed data" { + return nil, fmt.Errorf("unsupported counter location %q", counterLocation) + } + if len(key) == 0 { + return nil, errors.New("deferred test cases are not supported") + } + if counterBits != 8 { + return nil, fmt.Errorf("unsupported counter bits %d", counterBits) + } + + var context [12]byte + if _, err := cryptoRand.Read(context[:]); err != nil { + return nil, err + } + fixedData := make([]byte, 14) // label(1) + separator(1) + context(12) + copy(fixedData[2:], context[:]) + + out, err := hkdf.Expand(hashFn, key, string(fixedData), outputBytes) + if err != nil { + return nil, err + } + return [][]byte{key, fixedData, out}, nil + }, + } +} + +func cmdOneStepNoCounterHMAC(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 4, // key, info, salt, output bytes + handler: func(args [][]byte) ([][]byte, error) { + key := args[0] + info := args[1] + salt := args[2] + outBytes := int(binary.LittleEndian.Uint32(args[3])) + + mac := hmac.New(hashFn, salt) + if outBytes != mac.Size() { + return nil, fmt.Errorf("invalid output length: got %d want %d", outBytes, mac.Size()) + } + data := make([]byte, 0, len(key)+len(info)) + data = append(data, key...) + data = append(data, info...) + mac.Write(data) + return [][]byte{mac.Sum(nil)}, nil + }, + } +} + +var ( + rsaKeyCache = map[int]*rsa.PrivateKey{} + rsaKeyCacheMu sync.Mutex +) + +func getRSAKey(bits int) (*rsa.PrivateKey, error) { + rsaKeyCacheMu.Lock() + defer rsaKeyCacheMu.Unlock() + if k, ok := rsaKeyCache[bits]; ok { + return k, nil + } + k, err := rsa.GenerateKey(cryptoRand.Reader, bits) + if err != nil { + return nil, err + } + rsaKeyCache[bits] = k + return k, nil +} + +func cmdRSAKeyGen() command { + return command{ + requiredArgs: 1, // modulus bits + handler: func(args [][]byte) ([][]byte, error) { + bits := int(binary.LittleEndian.Uint32(args[0])) + key, err := getRSAKey(bits) + if err != nil { + return nil, err + } + eBytes := make([]byte, 4) + binary.BigEndian.PutUint32(eBytes, uint32(key.E)) + return [][]byte{eBytes, key.Primes[0].Bytes(), key.Primes[1].Bytes(), key.N.Bytes(), key.D.Bytes()}, nil + }, + } +} + +func cmdRSASigGen(hashFn func() hash.Hash, hashID crypto.Hash, pss bool) command { + return command{ + requiredArgs: 2, // modulus bits, message + handler: func(args [][]byte) ([][]byte, error) { + bits := int(binary.LittleEndian.Uint32(args[0])) + msg := args[1] + key, err := getRSAKey(bits) + if err != nil { + return nil, err + } + h := hashFn() + h.Write(msg) + digest := h.Sum(nil) + + var sig []byte + if !pss { + sig, err = rsa.SignPKCS1v15(cryptoRand.Reader, key, hashID, digest) + } else { + sig, err = rsa.SignPSS(cryptoRand.Reader, key, hashID, digest, &rsa.PSSOptions{ + SaltLength: h.Size(), + Hash: hashID, + }) + } + if err != nil { + return nil, err + } + + eBytes := make([]byte, 4) + binary.BigEndian.PutUint32(eBytes, uint32(key.E)) + return [][]byte{key.N.Bytes(), eBytes, sig}, nil + }, + } +} + +func cmdRSASigVer(hashFn func() hash.Hash, hashID crypto.Hash, pss bool) command { + return command{ + requiredArgs: 4, // n, e, message, signature + handler: func(args [][]byte) ([][]byte, error) { + n := new(big.Int).SetBytes(args[0]) + ePadded := make([]byte, 4) + copy(ePadded[4-len(args[1]):], args[1]) + e := int(binary.BigEndian.Uint32(ePadded)) + pub := &rsa.PublicKey{N: n, E: e} + + h := hashFn() + h.Write(args[2]) + digest := h.Sum(nil) + var err error + if !pss { + err = rsa.VerifyPKCS1v15(pub, hashID, digest, args[3]) + } else { + err = rsa.VerifyPSS(pub, hashID, digest, args[3], nil) + } + if err != nil { + return [][]byte{{0}}, nil + } + return [][]byte{{1}}, nil + }, + } +} + +func cmdRSASigGenByHashName(hashName string, pss bool) command { + hashFn, err := lookupHashByName(hashName) + if err != nil { + panic(err) + } + hashID, err := hashNameToCryptoHash(hashName) + if err != nil { + panic(err) + } + return cmdRSASigGen(hashFn, hashID, pss) +} + +func cmdRSASigVerByHashName(hashName string, pss bool) command { + hashFn, err := lookupHashByName(hashName) + if err != nil { + panic(err) + } + hashID, err := hashNameToCryptoHash(hashName) + if err != nil { + panic(err) + } + return cmdRSASigVer(hashFn, hashID, pss) +} + +func hashNameToCryptoHash(name string) (crypto.Hash, error) { + switch name { + case "SHA-1": + return crypto.SHA1, nil + case "SHA2-224": + return crypto.SHA224, nil + case "SHA2-256": + return crypto.SHA256, nil + case "SHA2-384": + return crypto.SHA384, nil + case "SHA2-512": + return crypto.SHA512, nil + default: + return 0, fmt.Errorf("unsupported hash for RSA: %s", name) + } +} + +func cmdTLSKDF12(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 5, // output bytes, secret, label, seed1, seed2 + handler: func(args [][]byte) ([][]byte, error) { + outLen := int(binary.LittleEndian.Uint32(args[0])) + secret := args[1] + label := args[2] + seed := append(append([]byte{}, label...), args[3]...) + seed = append(seed, args[4]...) + return [][]byte{tls12PRF(hashFn, secret, seed, outLen)}, nil + }, + } +} + +func tls12PRF(hashFn func() hash.Hash, secret, seed []byte, outLen int) []byte { + out := make([]byte, 0, outLen) + a := hmacDigest(hashFn, secret, seed) + for len(out) < outLen { + block := hmacDigest(hashFn, secret, append(append([]byte{}, a...), seed...)) + out = append(out, block...) + a = hmacDigest(hashFn, secret, a) + } + return out[:outLen] +} + +func hmacDigest(hashFn func() hash.Hash, key, data []byte) []byte { + m := hmac.New(hashFn, key) + m.Write(data) + return m.Sum(nil) +} + +func cmdSSHKDF(hashFn func() hash.Hash, client bool) command { + return command{ + requiredArgs: 4, // K, H, session id, cipher + handler: func(args [][]byte) ([][]byte, error) { + k := args[0] + h := args[1] + sessionID := args[2] + cipherName := string(args[3]) + + var keyLen int + switch cipherName { + case "AES-128": + keyLen = 16 + case "AES-192": + keyLen = 24 + case "AES-256": + keyLen = 32 + default: + return nil, fmt.Errorf("unsupported cipher: %q", cipherName) + } + + ivLabel, encLabel, intLabel := byte('A'), byte('C'), byte('E') + if !client { + ivLabel, encLabel, intLabel = 'B', 'D', 'F' + } + ivKey := sshDerive(hashFn, k, h, sessionID, ivLabel, 16) + encKey := sshDerive(hashFn, k, h, sessionID, encLabel, keyLen) + intKey := sshDerive(hashFn, k, h, sessionID, intLabel, hashFn().Size()) + return [][]byte{ivKey, encKey, intKey}, nil + }, + } +} + +func sshDerive(hashFn func() hash.Hash, k, h, sessionID []byte, letter byte, outLen int) []byte { + out := make([]byte, 0, outLen) + for len(out) < outLen { + hasher := hashFn() + hasher.Write(k) + hasher.Write(h) + if len(out) == 0 { + hasher.Write([]byte{letter}) + hasher.Write(sessionID) + } else { + hasher.Write(out) + } + out = append(out, hasher.Sum(nil)...) + } + return out[:outLen] +} + +func cmdECDH(curve elliptic.Curve) command { + return command{ + requiredArgs: 3, // peer x, peer y, private key (optional) + handler: func(args [][]byte) ([][]byte, error) { + peerX := new(big.Int).SetBytes(args[0]) + peerY := new(big.Int).SetBytes(args[1]) + if !curve.IsOnCurve(peerX, peerY) { + return nil, errors.New("invalid peer point") + } + + byteLen := (curve.Params().BitSize + 7) / 8 + sk := append([]byte(nil), args[2]...) + if len(sk) == 0 { + sk = make([]byte, byteLen) + for { + if _, err := cryptoRand.Read(sk); err != nil { + return nil, err + } + s := new(big.Int).SetBytes(sk) + if s.Sign() > 0 && s.Cmp(curve.Params().N) < 0 { + break + } + } + } + + pubX, pubY := curve.ScalarBaseMult(sk) + secretX, _ := curve.ScalarMult(peerX, peerY, sk) + if secretX == nil { + return nil, errors.New("ecdh failed") + } + return [][]byte{ + pubX.FillBytes(make([]byte, byteLen)), + pubY.FillBytes(make([]byte, byteLen)), + secretX.FillBytes(make([]byte, byteLen)), + }, nil + }, + } +} + +type acvpCTRDRBG struct { + block cipher.Block + v [aes.BlockSize]byte +} + +func newACVPCTRDRBG(entropy *[48]byte) (*acvpCTRDRBG, error) { + key := make([]byte, 32) + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + d := &acvpCTRDRBG{block: block} + d.v[len(d.v)-1] = 1 + if err := d.update(entropy); err != nil { + return nil, err + } + return d, nil +} + +func increment128(v *[16]byte) { + for i := len(v) - 1; i >= 0; i-- { + v[i]++ + if v[i] != 0 { + return + } + } +} + +func (d *acvpCTRDRBG) generateKeystream(out []byte) { + blockBuf := make([]byte, aes.BlockSize) + done := 0 + for done < len(out) { + d.block.Encrypt(blockBuf, d.v[:]) + increment128(&d.v) + done += copy(out[done:], blockBuf) + } +} + +func (d *acvpCTRDRBG) update(seed *[48]byte) error { + temp := make([]byte, 48) + d.generateKeystream(temp) + for i := range temp { + temp[i] ^= seed[i] + } + + block, err := aes.NewCipher(temp[:32]) + if err != nil { + return err + } + d.block = block + copy(d.v[:], temp[32:]) + increment128(&d.v) + return nil +} + +func (d *acvpCTRDRBG) generate(out []byte, additionalInput *[48]byte) error { + if additionalInput != nil { + if err := d.update(additionalInput); err != nil { + return err + } + } else { + additionalInput = new([48]byte) + } + + d.generateKeystream(out) + if rem := len(out) % aes.BlockSize; rem != 0 { + d.generateKeystream(make([]byte, aes.BlockSize-rem)) + } + return d.update(additionalInput) +} + +func require48Bytes(input []byte) (*[48]byte, error) { + if len(input) != 48 { + return nil, fmt.Errorf("invalid length: %d", len(input)) + } + return (*[48]byte)(input), nil +} + +func cmdCTRDRBGAFT() command { + return command{ + requiredArgs: 6, // outLen, entropy, personalization, ad1, ad2, nonce + handler: func(args [][]byte) ([][]byte, error) { + outLen := binary.LittleEndian.Uint32(args[0]) + entropy, err := require48Bytes(args[1]) + if err != nil { + return nil, fmt.Errorf("entropy: %w", err) + } + if len(args[2]) > 0 { + return nil, errors.New("personalization string not supported") + } + ad1, err := require48Bytes(args[3]) + if err != nil { + return nil, fmt.Errorf("ad1: %w", err) + } + ad2, err := require48Bytes(args[4]) + if err != nil { + return nil, fmt.Errorf("ad2: %w", err) + } + if len(args[5]) > 0 { + return nil, errors.New("unexpected nonce value") + } + + drbg, err := newACVPCTRDRBG(entropy) + if err != nil { + return nil, err + } + out := make([]byte, outLen) + if err := drbg.generate(out, ad1); err != nil { + return nil, err + } + if err := drbg.generate(out, ad2); err != nil { + return nil, err + } + return [][]byte{out}, nil + }, + } +} + +func cmdCTRDRBGReseedAFT() command { + return command{ + requiredArgs: 8, // outLen, entropy, personalization, reseedAD, reseedEntropy, ad1, ad2, nonce + handler: func(args [][]byte) ([][]byte, error) { + outLen := binary.LittleEndian.Uint32(args[0]) + entropy, err := require48Bytes(args[1]) + if err != nil { + return nil, fmt.Errorf("entropy: %w", err) + } + if len(args[2]) > 0 { + return nil, errors.New("personalization string not supported") + } + reseedAD, err := require48Bytes(args[3]) + if err != nil { + return nil, fmt.Errorf("reseed ad: %w", err) + } + reseedEntropy, err := require48Bytes(args[4]) + if err != nil { + return nil, fmt.Errorf("reseed entropy: %w", err) + } + ad1, err := require48Bytes(args[5]) + if err != nil { + return nil, fmt.Errorf("ad1: %w", err) + } + ad2, err := require48Bytes(args[6]) + if err != nil { + return nil, fmt.Errorf("ad2: %w", err) + } + if len(args[7]) > 0 { + return nil, errors.New("unexpected nonce value") + } + + drbg, err := newACVPCTRDRBG(entropy) + if err != nil { + return nil, err + } + var reseedSeed [48]byte + for i := range reseedSeed { + reseedSeed[i] = reseedEntropy[i] ^ reseedAD[i] + } + if err := drbg.update(&reseedSeed); err != nil { + return nil, err + } + + out := make([]byte, outLen) + if err := drbg.generate(out, ad1); err != nil { + return nil, err + } + if err := drbg.generate(out, ad2); err != nil { + return nil, err + } + return [][]byte{out}, nil + }, + } +} + +func cmdMLKEM768KeyGen() command { + return command{ + requiredArgs: 1, // seed (d||z) + handler: func(args [][]byte) ([][]byte, error) { + dk, err := mlkem.NewDecapsulationKey768(args[0]) + if err != nil { + return nil, err + } + return [][]byte{dk.EncapsulationKey().Bytes(), dk.Bytes()}, nil + }, + } +} + +func cmdMLKEM768Encap() command { + return command{ + requiredArgs: 2, // encapsulation key, entropy + handler: func(args [][]byte) ([][]byte, error) { + ek, err := mlkem.NewEncapsulationKey768(args[0]) + if err != nil { + return nil, err + } + ss, ct, err := mlkemtest.Encapsulate768(ek, args[1]) + if err != nil { + return nil, err + } + return [][]byte{ct, ss}, nil + }, + } +} + +func cmdMLKEM768Decap() command { + return command{ + requiredArgs: 2, // decapsulation key seed, ciphertext + handler: func(args [][]byte) ([][]byte, error) { + seed := args[0] + if len(seed) != mlkem.SeedSize && len(seed) > mlkem.SeedSize { + seed = seed[:mlkem.SeedSize] + } + dk, err := mlkem.NewDecapsulationKey768(seed) + if err != nil { + return nil, err + } + ss, err := dk.Decapsulate(args[1]) + if err != nil { + return nil, err + } + return [][]byte{ss}, nil + }, + } +} + +func cmdMLKEM1024KeyGen() command { + return command{ + requiredArgs: 1, // seed (d||z) + handler: func(args [][]byte) ([][]byte, error) { + dk, err := mlkem.NewDecapsulationKey1024(args[0]) + if err != nil { + return nil, err + } + return [][]byte{dk.EncapsulationKey().Bytes(), dk.Bytes()}, nil + }, + } +} + +func cmdMLKEM1024Encap() command { + return command{ + requiredArgs: 2, // encapsulation key, entropy + handler: func(args [][]byte) ([][]byte, error) { + ek, err := mlkem.NewEncapsulationKey1024(args[0]) + if err != nil { + return nil, err + } + ss, ct, err := mlkemtest.Encapsulate1024(ek, args[1]) + if err != nil { + return nil, err + } + return [][]byte{ct, ss}, nil + }, + } +} + +func cmdMLKEM1024Decap() command { + return command{ + requiredArgs: 2, // decapsulation key seed, ciphertext + handler: func(args [][]byte) ([][]byte, error) { + seed := args[0] + if len(seed) != mlkem.SeedSize && len(seed) > mlkem.SeedSize { + seed = seed[:mlkem.SeedSize] + } + dk, err := mlkem.NewDecapsulationKey1024(seed) + if err != nil { + return nil, err + } + ss, err := dk.Decapsulate(args[1]) + if err != nil { + return nil, err + } + return [][]byte{ss}, nil + }, + } +} + +func (d *officialHMACDRBG) reseed(entropy, additionalInput []byte) { + seed := make([]byte, 0, len(entropy)+len(additionalInput)) + seed = append(seed, entropy...) + seed = append(seed, additionalInput...) + d.update(seed) +} + +func cmdHMACDRBGReseed(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 8, // outLen, entropy, personalization, reseedAD, reseedEntropy, ad1, ad2, nonce + handler: func(args [][]byte) ([][]byte, error) { + outLen := binary.LittleEndian.Uint32(args[0]) + out := make([]byte, outLen) + drbg := newOfficialHMACDRBG(hashFn, args[1], args[7], args[2]) + drbg.reseed(args[4], args[3]) + drbg.generate(out, args[5]) + drbg.generate(out, args[6]) + return [][]byte{out}, nil + }, + } +} + +func cmdHMACDRBGPredictionResistance(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 8, // outLen, entropy, personalization, ad1, entropy1, ad2, entropy2, nonce + handler: func(args [][]byte) ([][]byte, error) { + outLen := binary.LittleEndian.Uint32(args[0]) + out := make([]byte, outLen) + drbg := newOfficialHMACDRBG(hashFn, args[1], args[7], args[2]) + drbg.reseed(args[4], args[3]) + drbg.generate(out, nil) + drbg.reseed(args[6], args[5]) + drbg.generate(out, nil) + return [][]byte{out}, nil + }, + } +} diff --git a/pkg/acvpwrapper/official_compat.go b/pkg/acvpwrapper/official_compat.go new file mode 100644 index 000000000..ed79b3c73 --- /dev/null +++ b/pkg/acvpwrapper/official_compat.go @@ -0,0 +1,351 @@ +package acvpwrapper + +import ( + "bytes" + "crypto/hkdf" + "crypto/hmac" + "crypto/pbkdf2" + "crypto/sha1" + "crypto/sha256" + "crypto/sha3" + "crypto/sha512" + "encoding/binary" + "errors" + "fmt" + "hash" +) + +func cmdShakeAFTVOT(newShake func() *sha3.SHAKE) command { + return command{ + requiredArgs: 2, // message, output length bytes + handler: func(args [][]byte) ([][]byte, error) { + msg := args[0] + outLenBytes := binary.LittleEndian.Uint32(args[1]) + out := make([]byte, outLenBytes) + + h := newShake() + h.Write(msg) + h.Read(out) + return [][]byte{out}, nil + }, + } +} + +func cmdShakeMCT(newShake func() *sha3.SHAKE) command { + return command{ + requiredArgs: 4, // seed, min output length bytes, max output length bytes, output length bytes + handler: func(args [][]byte) ([][]byte, error) { + md := args[0] + minOutBytes := binary.LittleEndian.Uint32(args[1]) + maxOutBytes := binary.LittleEndian.Uint32(args[2]) + outLenBytes := binary.LittleEndian.Uint32(args[3]) + if outLenBytes < 2 { + return nil, fmt.Errorf("invalid output length: %d", outLenBytes) + } + + rangeBytes := maxOutBytes - minOutBytes + 1 + if rangeBytes == 0 { + return nil, fmt.Errorf("invalid min/max output lengths: %d/%d", minOutBytes, maxOutBytes) + } + + h := newShake() + for i := 0; i < 1000; i++ { + msg := make([]byte, 16) + copy(msg, md[:minInt(len(md), 16)]) + + h.Reset() + h.Write(msg) + digest := make([]byte, outLenBytes) + h.Read(digest) + md = digest + + rightmost := uint32(md[outLenBytes-2])<<8 | uint32(md[outLenBytes-1]) + outLenBytes = minOutBytes + (rightmost % rangeBytes) + } + + encodedOutLen := make([]byte, 4) + binary.LittleEndian.PutUint32(encodedOutLen, outLenBytes) + return [][]byte{md, encodedOutLen}, nil + }, + } +} + +func cmdCShakeAFT(newCShake func(N, S []byte) *sha3.SHAKE) command { + return command{ + requiredArgs: 4, // message, output length bytes, function name, customization + handler: func(args [][]byte) ([][]byte, error) { + msg := args[0] + outLenBytes := binary.LittleEndian.Uint32(args[1]) + functionName := args[2] + customization := args[3] + + out := make([]byte, outLenBytes) + h := newCShake(functionName, customization) + h.Write(msg) + h.Read(out) + return [][]byte{out}, nil + }, + } +} + +func cmdCShakeMCT(newCShake func(N, S []byte) *sha3.SHAKE) command { + return command{ + requiredArgs: 6, // msg, min out bytes, max out bytes, out bytes, increment bytes, customization + handler: func(args [][]byte) ([][]byte, error) { + msg := args[0] + minOutLenBytes := binary.LittleEndian.Uint32(args[1]) + maxOutLenBytes := binary.LittleEndian.Uint32(args[2]) + outLenBytes := binary.LittleEndian.Uint32(args[3]) + incrementBytes := binary.LittleEndian.Uint32(args[4]) + customization := args[5] + + if outLenBytes < 2 { + return nil, fmt.Errorf("invalid output length: %d", outLenBytes) + } + rangeBits := (maxOutLenBytes*8 - minOutLenBytes*8) + 1 + if rangeBits == 0 { + return nil, fmt.Errorf("invalid min/max output lengths: %d/%d", minOutLenBytes, maxOutLenBytes) + } + + for i := 0; i < 1000; i++ { + innerMsg := make([]byte, 16) + copy(innerMsg, msg[:minInt(len(msg), 16)]) + + // For MCT, function name is fixed to the empty string. + h := newCShake(nil, customization) + h.Write(innerMsg) + digest := make([]byte, outLenBytes) + h.Read(digest) + msg = digest + + rightmostOutputBE := binary.BigEndian.Uint16(digest[outLenBytes-2:]) + incrementBits := incrementBytes * 8 + outLenBits := (minOutLenBytes * 8) + (uint32(rightmostOutputBE)%rangeBits)/incrementBits*incrementBits + outLenBytes = outLenBits / 8 + + msgWithBits := append(innerMsg, digest[len(digest)-2:]...) + customization = make([]byte, len(msgWithBits)) + for i, b := range msgWithBits { + customization[i] = (b % 26) + 'A' + } + } + + encodedOutLen := make([]byte, 4) + binary.LittleEndian.PutUint32(encodedOutLen, outLenBytes) + return [][]byte{msg, encodedOutLen, customization}, nil + }, + } +} + +func cmdHKDFAFT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 4, // key, salt, info, output length bytes + handler: func(args [][]byte) ([][]byte, error) { + key := args[0] + salt := args[1] + info := args[2] + keyLen := int(binary.LittleEndian.Uint32(args[3])) + + out, err := hkdf.Key(hashFn, key, salt, string(info), keyLen) + if err != nil { + return nil, err + } + return [][]byte{out}, nil + }, + } +} + +func cmdHKDFExtractAFT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 2, // secret, salt + handler: func(args [][]byte) ([][]byte, error) { + secret := args[0] + salt := args[1] + out, err := hkdf.Extract(hashFn, secret, salt) + if err != nil { + return nil, err + } + return [][]byte{out}, nil + }, + } +} + +func cmdHKDFExpandLabelAFT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 4, // output length bytes, secret, label, transcript hash + handler: func(args [][]byte) ([][]byte, error) { + keyLen := int(binary.LittleEndian.Uint32(args[0])) + secret := args[1] + label := args[2] + transcriptHash := args[3] + + out, err := tls13ExpandLabel(hashFn, secret, string(label), transcriptHash, keyLen) + if err != nil { + return nil, err + } + return [][]byte{out}, nil + }, + } +} + +func tls13ExpandLabel(hashFn func() hash.Hash, secret []byte, label string, context []byte, keyLen int) ([]byte, error) { + fullLabel := "tls13 " + label + info := make([]byte, 2+1+len(fullLabel)+1+len(context)) + binary.BigEndian.PutUint16(info[:2], uint16(keyLen)) + info[2] = byte(len(fullLabel)) + copy(info[3:3+len(fullLabel)], fullLabel) + info[3+len(fullLabel)] = byte(len(context)) + copy(info[4+len(fullLabel):], context) + + return hkdf.Expand(hashFn, secret, string(info), keyLen) +} + +func cmdPBKDF() command { + return command{ + requiredArgs: 5, // hash name, key length bits, salt, password, iteration count + handler: func(args [][]byte) ([][]byte, error) { + hashFn, err := lookupHashByName(string(args[0])) + if err != nil { + return nil, fmt.Errorf("PBKDF2 failed: %w", err) + } + keyLen := int(binary.LittleEndian.Uint32(args[1]) / 8) + salt := args[2] + password := args[3] + iter := int(binary.LittleEndian.Uint32(args[4])) + + derived, err := pbkdf2.Key(hashFn, string(password), salt, iter, keyLen) + if err != nil { + return nil, fmt.Errorf("PBKDF2 failed: %w", err) + } + return [][]byte{derived}, nil + }, + } +} + +func cmdHMACDRBGAFT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 6, // output length bytes, entropy, personalization, ad1, ad2, nonce + handler: func(args [][]byte) ([][]byte, error) { + outLen := binary.LittleEndian.Uint32(args[0]) + entropy := args[1] + personalization := args[2] + ad1 := args[3] + ad2 := args[4] + nonce := args[5] + + if len(ad1) != 0 || len(ad2) != 0 { + return nil, errors.New("additional data not supported") + } + + out := make([]byte, outLen) + drbg := newOfficialHMACDRBG(hashFn, entropy, nonce, personalization) + drbg.generate(out, nil) + drbg.generate(out, nil) + return [][]byte{out}, nil + }, + } +} + +type officialHMACDRBG struct { + hashFn func() hash.Hash + k []byte + v []byte +} + +func newOfficialHMACDRBG(hashFn func() hash.Hash, entropy, nonce, personalization []byte) *officialHMACDRBG { + size := hashFn().Size() + k := make([]byte, size) + v := bytes.Repeat([]byte{1}, size) + drbg := &officialHMACDRBG{hashFn: hashFn, k: k, v: v} + + seed := make([]byte, 0, len(entropy)+len(nonce)+len(personalization)) + seed = append(seed, entropy...) + seed = append(seed, nonce...) + seed = append(seed, personalization...) + drbg.update(seed) + return drbg +} + +func (d *officialHMACDRBG) update(data []byte) { + buf := make([]byte, 0, len(d.v)+1+len(data)) + buf = append(buf, d.v...) + buf = append(buf, 0) + buf = append(buf, data...) + + mac := hmac.New(d.hashFn, d.k) + mac.Write(buf) + d.k = mac.Sum(d.k[:0]) + + mac = hmac.New(d.hashFn, d.k) + mac.Write(d.v) + d.v = mac.Sum(d.v[:0]) + + if len(data) == 0 { + return + } + + buf = buf[:0] + buf = append(buf, d.v...) + buf = append(buf, 1) + buf = append(buf, data...) + + mac = hmac.New(d.hashFn, d.k) + mac.Write(buf) + d.k = mac.Sum(d.k[:0]) + + mac = hmac.New(d.hashFn, d.k) + mac.Write(d.v) + d.v = mac.Sum(d.v[:0]) +} + +func (d *officialHMACDRBG) generate(out []byte, additionalInput []byte) { + if len(additionalInput) > 0 { + d.update(additionalInput) + } + + done := 0 + for done < len(out) { + mac := hmac.New(d.hashFn, d.k) + mac.Write(d.v) + d.v = mac.Sum(d.v[:0]) + done += copy(out[done:], d.v) + } + + d.update(additionalInput) +} + +func lookupHashByName(name string) (func() hash.Hash, error) { + switch name { + case "SHA-1": + return sha1.New, nil + case "SHA2-224": + return sha256.New224, nil + case "SHA2-256": + return sha256.New, nil + case "SHA2-384": + return sha512.New384, nil + case "SHA2-512": + return sha512.New, nil + case "SHA2-512/224", "SHA2-512-224": + return sha512.New512_224, nil + case "SHA2-512/256", "SHA2-512-256": + return sha512.New512_256, nil + case "SHA3-224": + return newSHA3224, nil + case "SHA3-256": + return newSHA3256, nil + case "SHA3-384": + return newSHA3384, nil + case "SHA3-512": + return newSHA3512, nil + default: + return nil, fmt.Errorf("unknown hash name: %q", name) + } +} + +func minInt(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/pkg/acvpwrapper/run.sh b/pkg/acvpwrapper/run.sh new file mode 100644 index 000000000..094eae06e --- /dev/null +++ b/pkg/acvpwrapper/run.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" + +GO_IMAGE="${GO_IMAGE:-golang:1.26-alpine}" +BORINGSSL_DIR="${BORINGSSL_DIR:-/tmp/boringssl}" +ACVP_TESTDATA_DIR="${ACVP_TESTDATA_DIR:-/tmp/acvp-testdata}" +BORINGSSL_COMMIT="${BORINGSSL_COMMIT:-baaf868e6e8f}" +ACVP_TESTDATA_COMMIT="${ACVP_TESTDATA_COMMIT:-d893de8b8b1c}" +CONFIG_PATH="${CONFIG_PATH:-/work/pkg/acvpwrapper/acvp_test_fips140v1.26.public.config.json}" + +echo "[1/4] Build clickhouse-backup and ACVP symlink" +docker run --rm \ + -v "${REPO_ROOT}:/work" \ + -w /work \ + "${GO_IMAGE}" \ + sh -lc 'export PATH=$PATH:/usr/local/go/bin && CGO_ENABLED=0 go build -o clickhouse-backup ./cmd/clickhouse-backup && ln -sf clickhouse-backup clickhouse-backup-acvp' + +echo "[2/4] Fetch pinned boringssl and acvp-testdata" +if [[ ! -d "${BORINGSSL_DIR}/.git" ]]; then + rm -rf "${BORINGSSL_DIR}" + git clone https://boringssl.googlesource.com/boringssl "${BORINGSSL_DIR}" +fi +git -C "${BORINGSSL_DIR}" fetch --all --tags +git -C "${BORINGSSL_DIR}" checkout "${BORINGSSL_COMMIT}" + +if [[ ! -d "${ACVP_TESTDATA_DIR}/.git" ]]; then + rm -rf "${ACVP_TESTDATA_DIR}" + git clone https://github.com/geomys/acvp-testdata "${ACVP_TESTDATA_DIR}" +fi +git -C "${ACVP_TESTDATA_DIR}" fetch --all --tags +git -C "${ACVP_TESTDATA_DIR}" checkout "${ACVP_TESTDATA_COMMIT}" + +echo "[3/4] Build pinned acvptool" +docker run --rm \ + -v "${BORINGSSL_DIR}:/src" \ + -w /src \ + "${GO_IMAGE}" \ + sh -lc 'export PATH=$PATH:/usr/local/go/bin && go build -o /src/acvptool-pinned ./util/fipstools/acvp/acvptool' + +echo "[4/4] Run ACVP expected-output check" +docker run --rm \ + -e ACVP_WRAPPER=1 \ + -e GODEBUG=fips140=on \ + -v "${REPO_ROOT}:/work" \ + -v "${BORINGSSL_DIR}:/tmp/boringssl:ro" \ + -v "${ACVP_TESTDATA_DIR}:/tmp/acvp-testdata:rw" \ + -w /tmp/acvp-testdata \ + "${GO_IMAGE}" \ + sh -lc "export PATH=\$PATH:/usr/local/go/bin && go run /tmp/boringssl/util/fipstools/acvp/acvptool/test/check_expected.go -tool /tmp/boringssl/acvptool-pinned -module-wrappers go:/work/clickhouse-backup-acvp -tests ${CONFIG_PATH}" diff --git a/pkg/acvpwrapper/wrapper.go b/pkg/acvpwrapper/wrapper.go new file mode 100644 index 000000000..27022e3d6 --- /dev/null +++ b/pkg/acvpwrapper/wrapper.go @@ -0,0 +1,1235 @@ +package acvpwrapper + +import ( + "bufio" + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/elliptic" + "crypto/fips140" + "crypto/hmac" + "crypto/rand" + "crypto/sha1" + "crypto/sha256" + "crypto/sha3" + "crypto/sha512" + "encoding/binary" + "errors" + "fmt" + "hash" + "io" +) + +type request struct { + name string + args [][]byte +} + +type commandHandler func([][]byte) ([][]byte, error) + +type command struct { + requiredArgs int + handler commandHandler +} + +var capabilitiesJSON = []byte(`[ + { + "algorithm": "SHA-1", + "revision": "1.0", + "messageLength": [{ "min": 0, "max": 65528, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA2-224", + "revision": "1.0", + "messageLength": [{ "min": 0, "max": 65528, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA2-256", + "revision": "1.0", + "messageLength": [{ "min": 0, "max": 65528, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA2-384", + "revision": "1.0", + "messageLength": [{ "min": 0, "max": 65528, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA2-512", + "revision": "1.0", + "messageLength": [{ "min": 0, "max": 65528, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA2-512/224", + "revision": "1.0", + "messageLength": [{ "min": 0, "max": 65528, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA2-512/256", + "revision": "1.0", + "messageLength": [{ "min": 0, "max": 65528, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA3-224", + "revision": "2.0", + "messageLength": [{ "min": 0, "max": 65536, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA3-256", + "revision": "2.0", + "messageLength": [{ "min": 0, "max": 65536, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA3-384", + "revision": "2.0", + "messageLength": [{ "min": 0, "max": 65536, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "SHA3-512", + "revision": "2.0", + "messageLength": [{ "min": 0, "max": 65536, "increment": 8 }], + "performLargeDataTest": [1, 2, 4, 8] + }, + { + "algorithm": "ACVP-AES-ECB", + "revision": "1.0", + "direction": ["encrypt", "decrypt"], + "keyLen": [128, 192, 256] + }, + { + "algorithm": "ACVP-AES-CTR", + "revision": "1.0", + "direction": ["encrypt", "decrypt"], + "keyLen": [128, 192, 256], + "payloadLen": [{ "min": 8, "max": 128, "increment": 8 }], + "incrementalCounter": true, + "overflowCounter": true, + "performCounterTests": true + }, + { + "algorithm": "ACVP-AES-CBC", + "revision": "1.0", + "direction": ["encrypt", "decrypt"], + "keyLen": [128, 192, 256] + }, + { + "algorithm": "ACVP-AES-GCM", + "revision": "1.0", + "direction": ["encrypt", "decrypt"], + "keyLen": [128, 192, 256], + "payloadLen": [{ "min": 0, "max": 65536, "increment": 8 }], + "aadLen": [{ "min": 0, "max": 65536, "increment": 8 }], + "tagLen": [32, 64, 96, 104, 112, 120, 128], + "ivLen": [96], + "ivGen": ["external"] + }, + { + "algorithm": "ACVP-AES-GMAC", + "revision": "1.0", + "direction": ["encrypt", "decrypt"], + "keyLen": [128, 192, 256], + "payloadLen": [{ "min": 0, "max": 65536, "increment": 8 }], + "aadLen": [{ "min": 0, "max": 65536, "increment": 8 }], + "tagLen": [32, 64, 96, 104, 112, 120, 128], + "ivLen": [96], + "ivGen": ["external"] + }, + { + "algorithm": "HMAC-SHA-1", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 160, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA2-224", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 224, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA2-256", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 256, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA2-384", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 384, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA2-512", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 512, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA2-512/224", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 224, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA2-512/256", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 256, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA3-224", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 224, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA3-256", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 256, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA3-384", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 384, "increment": 8 }] + }, + { + "algorithm": "HMAC-SHA3-512", + "revision": "1.0", + "keyLen": [{ "min": 8, "max": 524288, "increment": 8 }], + "macLen": [{ "min": 32, "max": 512, "increment": 8 }] + }, + { + "algorithm": "SHAKE-128", + "revision": "1.0", + "inBit": false, + "outBit": false, + "inEmpty": true, + "outputLen": [{ "min": 16, "max": 65536, "increment": 8 }] + }, + { + "algorithm": "SHAKE-256", + "revision": "1.0", + "inBit": false, + "outBit": false, + "inEmpty": true, + "outputLen": [{ "min": 16, "max": 65536, "increment": 8 }] + }, + { + "algorithm": "cSHAKE-128", + "revision": "1.0", + "hexCustomization": false, + "outputLen": [{ "min": 16, "max": 65536, "increment": 8 }], + "msgLen": [{ "min": 0, "max": 65536, "increment": 8 }] + }, + { + "algorithm": "cSHAKE-256", + "revision": "1.0", + "hexCustomization": false, + "outputLen": [{ "min": 16, "max": 65536, "increment": 8 }], + "msgLen": [{ "min": 0, "max": 65536, "increment": 8 }] + }, + { + "algorithm": "PBKDF", + "revision": "1.0", + "capabilities": [{ + "iterationCount": [{ "min": 1, "max": 10000, "increment": 1 }], + "keyLen": [{ "min": 112, "max": 4096, "increment": 8 }], + "passwordLen": [{ "min": 8, "max": 64, "increment": 1 }], + "saltLen": [{ "min": 128, "max": 512, "increment": 8 }], + "hmacAlg": [ + "SHA2-224", "SHA2-256", "SHA2-384", "SHA2-512", + "SHA2-512/224", "SHA2-512/256", + "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512" + ] + }] + }, + { + "algorithm": "hmacDRBG", + "revision": "1.0", + "predResistanceEnabled": [false], + "reseedImplemented": false, + "capabilities": [{ + "mode": "SHA2-224", + "derFuncEnabled": false, + "entropyInputLen": [192], + "nonceLen": [96], + "persoStringLen": [192], + "additionalInputLen": [0], + "returnedBitsLen": 224 + }, { + "mode": "SHA2-256", + "derFuncEnabled": false, + "entropyInputLen": [256], + "nonceLen": [128], + "persoStringLen": [256], + "additionalInputLen": [0], + "returnedBitsLen": 256 + }, { + "mode": "SHA2-384", + "derFuncEnabled": false, + "entropyInputLen": [256], + "nonceLen": [128], + "persoStringLen": [256], + "additionalInputLen": [0], + "returnedBitsLen": 384 + }, { + "mode": "SHA2-512", + "derFuncEnabled": false, + "entropyInputLen": [256], + "nonceLen": [128], + "persoStringLen": [256], + "additionalInputLen": [0], + "returnedBitsLen": 512 + }, { + "mode": "SHA2-512/224", + "derFuncEnabled": false, + "entropyInputLen": [192], + "nonceLen": [96], + "persoStringLen": [192], + "additionalInputLen": [0], + "returnedBitsLen": 224 + }, { + "mode": "SHA2-512/256", + "derFuncEnabled": false, + "entropyInputLen": [256], + "nonceLen": [128], + "persoStringLen": [256], + "additionalInputLen": [0], + "returnedBitsLen": 256 + }, { + "mode": "SHA3-224", + "derFuncEnabled": false, + "entropyInputLen": [192], + "nonceLen": [96], + "persoStringLen": [192], + "additionalInputLen": [0], + "returnedBitsLen": 224 + }, { + "mode": "SHA3-256", + "derFuncEnabled": false, + "entropyInputLen": [256], + "nonceLen": [128], + "persoStringLen": [256], + "additionalInputLen": [0], + "returnedBitsLen": 256 + }, { + "mode": "SHA3-384", + "derFuncEnabled": false, + "entropyInputLen": [256], + "nonceLen": [128], + "persoStringLen": [256], + "additionalInputLen": [0], + "returnedBitsLen": 384 + }, { + "mode": "SHA3-512", + "derFuncEnabled": false, + "entropyInputLen": [256], + "nonceLen": [128], + "persoStringLen": [256], + "additionalInputLen": [0], + "returnedBitsLen": 512 + }] + }, + { + "algorithm": "KDA", + "mode": "HKDF", + "revision": "Sp800-56Cr1", + "fixedInfoPattern": "uPartyInfo||vPartyInfo", + "encoding": ["concatenation"], + "hmacAlg": [ + "SHA2-224", "SHA2-256", "SHA2-384", "SHA2-512", + "SHA2-512/224", "SHA2-512/256", + "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512" + ], + "macSaltMethods": ["default", "random"], + "l": 2048, + "z": [{ "min": 224, "max": 65336, "increment": 8 }] + }, + { + "algorithm": "ctrDRBG", + "revision": "1.0", + "predResistanceEnabled": [false], + "reseedImplemented": true, + "capabilities": [{ + "mode": "AES-256", + "derFuncEnabled": false, + "entropyInputLen": [384], + "nonceLen": [0], + "persoStringLen": [0], + "additionalInputLen": [384], + "returnedBitsLen": 128 + }] + }, + { + "algorithm": "KDA", + "mode": "OneStepNoCounter", + "revision": "Sp800-56Cr2", + "auxFunctions": [ + { "auxFunctionName": "HMAC-SHA2-224", "l": 224, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA2-256", "l": 256, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA2-384", "l": 384, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA2-512", "l": 512, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA2-512/224", "l": 224, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA2-512/256", "l": 256, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA3-224", "l": 224, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA3-256", "l": 256, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA3-384", "l": 384, "macSaltMethods": ["default", "random"] }, + { "auxFunctionName": "HMAC-SHA3-512", "l": 512, "macSaltMethods": ["default", "random"] } + ], + "fixedInfoPattern": "uPartyInfo||vPartyInfo", + "encoding": ["concatenation"], + "z": [{ "min": 224, "max": 65336, "increment": 8 }] + }, + { + "algorithm": "EDDSA", + "mode": "keyGen", + "revision": "1.0", + "curve": ["ED-25519"] + }, + { + "algorithm": "EDDSA", + "mode": "keyVer", + "revision": "1.0", + "curve": ["ED-25519"] + }, + { + "algorithm": "EDDSA", + "mode": "sigGen", + "revision": "1.0", + "pure": true, + "preHash": true, + "contextLength": [{ "min": 0, "max": 255, "increment": 1 }], + "curve": ["ED-25519"] + }, + { + "algorithm": "EDDSA", + "mode": "sigVer", + "revision": "1.0", + "pure": true, + "preHash": true, + "curve": ["ED-25519"] + }, + { + "algorithm": "ECDSA", + "mode": "keyGen", + "revision": "FIPS186-5", + "curve": ["P-224", "P-256", "P-384", "P-521"], + "secretGenerationMode": ["testing candidates"] + }, + { + "algorithm": "ECDSA", + "mode": "keyVer", + "revision": "FIPS186-5", + "curve": ["P-224", "P-256", "P-384", "P-521"] + }, + { + "algorithm": "ECDSA", + "mode": "sigGen", + "revision": "FIPS186-5", + "capabilities": [{ + "curve": ["P-224", "P-256", "P-384", "P-521"], + "hashAlg": ["SHA2-224", "SHA2-256", "SHA2-384", "SHA2-512", "SHA2-512/224", "SHA2-512/256", "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512"] + }] + }, + { + "algorithm": "ECDSA", + "mode": "sigVer", + "revision": "FIPS186-5", + "capabilities": [{ + "curve": ["P-224", "P-256", "P-384", "P-521"], + "hashAlg": ["SHA2-224", "SHA2-256", "SHA2-384", "SHA2-512", "SHA2-512/224", "SHA2-512/256", "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512"] + }] + }, + { + "algorithm": "DetECDSA", + "mode": "sigGen", + "revision": "FIPS186-5", + "capabilities": [{ + "curve": ["P-224", "P-256", "P-384", "P-521"], + "hashAlg": ["SHA2-224", "SHA2-256", "SHA2-384", "SHA2-512", "SHA2-512/224", "SHA2-512/256", "SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512"] + }] + }, + { + "algorithm": "CMAC-AES", + "revision": "1.0", + "capabilities": [{ + "direction": ["gen", "ver"], + "msgLen": [{ "min": 0, "max": 524288, "increment": 8 }], + "keyLen": [128, 256], + "macLen": [128] + }] + }, + { + "algorithm": "TLS-v1.2", + "mode": "KDF", + "revision": "RFC7627", + "hashAlg": ["SHA2-256", "SHA2-384", "SHA2-512"] + }, + { + "algorithm": "TLS-v1.3", + "mode": "KDF", + "revision": "RFC8446", + "hmacAlg": ["SHA2-256", "SHA2-384"], + "runningMode": ["DHE", "PSK", "PSK-DHE"] + }, + { + "algorithm": "kdf-components", + "mode": "ssh", + "revision": "1.0", + "hashAlg": ["SHA2-224", "SHA2-256", "SHA2-384", "SHA2-512"], + "cipher": ["AES-128", "AES-192", "AES-256"] + }, + { + "algorithm": "KAS-ECC-SSC", + "revision": "Sp800-56Ar3", + "scheme": { + "ephemeralUnified": { "kasRole": ["initiator", "responder"] }, + "staticUnified": { "kasRole": ["initiator", "responder"] } + }, + "domainParameterGenerationMethods": ["P-224", "P-256", "P-384", "P-521"] + }, + { + "algorithm": "KDF", + "revision": "1.0", + "capabilities": [{ + "kdfMode": "counter", + "macMode": ["CMAC-AES128", "CMAC-AES192", "CMAC-AES256"], + "supportedLengths": [256], + "fixedDataOrder": ["before fixed data"], + "counterLength": [16] + }, { + "kdfMode": "feedback", + "macMode": ["HMAC-SHA2-224", "HMAC-SHA2-256", "HMAC-SHA2-384", "HMAC-SHA2-512", "HMAC-SHA2-512/224", "HMAC-SHA2-512/256", "HMAC-SHA3-224", "HMAC-SHA3-256", "HMAC-SHA3-384", "HMAC-SHA3-512"], + "customKeyInLength": 0, + "supportedLengths": [{ "min": 8, "max": 4096, "increment": 8 }], + "fixedDataOrder": ["after fixed data"], + "counterLength": [8], + "supportsEmptyIv": true, + "requiresEmptyIv": true + }] + }, + { + "algorithm": "RSA", + "mode": "keyGen", + "revision": "FIPS186-5", + "infoGeneratedByServer": true, + "pubExpMode": "fixed", + "fixedPubExp": "010001", + "keyFormat": "standard", + "capabilities": [{ + "randPQ": "probable", + "properties": [ + { "modulo": 2048, "primeTest": ["2powSecStr"] }, + { "modulo": 3072, "primeTest": ["2powSecStr"] }, + { "modulo": 4096, "primeTest": ["2powSecStr"] } + ] + }] + }, + { + "algorithm": "RSA", + "mode": "sigGen", + "revision": "FIPS186-5", + "capabilities": [{ + "sigType": "pkcs1v1.5", + "properties": [ + { "modulo": 2048, "hashPair": [{ "hashAlg": "SHA2-224" }, { "hashAlg": "SHA2-256" }, { "hashAlg": "SHA2-384" }, { "hashAlg": "SHA2-512" }] }, + { "modulo": 3072, "hashPair": [{ "hashAlg": "SHA2-224" }, { "hashAlg": "SHA2-256" }, { "hashAlg": "SHA2-384" }, { "hashAlg": "SHA2-512" }] }, + { "modulo": 4096, "hashPair": [{ "hashAlg": "SHA2-224" }, { "hashAlg": "SHA2-256" }, { "hashAlg": "SHA2-384" }, { "hashAlg": "SHA2-512" }] } + ] + }, { + "sigType": "pss", + "properties": [ + { "maskFunction": ["mgf1"], "modulo": 2048, "hashPair": [{ "hashAlg": "SHA2-224", "saltLen": 28 }, { "hashAlg": "SHA2-256", "saltLen": 32 }, { "hashAlg": "SHA2-384", "saltLen": 48 }, { "hashAlg": "SHA2-512", "saltLen": 64 }] }, + { "maskFunction": ["mgf1"], "modulo": 3072, "hashPair": [{ "hashAlg": "SHA2-224", "saltLen": 28 }, { "hashAlg": "SHA2-256", "saltLen": 32 }, { "hashAlg": "SHA2-384", "saltLen": 48 }, { "hashAlg": "SHA2-512", "saltLen": 64 }] }, + { "maskFunction": ["mgf1"], "modulo": 4096, "hashPair": [{ "hashAlg": "SHA2-224", "saltLen": 28 }, { "hashAlg": "SHA2-256", "saltLen": 32 }, { "hashAlg": "SHA2-384", "saltLen": 48 }, { "hashAlg": "SHA2-512", "saltLen": 64 }] } + ] + }] + }, + { + "algorithm": "RSA", + "mode": "sigVer", + "revision": "FIPS186-5", + "pubExpMode": "fixed", + "fixedPubExp": "010001", + "capabilities": [{ + "sigType": "pkcs1v1.5", + "properties": [{ "modulo": 2048, "hashPair": [{ "hashAlg": "SHA2-224" }, { "hashAlg": "SHA2-256" }, { "hashAlg": "SHA2-384" }, { "hashAlg": "SHA2-512" }] }] + }, { + "sigType": "pkcs1v1.5", + "properties": [{ "modulo": 3072, "hashPair": [{ "hashAlg": "SHA2-224" }, { "hashAlg": "SHA2-256" }, { "hashAlg": "SHA2-384" }, { "hashAlg": "SHA2-512" }] }] + }, { + "sigType": "pkcs1v1.5", + "properties": [{ "modulo": 4096, "hashPair": [{ "hashAlg": "SHA2-224" }, { "hashAlg": "SHA2-256" }, { "hashAlg": "SHA2-384" }, { "hashAlg": "SHA2-512" }] }] + }, { + "sigType": "pss", + "properties": [{ "maskFunction": ["mgf1"], "modulo": 2048, "hashPair": [{ "hashAlg": "SHA2-224", "saltLen": 28 }, { "hashAlg": "SHA2-256", "saltLen": 32 }, { "hashAlg": "SHA2-384", "saltLen": 48 }, { "hashAlg": "SHA2-512", "saltLen": 64 }] }] + }, { + "sigType": "pss", + "properties": [{ "maskFunction": ["mgf1"], "modulo": 3072, "hashPair": [{ "hashAlg": "SHA2-224", "saltLen": 28 }, { "hashAlg": "SHA2-256", "saltLen": 32 }, { "hashAlg": "SHA2-384", "saltLen": 48 }, { "hashAlg": "SHA2-512", "saltLen": 64 }] }] + }, { + "sigType": "pss", + "properties": [{ "maskFunction": ["mgf1"], "modulo": 4096, "hashPair": [{ "hashAlg": "SHA2-224", "saltLen": 28 }, { "hashAlg": "SHA2-256", "saltLen": 32 }, { "hashAlg": "SHA2-384", "saltLen": 48 }, { "hashAlg": "SHA2-512", "saltLen": 64 }] }] + }] + } +]`) + +var commands = map[string]command{ + "getConfig": { + handler: func(args [][]byte) ([][]byte, error) { + return [][]byte{capabilitiesJSON}, nil + }, + }, + + "SHA-1": cmdHashAFT(sha1.New), + "SHA-1/MCT": cmdHashMCT(sha1.New), + "SHA-1/LDT": cmdHashLDT(sha1.New), + "SHA2-224": cmdHashAFT(sha256.New224), + "SHA2-224/MCT": cmdHashMCT(sha256.New224), + "SHA2-224/LDT": cmdHashLDT(sha256.New224), + "SHA2-256": cmdHashAFT(sha256.New), + "SHA2-256/MCT": cmdHashMCT(sha256.New), + "SHA2-256/LDT": cmdHashLDT(sha256.New), + "SHA2-384": cmdHashAFT(sha512.New384), + "SHA2-384/MCT": cmdHashMCT(sha512.New384), + "SHA2-384/LDT": cmdHashLDT(sha512.New384), + "SHA2-512": cmdHashAFT(sha512.New), + "SHA2-512/MCT": cmdHashMCT(sha512.New), + "SHA2-512/LDT": cmdHashLDT(sha512.New), + "SHA2-512/224": cmdHashAFT(sha512.New512_224), + "SHA2-512/224/MCT": cmdHashMCT(sha512.New512_224), + "SHA2-512/224/LDT": cmdHashLDT(sha512.New512_224), + "SHA2-512/256": cmdHashAFT(sha512.New512_256), + "SHA2-512/256/MCT": cmdHashMCT(sha512.New512_256), + "SHA2-512/256/LDT": cmdHashLDT(sha512.New512_256), + + "SHA3-224": cmdHashAFT(newSHA3224), + "SHA3-224/MCT": cmdSha3MCT(newSHA3224), + "SHA3-224/LDT": cmdHashLDT(newSHA3224), + "SHA3-256": cmdHashAFT(newSHA3256), + "SHA3-256/MCT": cmdSha3MCT(newSHA3256), + "SHA3-256/LDT": cmdHashLDT(newSHA3256), + "SHA3-384": cmdHashAFT(newSHA3384), + "SHA3-384/MCT": cmdSha3MCT(newSHA3384), + "SHA3-384/LDT": cmdHashLDT(newSHA3384), + "SHA3-512": cmdHashAFT(newSHA3512), + "SHA3-512/MCT": cmdSha3MCT(newSHA3512), + "SHA3-512/LDT": cmdHashLDT(newSHA3512), + "SHAKE-128": cmdShakeAFTVOT(sha3.NewSHAKE128), + "SHAKE-128/VOT": cmdShakeAFTVOT( + sha3.NewSHAKE128, + ), + "SHAKE-128/MCT": cmdShakeMCT(sha3.NewSHAKE128), + "SHAKE-256": cmdShakeAFTVOT(sha3.NewSHAKE256), + "SHAKE-256/VOT": cmdShakeAFTVOT(sha3.NewSHAKE256), + "SHAKE-256/MCT": cmdShakeMCT(sha3.NewSHAKE256), + "cSHAKE-128": cmdCShakeAFT(func(N, S []byte) *sha3.SHAKE { + return sha3.NewCSHAKE128(N, S) + }), + "cSHAKE-128/MCT": cmdCShakeMCT(func(N, S []byte) *sha3.SHAKE { + return sha3.NewCSHAKE128(N, S) + }), + "cSHAKE-256": cmdCShakeAFT(func(N, S []byte) *sha3.SHAKE { + return sha3.NewCSHAKE256(N, S) + }), + "cSHAKE-256/MCT": cmdCShakeMCT(func(N, S []byte) *sha3.SHAKE { + return sha3.NewCSHAKE256(N, S) + }), + + "HMAC-SHA2-224": cmdHMAC(sha256.New224), + "HMAC-SHA-1": cmdHMAC(sha1.New), + "HMAC-SHA2-256": cmdHMAC(sha256.New), + "HMAC-SHA2-384": cmdHMAC(sha512.New384), + "HMAC-SHA2-512": cmdHMAC(sha512.New), + "HMAC-SHA2-512/224": cmdHMAC(sha512.New512_224), + "HMAC-SHA2-512/256": cmdHMAC(sha512.New512_256), + "HMAC-SHA2-512-224": cmdHMAC(sha512.New512_224), + "HMAC-SHA2-512-256": cmdHMAC(sha512.New512_256), + "HMAC-SHA3-224": cmdHMAC(newSHA3224), + "HMAC-SHA3-256": cmdHMAC(newSHA3256), + "HMAC-SHA3-384": cmdHMAC(newSHA3384), + "HMAC-SHA3-512": cmdHMAC(newSHA3512), + "HKDF/SHA2-224": cmdHKDFAFT(sha256.New224), + "HKDF/SHA2-256": cmdHKDFAFT(sha256.New), + "HKDF/SHA2-384": cmdHKDFAFT(sha512.New384), + "HKDF/SHA2-512": cmdHKDFAFT(sha512.New), + "HKDF/SHA2-512/224": cmdHKDFAFT(sha512.New512_224), + "HKDF/SHA2-512/256": cmdHKDFAFT(sha512.New512_256), + "HKDF/SHA3-224": cmdHKDFAFT(newSHA3224), + "HKDF/SHA3-256": cmdHKDFAFT(newSHA3256), + "HKDF/SHA3-384": cmdHKDFAFT(newSHA3384), + "HKDF/SHA3-512": cmdHKDFAFT(newSHA3512), + "HKDFExtract/SHA2-256": cmdHKDFExtractAFT(sha256.New), + "HKDFExtract/SHA2-384": cmdHKDFExtractAFT(sha512.New384), + "HKDFExpandLabel/SHA2-256": cmdHKDFExpandLabelAFT(sha256.New), + "HKDFExpandLabel/SHA2-384": cmdHKDFExpandLabelAFT(sha512.New384), + "PBKDF": cmdPBKDF(), + "hmacDRBG/SHA2-224": cmdHMACDRBGAFT(sha256.New224), + "hmacDRBG/SHA2-256": cmdHMACDRBGAFT(sha256.New), + "hmacDRBG/SHA2-384": cmdHMACDRBGAFT(sha512.New384), + "hmacDRBG/SHA2-512": cmdHMACDRBGAFT(sha512.New), + "hmacDRBG/SHA2-512/224": cmdHMACDRBGAFT(sha512.New512_224), + "hmacDRBG/SHA2-512/256": cmdHMACDRBGAFT(sha512.New512_256), + "hmacDRBG/SHA3-224": cmdHMACDRBGAFT(newSHA3224), + "hmacDRBG/SHA3-256": cmdHMACDRBGAFT(newSHA3256), + "hmacDRBG/SHA3-384": cmdHMACDRBGAFT(newSHA3384), + "hmacDRBG/SHA3-512": cmdHMACDRBGAFT(newSHA3512), + "ctrDRBG/AES-256": cmdCTRDRBGAFT(), + "ctrDRBG-reseed/AES-256": cmdCTRDRBGReseedAFT(), + "hmacDRBG-reseed/SHA2-224": cmdHMACDRBGReseed(sha256.New224), + "hmacDRBG-reseed/SHA2-256": cmdHMACDRBGReseed(sha256.New), + "hmacDRBG-reseed/SHA2-384": cmdHMACDRBGReseed(sha512.New384), + "hmacDRBG-reseed/SHA2-512": cmdHMACDRBGReseed(sha512.New), + "hmacDRBG-pr/SHA2-224": cmdHMACDRBGPredictionResistance(sha256.New224), + "hmacDRBG-pr/SHA2-256": cmdHMACDRBGPredictionResistance(sha256.New), + "hmacDRBG-pr/SHA2-384": cmdHMACDRBGPredictionResistance(sha512.New384), + "hmacDRBG-pr/SHA2-512": cmdHMACDRBGPredictionResistance(sha512.New), + + "EDDSA/keyGen": cmdEDDSAKeyGen(), + "EDDSA/keyVer": cmdEDDSAKeyVer(), + "EDDSA/sigGen": cmdEDDSASigGen(), + "EDDSA/sigVer": cmdEDDSASigVer(), + + "ECDSA/keyGen": cmdECDSAKeyGen(), + "ECDSA/keyVer": cmdECDSAKeyVer(), + "ECDSA/sigGen": cmdECDSASigGen(false), + "DetECDSA/sigGen": cmdECDSASigGen(true), + "ECDSA/sigVer": cmdECDSASigVer(), + + "CMAC-AES": cmdCMACAESAFT(), + "CMAC-AES/verify": cmdCMACAESVerifyAFT(), + "KDF-counter": cmdKDFCounter(), + "KDF-feedback": cmdKDFFeedback(), + + "OneStepNoCounter/HMAC-SHA2-224": cmdOneStepNoCounterHMAC(sha256.New224), + "OneStepNoCounter/HMAC-SHA2-256": cmdOneStepNoCounterHMAC(sha256.New), + "OneStepNoCounter/HMAC-SHA2-384": cmdOneStepNoCounterHMAC(sha512.New384), + "OneStepNoCounter/HMAC-SHA2-512": cmdOneStepNoCounterHMAC(sha512.New), + "OneStepNoCounter/HMAC-SHA2-512/224": cmdOneStepNoCounterHMAC(sha512.New512_224), + "OneStepNoCounter/HMAC-SHA2-512/256": cmdOneStepNoCounterHMAC(sha512.New512_256), + "OneStepNoCounter/HMAC-SHA2-512-224": cmdOneStepNoCounterHMAC(sha512.New512_224), + "OneStepNoCounter/HMAC-SHA2-512-256": cmdOneStepNoCounterHMAC(sha512.New512_256), + "OneStepNoCounter/HMAC-SHA3-224": cmdOneStepNoCounterHMAC(newSHA3224), + "OneStepNoCounter/HMAC-SHA3-256": cmdOneStepNoCounterHMAC(newSHA3256), + "OneStepNoCounter/HMAC-SHA3-384": cmdOneStepNoCounterHMAC(newSHA3384), + "OneStepNoCounter/HMAC-SHA3-512": cmdOneStepNoCounterHMAC(newSHA3512), + + "TLSKDF/1.2/SHA2-256": cmdTLSKDF12(sha256.New), + "TLSKDF/1.2/SHA2-384": cmdTLSKDF12(sha512.New384), + "TLSKDF/1.2/SHA2-512": cmdTLSKDF12(sha512.New), + "SSHKDF/SHA2-224/client": cmdSSHKDF(sha256.New224, true), + "SSHKDF/SHA2-224/server": cmdSSHKDF(sha256.New224, false), + "SSHKDF/SHA2-256/client": cmdSSHKDF(sha256.New, true), + "SSHKDF/SHA2-256/server": cmdSSHKDF(sha256.New, false), + "SSHKDF/SHA2-384/client": cmdSSHKDF(sha512.New384, true), + "SSHKDF/SHA2-384/server": cmdSSHKDF(sha512.New384, false), + "SSHKDF/SHA2-512/client": cmdSSHKDF(sha512.New, true), + "SSHKDF/SHA2-512/server": cmdSSHKDF(sha512.New, false), + + "ECDH/P-224": cmdECDH(elliptic.P224()), + "ECDH/P-256": cmdECDH(elliptic.P256()), + "ECDH/P-384": cmdECDH(elliptic.P384()), + "ECDH/P-521": cmdECDH(elliptic.P521()), + + "RSA/keyGen": cmdRSAKeyGen(), + "RSA/sigGen/SHA-1/pkcs1v1.5": cmdRSASigGenByHashName("SHA-1", false), + "RSA/sigGen/SHA2-224/pkcs1v1.5": cmdRSASigGenByHashName("SHA2-224", false), + "RSA/sigGen/SHA2-256/pkcs1v1.5": cmdRSASigGenByHashName("SHA2-256", false), + "RSA/sigGen/SHA2-384/pkcs1v1.5": cmdRSASigGenByHashName("SHA2-384", false), + "RSA/sigGen/SHA2-512/pkcs1v1.5": cmdRSASigGenByHashName("SHA2-512", false), + "RSA/sigGen/SHA2-224/pss": cmdRSASigGenByHashName("SHA2-224", true), + "RSA/sigGen/SHA2-256/pss": cmdRSASigGenByHashName("SHA2-256", true), + "RSA/sigGen/SHA2-384/pss": cmdRSASigGenByHashName("SHA2-384", true), + "RSA/sigGen/SHA2-512/pss": cmdRSASigGenByHashName("SHA2-512", true), + "RSA/sigVer/SHA-1/pkcs1v1.5": cmdRSASigVerByHashName("SHA-1", false), + "RSA/sigVer/SHA2-224/pkcs1v1.5": cmdRSASigVerByHashName("SHA2-224", false), + "RSA/sigVer/SHA2-256/pkcs1v1.5": cmdRSASigVerByHashName("SHA2-256", false), + "RSA/sigVer/SHA2-384/pkcs1v1.5": cmdRSASigVerByHashName("SHA2-384", false), + "RSA/sigVer/SHA2-512/pkcs1v1.5": cmdRSASigVerByHashName("SHA2-512", false), + "RSA/sigVer/SHA2-224/pss": cmdRSASigVerByHashName("SHA2-224", true), + "RSA/sigVer/SHA2-256/pss": cmdRSASigVerByHashName("SHA2-256", true), + "RSA/sigVer/SHA2-384/pss": cmdRSASigVerByHashName("SHA2-384", true), + "RSA/sigVer/SHA2-512/pss": cmdRSASigVerByHashName("SHA2-512", true), + + "AES/encrypt": cmdAESECB(true), + "AES/decrypt": cmdAESECB(false), + "AES-CBC/encrypt": cmdAESCBC(true), + "AES-CBC/decrypt": cmdAESCBC(false), + "AES-CTR/encrypt": cmdAESCTR(), + "AES-CTR/decrypt": cmdAESCTR(), + "AES-GCM/seal": cmdAESGCMSeal(false), + "AES-GCM/open": cmdAESGCMOpen(false), + "AES-GCM-randnonce/seal": cmdAESGCMSeal(true), + "AES-GCM-randnonce/open": cmdAESGCMOpen(true), +} + +func Run(reader io.Reader, writer io.Writer) error { + if !fips140.Enabled() { + return errors.New("acvp must run with GODEBUG=fips140=on (or only)") + } + return processingLoop(bufio.NewReader(reader), writer) +} + +func processingLoop(reader io.Reader, writer io.Writer) error { + return processingLoopWithCommands(reader, writer, commands) +} + +func processingLoopWithCommands(reader io.Reader, writer io.Writer, commandSet map[string]command) error { + for { + req, err := readRequest(reader) + if errors.Is(err, io.EOF) { + return nil + } + if err != nil { + return fmt.Errorf("reading request: %w", err) + } + + cmd, ok := commandSet[req.name] + if !ok { + return fmt.Errorf("unknown command: %q", req.name) + } + if got := len(req.args); got != cmd.requiredArgs { + return fmt.Errorf("command %q expected %d args, got %d", req.name, cmd.requiredArgs, got) + } + + response, err := cmd.handler(req.args) + if err != nil { + return fmt.Errorf("command %q failed: %w", req.name, err) + } + if err := writeResponse(writer, response); err != nil { + return fmt.Errorf("write response for %q: %w", req.name, err) + } + } +} + +func readRequest(reader io.Reader) (*request, error) { + var numArgs uint32 + if err := binary.Read(reader, binary.LittleEndian, &numArgs); err != nil { + return nil, err + } + if numArgs == 0 { + return nil, errors.New("invalid request: zero args") + } + args, err := readArgs(reader, numArgs) + if err != nil { + return nil, err + } + return &request{ + name: string(args[0]), + args: args[1:], + }, nil +} + +func readArgs(reader io.Reader, count uint32) ([][]byte, error) { + lengths := make([]uint32, count) + for i := range lengths { + if err := binary.Read(reader, binary.LittleEndian, &lengths[i]); err != nil { + return nil, fmt.Errorf("read arg length %d: %w", i, err) + } + } + args := make([][]byte, count) + for i, length := range lengths { + buf := make([]byte, length) + if _, err := io.ReadFull(reader, buf); err != nil { + return nil, fmt.Errorf("read arg %d data: %w", i, err) + } + args[i] = buf + } + return args, nil +} + +func writeResponse(writer io.Writer, args [][]byte) error { + numArgs := uint32(len(args)) + if err := binary.Write(writer, binary.LittleEndian, numArgs); err != nil { + return err + } + for i, arg := range args { + if err := binary.Write(writer, binary.LittleEndian, uint32(len(arg))); err != nil { + return fmt.Errorf("write arg length %d: %w", i, err) + } + } + for i, arg := range args { + if _, err := writer.Write(arg); err != nil { + return fmt.Errorf("write arg %d data: %w", i, err) + } + } + return nil +} + +func cmdHashAFT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 1, + handler: func(args [][]byte) ([][]byte, error) { + h := hashFn() + h.Write(args[0]) + return [][]byte{h.Sum(nil)}, nil + }, + } +} + +func cmdHashMCT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 1, + handler: func(args [][]byte) ([][]byte, error) { + h := hashFn() + seed := args[0] + hSize := h.Size() + if len(seed) != hSize { + return nil, fmt.Errorf("seed length %d does not match digest size %d", len(seed), hSize) + } + + buf := make([]byte, 0, hSize*3) + buf = append(buf, seed...) + buf = append(buf, seed...) + buf = append(buf, seed...) + + digest := make([]byte, 0, hSize) + for i := 0; i < 1000; i++ { + h.Reset() + h.Write(buf) + digest = h.Sum(digest[:0]) + copy(buf, buf[hSize:]) + copy(buf[2*hSize:], digest) + } + return [][]byte{buf[2*hSize:]}, nil + }, + } +} + +func cmdSha3MCT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 1, + handler: func(args [][]byte) ([][]byte, error) { + h := hashFn() + digest := args[0] + for i := 0; i < 1000; i++ { + h.Reset() + h.Write(digest) + digest = h.Sum(nil) + } + return [][]byte{digest}, nil + }, + } +} + +func cmdHashLDT(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 2, + handler: func(args [][]byte) ([][]byte, error) { + content := args[0] + if len(args[1]) != 8 { + return nil, fmt.Errorf("invalid repetition count size: %d", len(args[1])) + } + times := binary.LittleEndian.Uint64(args[1]) + h := hashFn() + for i := uint64(0); i < times; i++ { + h.Write(content) + } + return [][]byte{h.Sum(nil)}, nil + }, + } +} + +func cmdHMAC(hashFn func() hash.Hash) command { + return command{ + requiredArgs: 2, + handler: func(args [][]byte) ([][]byte, error) { + msg := args[0] + key := args[1] + mac := hmac.New(hashFn, key) + mac.Write(msg) + return [][]byte{mac.Sum(nil)}, nil + }, + } +} + +func cmdAESECB(encrypt bool) command { + return command{ + requiredArgs: 3, + handler: func(args [][]byte) ([][]byte, error) { + key := args[0] + input := args[1] + if len(input)%aes.BlockSize != 0 { + return nil, fmt.Errorf("input length must be a multiple of %d bytes", aes.BlockSize) + } + iterations, err := parseIterations(args[2]) + if err != nil { + return nil, err + } + + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + result := append([]byte(nil), input...) + prevResult := make([]byte, len(result)) + + for j := uint32(0); j < iterations; j++ { + if j == iterations-1 { + copy(prevResult, result) + } + for i := 0; i < len(result); i += aes.BlockSize { + if encrypt { + block.Encrypt(result[i:i+aes.BlockSize], result[i:i+aes.BlockSize]) + } else { + block.Decrypt(result[i:i+aes.BlockSize], result[i:i+aes.BlockSize]) + } + } + } + + return [][]byte{result, prevResult}, nil + }, + } +} + +func cmdAESCBC(encrypt bool) command { + return command{ + requiredArgs: 4, + handler: func(args [][]byte) ([][]byte, error) { + key := args[0] + input := append([]byte(nil), args[1]...) + iv := append([]byte(nil), args[2]...) + + if len(input) == 0 || len(input)%aes.BlockSize != 0 { + return nil, fmt.Errorf("input length must be a non-zero multiple of %d", aes.BlockSize) + } + if len(iv) != aes.BlockSize { + return nil, fmt.Errorf("iv length must be %d", aes.BlockSize) + } + iterations, err := parseIterations(args[3]) + if err != nil { + return nil, err + } + + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + result := make([]byte, len(input)) + prevResult := make([]byte, len(input)) + prevInput := make([]byte, len(input)) + + for j := uint32(0); j < iterations; j++ { + copy(prevResult, result) + if j > 0 { + if encrypt { + iv = append(iv[:0], result...) + } else { + iv = append(iv[:0], prevInput...) + } + } + + modeIV := make([]byte, aes.BlockSize) + copy(modeIV, iv) + if encrypt { + cipher.NewCBCEncrypter(block, modeIV).CryptBlocks(result, input) + } else { + cipher.NewCBCDecrypter(block, modeIV).CryptBlocks(result, input) + prevInput = append(prevInput[:0], input...) + } + + if j == 0 { + input = append(input[:0], iv...) + } else { + input = append(input[:0], prevResult...) + } + } + + return [][]byte{result, prevResult}, nil + }, + } +} + +func cmdAESCTR() command { + return command{ + requiredArgs: 4, + handler: func(args [][]byte) ([][]byte, error) { + key := args[0] + input := args[1] + counter := append([]byte(nil), args[2]...) + + if len(counter) != aes.BlockSize { + return nil, fmt.Errorf("counter length must be %d", aes.BlockSize) + } + iterations, err := parseIterations(args[3]) + if err != nil { + return nil, err + } + if iterations != 1 { + return nil, errors.New("aes-ctr supports only one iteration") + } + + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + out := make([]byte, len(input)) + cipher.NewCTR(block, counter).XORKeyStream(out, input) + return [][]byte{out}, nil + }, + } +} + +func cmdAESGCMSeal(randNonce bool) command { + return command{ + requiredArgs: 5, + handler: func(args [][]byte) ([][]byte, error) { + tagLen := int(parseU32(args[0])) + key := args[1] + plaintext := args[2] + nonce := append([]byte(nil), args[3]...) + aad := args[4] + + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + if randNonce { + nonce = make([]byte, 12) + if _, err := rand.Read(nonce); err != nil { + return nil, err + } + } + if len(nonce) != 12 { + return nil, fmt.Errorf("invalid nonce size: got %d, need 12", len(nonce)) + } + + var sealed []byte + if tagLen >= 12 && tagLen <= 16 { + gcm, err := cipher.NewGCMWithTagSize(block, tagLen) + if err != nil { + return nil, err + } + sealed = gcm.Seal(nil, nonce, plaintext, aad) + } else if tagLen >= 4 && tagLen < 12 { + // Stdlib only supports 12..16-byte tags. Match acvptool framing by + // generating a 16-byte tag and truncating. + gcm, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } + full := gcm.Seal(nil, nonce, plaintext, aad) + tagStart := len(full) - gcm.Overhead() + sealed = append(append([]byte(nil), full[:tagStart]...), full[tagStart:tagStart+tagLen]...) + } else { + return nil, fmt.Errorf("unsupported GCM tag size: %d", tagLen) + } + if randNonce { + sealed = append(sealed, nonce...) + } + return [][]byte{sealed}, nil + }, + } +} + +func cmdAESGCMOpen(randNonce bool) command { + return command{ + requiredArgs: 5, + handler: func(args [][]byte) ([][]byte, error) { + tagLen := int(parseU32(args[0])) + key := args[1] + ciphertextWithTag := append([]byte(nil), args[2]...) + nonce := append([]byte(nil), args[3]...) + aad := args[4] + if randNonce { + if len(ciphertextWithTag) < 12 { + return [][]byte{{0}, {}}, nil + } + nonce = ciphertextWithTag[len(ciphertextWithTag)-12:] + ciphertextWithTag = ciphertextWithTag[:len(ciphertextWithTag)-12] + } + + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + if len(nonce) != 12 { + return [][]byte{{0}, {}}, nil + } + + if tagLen < 12 || tagLen > 16 { + // Keep wrapper process alive for unsupported tag sizes. + return [][]byte{{0}, {}}, nil + } + + gcm, err := cipher.NewGCMWithTagSize(block, tagLen) + if err != nil { + return nil, err + } + plaintext, err := gcm.Open(nil, nonce, ciphertextWithTag, aad) + if err != nil { + return [][]byte{{0}, {}}, nil + } + return [][]byte{{1}, plaintext}, nil + }, + } +} + +func parseIterations(raw []byte) (uint32, error) { + if len(raw) != 4 { + return 0, fmt.Errorf("invalid iteration size: %d", len(raw)) + } + iterations := binary.LittleEndian.Uint32(raw) + if iterations == 0 || iterations == ^uint32(0) { + return 0, fmt.Errorf("invalid iteration count: %d", iterations) + } + return iterations, nil +} + +func parseU32(raw []byte) uint32 { + if len(raw) < 4 { + padded := make([]byte, 4) + copy(padded, raw) + return binary.LittleEndian.Uint32(padded) + } + return binary.LittleEndian.Uint32(raw[:4]) +} + +func newSHA3224() hash.Hash { + return sha3.New224() +} + +func newSHA3256() hash.Hash { + return sha3.New256() +} + +func newSHA3384() hash.Hash { + return sha3.New384() +} + +func newSHA3512() hash.Hash { + return sha3.New512() +} + +func encodeRequest(name string, args ...[]byte) []byte { + // test helper + total := 4 + 4*(1+len(args)) + len(name) + for _, arg := range args { + total += len(arg) + } + buf := bytes.NewBuffer(make([]byte, 0, total)) + _ = binary.Write(buf, binary.LittleEndian, uint32(1+len(args))) + _ = binary.Write(buf, binary.LittleEndian, uint32(len(name))) + for _, arg := range args { + _ = binary.Write(buf, binary.LittleEndian, uint32(len(arg))) + } + buf.WriteString(name) + for _, arg := range args { + buf.Write(arg) + } + return buf.Bytes() +} diff --git a/pkg/acvpwrapper/wrapper_test.go b/pkg/acvpwrapper/wrapper_test.go new file mode 100644 index 000000000..20c3e6926 --- /dev/null +++ b/pkg/acvpwrapper/wrapper_test.go @@ -0,0 +1,65 @@ +package acvpwrapper + +import ( + "bytes" + "crypto/sha256" + "encoding/binary" + "encoding/hex" + "io" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGetConfig(t *testing.T) { + in := bytes.NewBuffer(encodeRequest("getConfig")) + var out bytes.Buffer + err := processingLoop(in, &out) + require.NoError(t, err) + + resp, err := decodeResponse(&out) + require.NoError(t, err) + require.Len(t, resp, 1) + require.Contains(t, string(resp[0]), `"algorithm": "SHA2-256"`) + require.Contains(t, string(resp[0]), `"algorithm": "ACVP-AES-GCM"`) + require.NotContains(t, string(resp[0]), `"algorithm": "ML-KEM"`) + require.NotContains(t, string(resp[0]), `"algorithm": "ML-DSA"`) +} + +func TestSHA256AFT(t *testing.T) { + msg := []byte("abc") + in := bytes.NewBuffer(encodeRequest("SHA2-256", msg)) + var out bytes.Buffer + + err := processingLoop(in, &out) + require.NoError(t, err) + + resp, err := decodeResponse(&out) + require.NoError(t, err) + require.Len(t, resp, 1) + + sum := sha256.Sum256(msg) + require.Equal(t, hex.EncodeToString(sum[:]), hex.EncodeToString(resp[0])) +} + +func decodeResponse(r io.Reader) ([][]byte, error) { + var count uint32 + if err := binary.Read(r, binary.LittleEndian, &count); err != nil { + return nil, err + } + lengths := make([]uint32, count) + for i := range lengths { + if err := binary.Read(r, binary.LittleEndian, &lengths[i]); err != nil { + return nil, err + } + } + args := make([][]byte, count) + for i, n := range lengths { + buf := make([]byte, n) + if _, err := io.ReadFull(r, buf); err != nil { + return nil, err + } + args[i] = buf + } + return args, nil +} From 01ac729542359580aa7c1d4783ae113e16c30aef Mon Sep 17 00:00:00 2001 From: slach Date: Thu, 14 May 2026 00:37:27 +0500 Subject: [PATCH 2/2] test(testflows): regenerate cli snapshot for new acvp command --- .../clickhouse_backup/tests/snapshots/cli.py.cli.snapshot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testflows/clickhouse_backup/tests/snapshots/cli.py.cli.snapshot b/test/testflows/clickhouse_backup/tests/snapshots/cli.py.cli.snapshot index 2aff71a8d..e7762e843 100644 --- a/test/testflows/clickhouse_backup/tests/snapshots/cli.py.cli.snapshot +++ b/test/testflows/clickhouse_backup/tests/snapshots/cli.py.cli.snapshot @@ -1,6 +1,6 @@ default_config = r"""'[\'general:\', \' remote_storage: none\', \' backups_to_keep_local: 0\', \' backups_to_keep_remote: 0\', \' log_level: info\', \' allow_empty_backups: false\', \' allow_object_disk_streaming: false\', \' use_resumable_state: true\', \' restore_schema_on_cluster: ""\', \' upload_by_part: true\', \' download_by_part: true\', \' restore_database_mapping: {}\', \' restore_table_mapping: {}\', \' retries_on_failure: 3\', \' retries_pause: 5s\', \' retries_jitter: 0\', \' watch_interval: 1h\', \' full_interval: 24h\', \' watch_backup_name_template: shard{shard}-{type}-{time:20060102150405}\', \' sharded_operation_mode: ""\', \' cpu_nice_priority: 15\', \' io_nice_priority: idle\', \' rbac_backup_always: true\', \' rbac_conflict_resolution: recreate\', \' config_backup_always: false\', \' named_collections_backup_always: false\', \' delete_batch_size: 1000\', \' retriesduration: 5s\', \' watchduration: 1h0m0s\', \' fullduration: 24h0m0s\', \'clickhouse:\', \' username: default\', \' password: ""\', \' host: localhost\', \' port: 9000\', \' disk_mapping: {}\', \' skip_tables:\', \' - system.*\', \' - INFORMATION_SCHEMA.*\', \' - information_schema.*\', \' - _temporary_and_external_tables.*\', \' skip_table_engines: []\', \' skip_disks: []\', \' skip_disk_types: []\', \' timeout: 30m\', \' freeze_by_part: false\', \' freeze_by_part_where: ""\', \' use_embedded_backup_restore: false\', \' use_embedded_backup_restore_cluster: ""\', \' embedded_backup_disk: ""\', \' backup_mutations: true\', \' restore_as_attach: false\', \' restore_distributed_cluster: ""\', \' check_parts_columns: true\', \' secure: false\', \' skip_verify: false\', \' sync_replicated_tables: false\', \' log_sql_queries: true\', \' config_dir: /etc/clickhouse-server/\', \' restart_command: exec:systemctl restart clickhouse-server\', \' ignore_not_exists_error_during_freeze: true\', \' check_replicas_before_attach: true\', \' default_replica_path: /clickhouse/tables/{cluster}/{shard}/{database}/{table}\', " default_replica_name: \'{replica}\'", \' tls_key: ""\', \' tls_cert: ""\', \' tls_ca: ""\', \' debug: false\', \' force_rebalance: false\', \'s3:\', \' access_key: ""\', \' secret_key: ""\', \' bucket: ""\', \' endpoint: ""\', \' region: us-east-1\', \' acl: private\', \' assume_role_arn: ""\', \' force_path_style: false\', \' path: ""\', \' object_disk_path: ""\', \' disable_ssl: false\', \' compression_level: 1\', \' compression_format: tar\', \' sse: ""\', \' sse_kms_key_id: ""\', \' sse_customer_algorithm: ""\', \' sse_customer_key: ""\', \' sse_customer_key_md5: ""\', \' sse_kms_encryption_context: ""\', \' disable_cert_verification: false\', \' use_custom_storage_class: false\', \' storage_class: STANDARD\', \' custom_storage_class_map: {}\', \' allow_multipart_download: false\', \' object_labels: {}\', \' request_payer: ""\', \' check_sum_algorithm: ""\', \' request_content_md5: false\', \' retry_mode: standard\', \' chunk_size: 5242880\', \' debug: false\', \'gcs:\', \' credentials_file: ""\', \' credentials_json: ""\', \' credentials_json_encoded: ""\', \' sa_email: ""\', \' embedded_access_key: ""\', \' embedded_secret_key: ""\', \' skip_credentials: false\', \' bucket: ""\', \' path: ""\', \' object_disk_path: ""\', \' compression_level: 1\', \' compression_format: tar\', \' debug: false\', \' force_http: false\', \' endpoint: ""\', \' storage_class: STANDARD\', \' object_labels: {}\', \' custom_storage_class_map: {}\', \' chunk_size: 16777216\', \' encryption_key: ""\', \'cos:\', \' url: ""\', \' timeout: 2m\', \' secret_id: ""\', \' secret_key: ""\', \' path: ""\', \' object_disk_path: ""\', \' compression_format: tar\', \' compression_level: 1\', \' allow_multipart_download: false\', \' debug: false\', \'api:\', \' listen: localhost:7171\', \' enable_metrics: true\', \' enable_pprof: false\', \' username: ""\', \' password: ""\', \' secure: false\', \' certificate_file: ""\', \' private_key_file: ""\', \' ca_cert_file: ""\', \' ca_key_file: ""\', \' create_integration_tables: false\', \' integration_tables_host: ""\', \' allow_parallel: false\', \' complete_resumable_after_restart: true\', \' watch_is_main_process: false\', \'ftp:\', \' address: ""\', \' timeout: 2m\', \' username: ""\', \' password: ""\', \' tls: false\', \' skip_tls_verify: false\', \' path: ""\', \' object_disk_path: ""\', \' compression_format: tar\', \' compression_level: 1\', \' debug: false\', \'sftp:\', \' address: ""\', \' port: 22\', \' username: ""\', \' password: ""\', \' key: ""\', \' path: ""\', \' object_disk_path: ""\', \' compression_format: tar\', \' compression_level: 1\', \' debug: false\', \'azblob:\', \' endpoint_schema: https\', \' endpoint_suffix: core.windows.net\', \' account_name: ""\', \' account_key: ""\', \' sas: ""\', \' use_managed_identity: false\', \' container: ""\', \' assume_container_exists: false\', \' path: ""\', \' object_disk_path: ""\', \' compression_level: 1\', \' compression_format: tar\', \' sse_key: ""\', \' buffer_count: 3\', \' timeout: 4h\', \' debug: false\', \'custom:\', \' upload_command: ""\', \' download_command: ""\', \' list_command: ""\', \' delete_command: ""\', \' command_timeout: 4h\', \' commandtimeoutduration: 4h0m0s\']'""" -help_flag = r"""'NAME:\n clickhouse-backup - Tool for easy backup of ClickHouse with cloud supportUSAGE:\n clickhouse-backup [-t, --tables=.] DESCRIPTION:\n Run as \'root\' or \'clickhouse\' userCOMMANDS:\n tables List of tables, exclude skip_tables\n create Create new backup\n create_remote Create and upload new backup\n upload Upload backup to remote storage\n list List of backups\n download Download backup from remote storage\n restore Create schema and restore data from backup\n restore_remote Download and restore\n delete Delete specific backup\n default-config Print default config\n print-config Print current config merged with environment variables\n clean Remove data in \'shadow\' folder from all \'path\' folders available from \'system.disks\'\n clean_remote_broken Remove all broken remote backups\n clean_local_broken Remove all broken local backups\n watch Run infinite loop which create full + incremental backup sequence to allow efficient backup sequences\n server Run API server\n help, h Shows a list of commands or help for one commandGLOBAL OPTIONS:\n --config value, -c value Config \'FILE\' name. (default: "/etc/clickhouse-backup/config.yml") [$CLICKHOUSE_BACKUP_CONFIG]\n --environment-override value, --env value override any environment variable via CLI parameter\n --help, -h show help\n --version, -v print the version'""" +help_flag = r"""'NAME:\n clickhouse-backup - Tool for easy backup of ClickHouse with cloud supportUSAGE:\n clickhouse-backup [-t, --tables=.
] DESCRIPTION:\n Run as \'root\' or \'clickhouse\' userCOMMANDS:\n tables List of tables, exclude skip_tables\n create Create new backup\n create_remote Create and upload new backup\n upload Upload backup to remote storage\n list List of backups\n download Download backup from remote storage\n restore Create schema and restore data from backup\n restore_remote Download and restore\n delete Delete specific backup\n default-config Print default config\n print-config Print current config merged with environment variables\n clean Remove data in \'shadow\' folder from all \'path\' folders available from \'system.disks\'\n clean_remote_broken Remove all broken remote backups\n clean_local_broken Remove all broken local backups\n watch Run infinite loop which create full + incremental backup sequence to allow efficient backup sequences\n acvp Run ACVP wrapper protocol over stdin/stdout\n server Run API server\n help, h Shows a list of commands or help for one commandGLOBAL OPTIONS:\n --config value, -c value Config \'FILE\' name. (default: "/etc/clickhouse-backup/config.yml") [$CLICKHOUSE_BACKUP_CONFIG]\n --environment-override value, --env value override any environment variable via CLI parameter\n --help, -h show help\n --version, -v print the version'""" -cli_usage = r"""'NAME:\n clickhouse-backup - Tool for easy backup of ClickHouse with cloud supportUSAGE:\n clickhouse-backup [-t, --tables=.
] DESCRIPTION:\n Run as \'root\' or \'clickhouse\' userCOMMANDS:\n tables List of tables, exclude skip_tables\n create Create new backup\n create_remote Create and upload new backup\n upload Upload backup to remote storage\n list List of backups\n download Download backup from remote storage\n restore Create schema and restore data from backup\n restore_remote Download and restore\n delete Delete specific backup\n default-config Print default config\n print-config Print current config merged with environment variables\n clean Remove data in \'shadow\' folder from all \'path\' folders available from \'system.disks\'\n clean_remote_broken Remove all broken remote backups\n clean_local_broken Remove all broken local backups\n watch Run infinite loop which create full + incremental backup sequence to allow efficient backup sequences\n server Run API server\n help, h Shows a list of commands or help for one commandGLOBAL OPTIONS:\n --config value, -c value Config \'FILE\' name. (default: "/etc/clickhouse-backup/config.yml") [$CLICKHOUSE_BACKUP_CONFIG]\n --environment-override value, --env value override any environment variable via CLI parameter\n --help, -h show help\n --version, -v print the version'""" +cli_usage = r"""'NAME:\n clickhouse-backup - Tool for easy backup of ClickHouse with cloud supportUSAGE:\n clickhouse-backup [-t, --tables=.
] DESCRIPTION:\n Run as \'root\' or \'clickhouse\' userCOMMANDS:\n tables List of tables, exclude skip_tables\n create Create new backup\n create_remote Create and upload new backup\n upload Upload backup to remote storage\n list List of backups\n download Download backup from remote storage\n restore Create schema and restore data from backup\n restore_remote Download and restore\n delete Delete specific backup\n default-config Print default config\n print-config Print current config merged with environment variables\n clean Remove data in \'shadow\' folder from all \'path\' folders available from \'system.disks\'\n clean_remote_broken Remove all broken remote backups\n clean_local_broken Remove all broken local backups\n watch Run infinite loop which create full + incremental backup sequence to allow efficient backup sequences\n acvp Run ACVP wrapper protocol over stdin/stdout\n server Run API server\n help, h Shows a list of commands or help for one commandGLOBAL OPTIONS:\n --config value, -c value Config \'FILE\' name. (default: "/etc/clickhouse-backup/config.yml") [$CLICKHOUSE_BACKUP_CONFIG]\n --environment-override value, --env value override any environment variable via CLI parameter\n --help, -h show help\n --version, -v print the version'"""